diff --git a/3D_Object_Detection/Object_Tracking/img/CA.png b/3D_Object_Detection/Object_Tracking/img/CA.png new file mode 100644 index 00000000..20ca3859 Binary files /dev/null and b/3D_Object_Detection/Object_Tracking/img/CA.png differ diff --git a/3D_Object_Detection/Object_Tracking/img/abt.png b/3D_Object_Detection/Object_Tracking/img/abt.png new file mode 100644 index 00000000..024ff2a9 Binary files /dev/null and b/3D_Object_Detection/Object_Tracking/img/abt.png differ diff --git a/3D_Object_Detection/Object_Tracking/img/affine.png b/3D_Object_Detection/Object_Tracking/img/affine.png new file mode 100644 index 00000000..feb82501 Binary files /dev/null and b/3D_Object_Detection/Object_Tracking/img/affine.png differ diff --git a/3D_Object_Detection/Object_Tracking/img/da.png b/3D_Object_Detection/Object_Tracking/img/da.png new file mode 100644 index 00000000..67124c8c Binary files /dev/null and b/3D_Object_Detection/Object_Tracking/img/da.png differ diff --git a/3D_Object_Detection/Object_Tracking/img/e2.png b/3D_Object_Detection/Object_Tracking/img/e2.png new file mode 100644 index 00000000..7fd42ce6 Binary files /dev/null and b/3D_Object_Detection/Object_Tracking/img/e2.png differ diff --git a/3D_Object_Detection/Object_Tracking/img/eucli.png b/3D_Object_Detection/Object_Tracking/img/eucli.png new file mode 100644 index 00000000..b098449b Binary files /dev/null and b/3D_Object_Detection/Object_Tracking/img/eucli.png differ diff --git a/3D_Object_Detection/Object_Tracking/img/mht.png b/3D_Object_Detection/Object_Tracking/img/mht.png new file mode 100644 index 00000000..159fa47b Binary files /dev/null and b/3D_Object_Detection/Object_Tracking/img/mht.png differ diff --git a/3D_Object_Detection/Object_Tracking/img/mtt.png b/3D_Object_Detection/Object_Tracking/img/mtt.png new file mode 100644 index 00000000..470baff5 Binary files /dev/null and b/3D_Object_Detection/Object_Tracking/img/mtt.png differ diff --git a/3D_Object_Detection/Object_Tracking/img/pro.png b/3D_Object_Detection/Object_Tracking/img/pro.png new file mode 100644 index 00000000..481e37f9 Binary files /dev/null and b/3D_Object_Detection/Object_Tracking/img/pro.png differ diff --git a/3D_Object_Detection/Object_Tracking/img/rotation.png b/3D_Object_Detection/Object_Tracking/img/rotation.png new file mode 100644 index 00000000..451aef47 Binary files /dev/null and b/3D_Object_Detection/Object_Tracking/img/rotation.png differ diff --git a/3D_Object_Detection/Object_Tracking/img/s2d.png b/3D_Object_Detection/Object_Tracking/img/s2d.png new file mode 100644 index 00000000..f64c60c7 Binary files /dev/null and b/3D_Object_Detection/Object_Tracking/img/s2d.png differ diff --git a/3D_Object_Detection/Object_Tracking/img/scale.png b/3D_Object_Detection/Object_Tracking/img/scale.png new file mode 100644 index 00000000..b82a7278 Binary files /dev/null and b/3D_Object_Detection/Object_Tracking/img/scale.png differ diff --git a/3D_Object_Detection/Object_Tracking/img/sim.png b/3D_Object_Detection/Object_Tracking/img/sim.png new file mode 100644 index 00000000..8e286a8d Binary files /dev/null and b/3D_Object_Detection/Object_Tracking/img/sim.png differ diff --git a/3D_Object_Detection/Object_Tracking/img/translation.png b/3D_Object_Detection/Object_Tracking/img/translation.png new file mode 100644 index 00000000..b6305da6 Binary files /dev/null and b/3D_Object_Detection/Object_Tracking/img/translation.png differ diff --git a/3D_Object_Detection/Object_Tracking/pf_socker/genfilename.m b/3D_Object_Detection/Object_Tracking/pf_socker/genfilename.m new file mode 100644 index 00000000..e3cbc847 --- /dev/null +++ b/3D_Object_Detection/Object_Tracking/pf_socker/genfilename.m @@ -0,0 +1,7 @@ +%function fname = genfilename(sequencestruct, framenumber) +function fname = genfilename(sequencestruct, framenumber) +digstr = sprintf('%%0%dd',sequencestruct.digits); +filstr = sprintf('%%s%s%%s',digstr); +fname = sprintf(filstr,sequencestruct.prefix,framenumber,sequencestruct.postfix); +return + diff --git a/3D_Object_Detection/Object_Tracking/pf_socker/readme.md b/3D_Object_Detection/Object_Tracking/pf_socker/readme.md new file mode 100644 index 00000000..85e57c14 --- /dev/null +++ b/3D_Object_Detection/Object_Tracking/pf_socker/readme.md @@ -0,0 +1 @@ +# 足球视频 粒子滤波跟踪 matlab diff --git a/3D_Object_Detection/Object_Tracking/pf_socker/resampindex.m b/3D_Object_Detection/Object_Tracking/pf_socker/resampindex.m new file mode 100644 index 00000000..5cddef97 --- /dev/null +++ b/3D_Object_Detection/Object_Tracking/pf_socker/resampindex.m @@ -0,0 +1,33 @@ + + +function indices = resampindex(weights) + +weights = max(0,weights); +weights = weights/sum(weights); +N = length(weights); +cumprob=[0 cumsum(weights)]; +indices = zeros(1,N); + +if (0) +%usual version where each sample drawn randomly +uni=rand(1,N); +for j=1:N + ind=find((uni>cumprob(j)) & (uni<=cumprob(j+1))); + indices(ind)=j; +end +return +end + +%more efficient version where one random sample seeds +%a deterministically methodical sampling by 1/N +i=1; +u1 = rand(1)/N; +for j=1:N + uj = u1 + (j-1)/N; + while (uj > cumprob(i)) + i=i+1; + end + indices(j) = (i-1); +end +return + diff --git a/3D_Object_Detection/Object_Tracking/pf_socker/samplePFcode.m b/3D_Object_Detection/Object_Tracking/pf_socker/samplePFcode.m new file mode 100644 index 00000000..8f9510ae --- /dev/null +++ b/3D_Object_Detection/Object_Tracking/pf_socker/samplePFcode.m @@ -0,0 +1,152 @@ +%Sample particle filter code to get you started +%This is a very simple, no-frills implementation. +%Bob Collins, + +% 粒子滤波跟踪 + +%As observations, we will use the ground truth bounding +%box information provided with the VS-PETS soccer dataset +%to simulate a (very accurate) person detector. +%observations + +% 目标边框数据 glound trouth +% www.cse.psu.edu/~rcollins/CSE598B/Datasets/soccerboxes.mat +% 视频数据 +% www.cse.psu.edu/~rcollins/CSE598B/Datasets/Soccer.zip +% 背景 +% www.cse.psu.edu/~rcollins/CSE598B/Datasets/soccerbgimage.mat +% 介绍 +% http://www.cse.psu.edu/~rtc12/CSE598C/Chap2ParticlesDAF.pdf +load soccerboxes.mat + +%each box is stored as one row of allboxes +%there are 6 columns +% col1 : frame number this box comes from +% col2 : object identifier this box comes from +% col3 : x coord (matlab col) of box center +% col4 : y coord (matlab row) of box center +% col5 : width of box +% col6 : height of box + +%prepare sequence structure for genfilename.m +startframe = min(allboxes(:,1)); +endframe = max(allboxes(:,1)); +prefix = 'Soccer/Frame'; +postfix = '.jpg'; +sequence = struct('prefix',prefix,'postfix',postfix,'digits',4,'startframe',startframe,'endframe',endframe) + +%initialize by choosing a subsequence and one person to track +fstart = startframe; +fend = endframe; +fend = fstart+100; %I just want to run for a 100 frames for now, to demonstrate +fnum = fstart; + +%get image frame and draw it +fname = genfilename(sequence,fnum) +imrgb = imread(fname); +figure(1); imagesc(imrgb); + +%find all boxes in frame number fnum and draw each one on image +inds = find(allboxes(:,1)==fnum); +hold on +for iii=1:length(inds) + box = allboxes(inds(iii),:); + objnum = box(2); + col0 = box(3); + row0 = box(4); + dcol = box(5)/2.0; + drow = box(6)/2.0; + h = plot(col0+[-dcol dcol dcol -dcol -dcol],row0+[-drow -drow drow drow -drow],'y-'); + set(h,'LineWidth',2); +end +hold off +drawnow + +%intialize prior by clicking mouse near center of person +%you want to track +[x0,y0] = ginput(1); + +%number of particles for particle filtering +nsamples = 100; +%prior distribution will be gaussian +priorsigmax = 10; +priorsigmay = 10; +%generate particles from prior distribution +sampx = x0 + priorsigmax*randn(1,nsamples); +sampy = y0 + priorsigmay*randn(1,nsamples); +weights = ones(1,nsamples)/nsamples; +%plot particles +figure(1); imagesc(imrgb); hold on +plot(sampx,sampy,'b.'); +hold off; drawnow; + +%now start tracking +deltaframe = 2; %set to 1 for every frame +for fnum = (fstart+deltaframe): deltaframe : fend + %get image frame and draw it + fname = genfilename(sequence,fnum) + imrgb = imread(fname); + figure(1); imagesc(imrgb); + %find all boxes in frame number fnum + inds = find(allboxes(:,1)==fnum); + + %do motion prediction step of Bayes filtering + %we will use a deterministic motion model plus + %additive gaussian noise. + %we are using simple constant position model + %as a simple demonstration; it would be better + %to use constant velocity. + motpredsigmax = 10; + motpredsigmay = 10; + predx = sampx + motpredsigmax*randn(1,nsamples); + predy = sampy + motpredsigmay*randn(1,nsamples); + + %compute weights based on likelihood + %recall weights should be oldweight * likelihood + %but all old weights are equal, so new weight will + %just be the likelihood. + %For measuring likelihood, we are using a mixture + %model (parzen estimate) based on the locations of + %the ground truth bounding boxes Note that this is + %a semiparametric, multimodal distribtion + obssigmax = 5; + obssigmay = 5; + + %there surely must be a more efficient way to do the + %following as a vectorized computation rather than + %a loop, but I want to just get it right the first time + weights = ones(1,nsamples); + for i=1:nsamples + prob = 0; + x = predx(i); y=predy(i); + for iii=1:length(inds) + box = allboxes(inds(iii),:); + midx = box(3); %centroid of box + midy = box(4); + dx = midx-x; dy = midy-y; + p = exp(- 0.5 *(dx^2 / obssigmax^2 + dy^2 / obssigmay^2)); + prob = prob + p; + end + weights(i) = prob + end + + %resample particles according to likelihood weights + %the resulting samples will then have equal weight + + % 重采样================================== + indices = resampindex(weights); + sampx = predx(indices); + sampy = predy(indices); + %plot resampled particles + %jitter with a little noise so multiple copies can be seen + figure(1); imagesc(imrgb); hold on + plot(sampx+1*randn(1,nsamples),sampy+1*randn(1,nsamples),'b.'); + drawnow + +end + + + + + + diff --git a/3D_Object_Detection/Object_Tracking/pf_socker/soccerboxesusage.m b/3D_Object_Detection/Object_Tracking/pf_socker/soccerboxesusage.m new file mode 100644 index 00000000..d5926513 --- /dev/null +++ b/3D_Object_Detection/Object_Tracking/pf_socker/soccerboxesusage.m @@ -0,0 +1,79 @@ +%sample code to show how to read and interpret the ground truth boxes +%from the soccer sequence (VS-PETS2003). + +%load in all boxes, it will be in variable allboxes +load soccerboxes.mat + + +%each box is stored as one row of allboxes +%there are 6 columns +% col1 : frame number this box comes from +% col2 : object identifier this box comes from +% col3 : x coord (matlab col) of box center +% col4 : y coord (matlab row) of box center +% col5 : width of box +% col6 : height of box + + +%=========================================================== +%example usage: draw all boxes overlaid on frame number 10 +startframe = min(allboxes(:,1)); +endframe = max(allboxes(:,1)); +prefix = 'Soccer/Frame'; +postfix = '.jpg'; +sequence = struct('prefix',prefix,'postfix',postfix,'digits',4,'startframe',startframe,'endframe',endframe) + +%frame number +fnum = 10; + +%get image frame and draw it +fname = genfilename(sequence,fnum) +imrgb = imread(fname); +figure(1); imagesc(imrgb); + +%find all boxes in frame number fnum and draw each one on image +inds = find(allboxes(:,1)==fnum); +hold on +for iii=1:length(inds) + box = allboxes(inds(iii),:); + objnum = box(2); + col0 = box(3); + row0 = box(4); + dcol = box(5)/2.0; + drow = box(6)/2.0; + h = plot(col0+[-dcol dcol dcol -dcol -dcol],row0+[-drow -drow drow drow -drow],'y-'); + set(h,'LineWidth',2); +end +hold off +drawnow + + +%=========================================================== +%example usage: doing background subtraction on frame number 10 + +%load precomputed background image into bgimage +load soccerbgimage.mat +bgimage = double(bgimage); + +prefix = 'Soccer/Frame'; +postfix = '.jpg'; +sequence = struct('prefix',prefix,'postfix',postfix,'digits',4,'startframe',startframe,'endframe',endframe) + +%frame number +fnum = 10; + +%get image frame and draw it +fname = genfilename(sequence,fnum) +imrgb = imread(fname); + +%do background subtraction and thresholding +bgthresh = 30; +rgbabsdiff = abs(double(imrgb)-bgimage); +maxdiff = max(rgbabsdiff,[],3); %max diff in red green or blue +bgmask = roicolor(maxdiff,bgthresh,Inf); + +%display +figure(2); colormap(gray); +imagesc(bgmask); +drawnow + diff --git a/3D_Object_Detection/Object_Tracking/readme.md b/3D_Object_Detection/Object_Tracking/readme.md index b92b8b64..46a2ca7d 100644 --- a/3D_Object_Detection/Object_Tracking/readme.md +++ b/3D_Object_Detection/Object_Tracking/readme.md @@ -5,14 +5,30 @@ Augmented Reality 增强现实 Motion Capture 运动捕捉 Surveillance 监控 - Sports Analysis 运动(足球、篮球...)分析 + Sports Analysis 运动(足球、篮球...)分析 + 动物行为分析 ... # 目录 1. 运动估计/光流 Mption Estimation / optical Flow 2. 单目标跟踪 Single Object Tracking 3. 多目标跟踪 Multiple Object Trackink + 个体之间的差异性 几何信息约束、不相容约束 + +# 运动假设 + constant position (+ noise) 恒定位置(+噪声 高斯噪声、非高斯噪声) + constant velocity 速度恒定 + constant acceleration 加速度恒定 + 多目标运动之间的关联性 + +![](https://github.com/Ewenwan/MVision/blob/master/3D_Object_Detection/Object_Tracking/img/mtt.png) ## 1. 运动估计/光流 + +[光流简介](http://vision.middlebury.edu/flow/floweval-ijcv2011.pdf) + +[光流法总结](https://zhuanlan.zhihu.com/p/35392023) + + ![](https://github.com/Ewenwan/MVision/blob/master/3D_Object_Detection/Object_Tracking/img/mf.PNG) 3D运动 投影到 2D图像平面上 @@ -26,6 +42,68 @@ (1)亮度恒定,前后帧观测到的对应点的灰度值一样。 (2)时间连续或者运动位移小。 (3)空间一致性:邻近点有相似运动,同一子图像的像素点具有相同的运动。 + + 光流(optic flow)是什么呢?名字很专业,感觉很陌生,但本质上,我们是最熟悉不过的了。 + 因为这种视觉现象我们每天都在经历。从本质上说,光流就是你在这个运动着的世界里感觉到的明显的 + 视觉运动(呵呵,相对论,没有绝对的静止,也没有绝对的运动)。 + 例如,当你坐在火车上,然后往窗外看。你可以看到树、地面、建筑等等,他们都在往后退。 + 这个运动就是光流。而且,我们都会发现,他们的运动速度居然不一样? + 这就给我们提供了一个挺有意思的信息:通过不同目标的运动速度判断它们与我们的距离。 + 一些比较远的目标,例如云、山,它们移动很慢,感觉就像静止一样。 + 但一些离得比较近的物体,例如建筑和树,就比较快的往后退,然后离我们的距离越近,它们往后退的速度越快。 + 一些非常近的物体,例如路面的标记啊,草地啊等等,快到好像在我们耳旁发出嗖嗖的声音。 + + 光流除了提供远近外,还可以提供角度信息。与咱们的眼睛正对着的方向成90度方向运动的物体速度要比其他角度的快, + 当小到0度的时候,也就是物体朝着我们的方向直接撞过来,我们就是感受不到它的运动(光流)了, + 看起来好像是静止的。当它离我们越近,就越来越大(当然了,我们平时看到感觉还是有速度的, + 因为物体较大,它的边缘还是和我们人眼具有大于0的角度的)。 + + 光流的概念是Gibson在1950年首先提出来的。它是空间运动物体在观察成像平面上的像素运动的瞬时速度, + 是利用图像序列中像素在时间域上的变化以及相邻帧之间的相关性来找到上一帧跟当前帧之间存在的对应关系, + 从而计算出相邻帧之间物体的运动信息的一种方法。一般而言,光流是由于场景中前景目标本身的移动 + 、相机的运动,或者两者的共同运动所产生的。 + + 当人的眼睛观察运动物体时,物体的景象在人眼的视网膜上形成一系列连续变化的图像, + 这一系列连续变化的信息不断“流过”视网膜(即图像平面),好像一种光的“流”, + 故称之为光流(optical flow)。光流表达了图像的变化,由于它包含了目标运动的信息, + 因此可被观察者用来确定目标的运动情况。 + 研究光流场的目的就是为了从图片序列中近似得到不能直接得到的运动场。运动场, + 其实就是物体在三维真实世界中的运动;光流场,是运动场在二维图像平面上(人的眼睛或者摄像头)的投影。 + + 那通俗的讲就是通过一个图片序列,把每张图像中每个像素的运动速度和运动方向找出来就是光流场。 + 那怎么找呢?咱们直观理解肯定是:第t帧的时候A点的位置是(x1, y1),那么我们在第t+1帧的时候再找到A点, + 假如它的位置是(x2,y2),那么我们就可以确定A点的运动了: + (Vx, Vy) = (x2, y2) - (x1,y1)。 + Barron等人对多种光流计算技术进行了总结,按照理论基础与数学方法的区别把它们分成四种: + 基于梯度的方法、 + 基于匹配的方法、 + 基于能量的方法、 + 基于相位的方法。 + 近年来神经动力学方法也颇受学者重视。 + + OpenCV中实现了不少的光流算法。 + 1)calcOpticalFlowPyrLK + 通过金字塔Lucas-Kanade 光流方法计算某些点集的光流(稀疏光流)。 + 理解的话,可以参考这篇论文: + ”Pyramidal Implementation of + the Lucas Kanade Feature TrackerDescription of the algorithm” + 2)calcOpticalFlowFarneback + 用Gunnar Farneback 的算法计算稠密光流(即图像上所有像素点的光流都计算出来)。 + 它的相关论文是:"Two-Frame Motion Estimation Based on PolynomialExpansion" + 3)CalcOpticalFlowBM + 通过块匹配的方法来计算光流。 + 4)CalcOpticalFlowHS + 用Horn-Schunck 的算法计算稠密光流。相关论文好像是这篇:”Determining Optical Flow” + 5)calcOpticalFlowSF + 这一个是2012年欧洲视觉会议的一篇文章的实现: + "SimpleFlow: A Non-iterative, Sublinear Optical FlowAlgorithm", + 工程网站是:http://graphics.berkeley.edu/papers/Tao-SAN-2012-05/ + 在OpenCV新版本中有引入。 + + + + + ### 传统算法求光流 klt Kanade-Lucas-Tomasi Feature Tracker [OPENCV光流源码分析](https://blog.csdn.net/ironyoung/article/details/60884929) @@ -112,20 +190,75 @@ - 目标视觉跟踪(visual object tracking),根据目标的跟踪方式,跟踪一般可以分为两大类: - a. 生产(generative)模型方法 - b. 判别(discriminative)模型方法。 - - 生成类方法 在当前帧对目标区域建模,下一帧寻找与模型最相似的区域就是预测位置, - 如卡尔曼滤波(Kalman Filter),粒子滤波(Particle Filter),均值漂移算法(Mean Shift)等。 +# 目标视觉跟踪(visual object tracking),根据目标的跟踪方式,分为 + a. 生产(generative)模型方法 Appearance-Based Tracking + b. 判别(discriminative)模型方法 + c. 相关滤波 + d. 深度学习方法 - 目前比较流行的是判别类方法(Discriminative Tracking),也叫跟踪检测(tracking-by-detection), +## a. 生成类方法 Appearance-Based Tracking + +![](https://github.com/Ewenwan/MVision/blob/master/3D_Object_Detection/Object_Tracking/img/abt.png) + + 在当前帧对目标区域建模,下一帧寻找与模型最相似的区域就是预测位置, + 如卡尔曼滤波(Kalman Filter),贝叶斯滤波Bayes filter + + 采样的方法:粒子滤波(Particle Filter), + + Appearance-Based Tracking 均值漂移算法(Mean Shift)、LK光流等。 + + http://www.cse.psu.edu/~rtc12/CSE598C/meanshiftIntro.pdf + + + + 当前帧+上一帧的位置 + + >>>> 响应图(置信图、概率图) Response map >>> current location + 外观模型/颜色、边缘、强度直方图 confidence map; likelihood image + Mode-Seeking 模式搜索 + Mean Shift、KF、PF + finding discriminative features + 找到最具区别性的特征 + +## b. 目前比较流行的是判别类方法(Discriminative Tracking) + 也叫跟踪检测(tracking-by-detection), 当前帧以目标区域为正样本,背景区域为负样本用来训练分类器, 下一帧用训练好的分类器找最优区域,经典的判别类方法有Struck和TLD等。 - 最近几年相关滤波方法(Correlation Filter Tracking)如MOSSE, CF,KCF/DCF,CN,DSST也比较火。 - MOSSE算法开启了相关滤波器的大门,提出以滤波器求相关的形式来获取输出响应,进而获得最大响应处的位置也即我们期望跟踪的目标中心位置。 - CF,KCF/DCF,三者都是核相关滤波方法,引入核函数使高维空间中的非线性问题变为线性问题从而加速训练和检测, + 分类器 跟踪 + http://www.cse.psu.edu/~rtc12/CSE598C/classificationTracking.pdf + + +## c. 相关滤波方法 +[参考](http://www.cse.psu.edu/~rtc12/CSE598C/LKintro.pdf) + + 目标框f(x,y) 和 搜索框g(x,y) 之间的相关性 + 1. 需要一个相关性评价准则 相关性函数 SSD 差平方和 ssd = sum(f(x,y)-g(x,y))^2 块匹配 零均值处理 + ssd = sum(f(x,y)-g(x,y))^2 = + sum( f^2 + g^2 - 2*f()*g()) = sum(f^2) + sum(g^2) - 2*Correlation_func + + Correlation_func = sum(f(x,y)g(x,y)) 零均值处理 + 交叉相关/互相关 cross-correlation + + 强度归一化 + f‘ = (f - fmean)/ f标准差 + g' = (g - gmean)/ g标准差 + + 带窗函数的 SSD + ssd = sum(W(x,y)*(f(x,y)-g(x,y))^2) + W(x,y) 权值窗口, 高斯窗函数 + + 一阶泰勒展开: + ssd = sum(W(x,y)*(u×fx + v*fy + f(x,y)-g(x,y))^2) + + + 2. 搜索策略,穷举搜索 exhaustive search + + + 最近几年 相关滤波方法(Correlation Filter Tracking)如MOSSE, CF,KCF/DCF,CN,DSST也比较火。 + MOSSE算法开启了相关滤波器的大门,提出以滤波器求相关的形式来获取输出响应, + 进而获得最大响应处的位置也即我们期望跟踪的目标中心位置。 + CF,KCF/DCF,三者都是核相关滤波方法, + 引入核函数使高维空间中的非线性问题变为线性问题从而加速训练和检测, 利用循环矩阵增加训练样本,利用DFT的性质避免求逆操作提高跟踪速度。 CSK利用图像的灰度信息,高斯滤波和1倍padding; KCF利用HOG特征,高斯滤波和1.5倍padding, @@ -147,11 +280,58 @@ SRDCF在KCF/DCF的基础上通过多尺度搜索解决了多尺度问题,并且加入惩罚项来解决循环矩阵的边界效应。 在空间权重函数中加入惩罚权重w,超过边界的w更大作为惩罚;在检测时选择一定的候选框进行尺度匹配,找到最合适的尺度大小。 - 深度学习方法: - +## d. 深度学习方法: + +## 多目标跟踪 +[数据关联,特征匹配、哪个目标加入到轨迹内、kf预测、2d框交并比、](http://www.cse.psu.edu/~rtc12/CSE598C/datassocPart1.pdf) + +[comboptBlockICM](http://www.cse.psu.edu/~rtc12/CSE598C/comboptBlockICM.pdf) + + +![](https://github.com/Ewenwan/MVision/blob/master/3D_Object_Detection/Object_Tracking/img/mht.png) + +![](https://github.com/Ewenwan/MVision/blob/master/3D_Object_Detection/Object_Tracking/img/da.png) + +# 通常目标跟踪主要面临的难点有: + 外观变化,光照变化,快速运动,运动模糊,背景干扰等。 - 通常目标跟踪主要面临的难点有: - 外观变化,光照变化,快速运动,运动模糊,背景干扰等。 - +# 目标状态 观测有噪声,状态估计问题 + e.g.: [x y] (location 位置) + [x y dx dy] (location + velocity 位置+速度) + [x,y,θ,scale] + [x y appearance_params] (location + appearance 位置+样貌) + + + + +# 2d变换总结 平移 缩放 欧式变换 相似变换 仿射变换 投影变换 +> 平移变换 方向+...不变 + +![](https://github.com/Ewenwan/MVision/blob/master/3D_Object_Detection/Object_Tracking/img/translation.png) +> 缩放变换 方向+...不变 长度变化 + +![](https://github.com/Ewenwan/MVision/blob/master/3D_Object_Detection/Object_Tracking/img/scale.png) +> 欧式变换 长度+...不变 + +![](https://github.com/Ewenwan/MVision/blob/master/3D_Object_Detection/Object_Tracking/img/eucli.png) +![](https://github.com/Ewenwan/MVision/blob/master/3D_Object_Detection/Object_Tracking/img/e2.png) +> 相似变换 角度+...不变 + +![](https://github.com/Ewenwan/MVision/blob/master/3D_Object_Detection/Object_Tracking/img/sim.png) + +> 仿射变换 平行+...不变 + +![](https://github.com/Ewenwan/MVision/blob/master/3D_Object_Detection/Object_Tracking/img/affine.png) + +> 投影变换 直线性+...不变 + +![](https://github.com/Ewenwan/MVision/blob/master/3D_Object_Detection/Object_Tracking/img/pro.png) + +> 黎曼几何 直线变曲线 + + + + + diff --git a/3D_Object_Detection/Object_Tracking/src/CMakeLists.txt b/3D_Object_Detection/Object_Tracking/src/CMakeLists.txt new file mode 100644 index 00000000..8353ec03 --- /dev/null +++ b/3D_Object_Detection/Object_Tracking/src/CMakeLists.txt @@ -0,0 +1,15 @@ +# CMake版本限制 +cmake_minimum_required(VERSION 2.8) +# 工程名字 +project( DisplayImage ) +# 找opencv +find_package( OpenCV REQUIRED ) +# 包含opencv +include_directories( ${OpenCV_INCLUDE_DIRS} ) + + +add_executable( single_tracker single_tracker.cpp ) +target_link_libraries( single_tracker ${OpenCV_LIBS} ) + +add_executable( opticalFlow opticalFlow.cpp) +target_link_libraries( opticalFlow ${OpenCV_LIBS} ) diff --git a/3D_Object_Detection/Object_Tracking/src/multitracker.cpp b/3D_Object_Detection/Object_Tracking/src/multitracker.cpp new file mode 100644 index 00000000..5334f4bc --- /dev/null +++ b/3D_Object_Detection/Object_Tracking/src/multitracker.cpp @@ -0,0 +1,93 @@ +/*---------------------------------------------- + * Usage: + * example_tracking_multitracker [algorithm] + * + * example: + * example_tracking_multitracker Bolt/img/%04d.jpg + * example_tracking_multitracker faceocc2.webm KCF + *--------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace cv; + +int main( int argc, char** argv ){ + // set the default tracking algorithm + std::string trackingAlg = "KCF"; +// 跟踪器的创建可选以下几种,代表使用的跟踪算法; +// MIL +// BOOSTING +// MEDIANFLOW +// TLD +// KCF + // set the tracking algorithm from parameter + if(argc>2) + trackingAlg = argv[2]; + // create the tracker + //! [create] + MultiTracker trackers(trackingAlg); + //! [create] + + // container of the tracked objects + //! [roi] + vector objects;// 多目标 + //! [roi] + + // set input video + std::string video = argv[1]; + VideoCapture cap(video); + + Mat frame; + + // get bounding box + cap >> frame; + //! [selectmulti] + selectROI("tracker",frame,objects); + //! [selectmulti] + + //quit when the tracked object(s) is not provided + if(objects.size()<1) + return 0; + + // initialize the tracker + //! [init] + trackers.add(frame,objects); + //! [init] + + // do the tracking + printf("Start the tracking process, press ESC to quit.\n"); + for ( ;; ) + { + // get frame from the video + cap >> frame; + + // stop the program if no more images + if(frame.rows==0 || frame.cols==0) + break; + + //update the tracking result + //! [update] + trackers.update(frame);// 获得跟踪结果 + //! [update] + + //! [result] + // draw the tracked object + for(unsigned i=0;i +#include "opencv2/opencv.hpp" +using namespace cv; +using namespace std; +#define UNKNOWN_FLOW_THRESH 1e9 // 光流最大值 1000000000 + +// 孟塞尔颜色系统=========== +// Color encoding of flow vectors from: +// http://members.shaw.ca/quadibloc/other/colint.htm +// This code is modified from: +// http://vision.middlebury.edu/flow/data/ +void makecolorwheel(vector &colorwheel) +{ +// 红(R)、红黄(YR)、黄(Y)、黄绿(GY)、绿(G)、绿蓝(BG)、蓝(B)、蓝紫(PB)、紫(P)、紫红(RP)。 + int RY = 15; + int YG = 6; + int GC = 4; + int CB = 11; + int BM = 13; + int MR = 6; + int i; + for (i = 0; i < RY; i++) + colorwheel.push_back(Scalar(255, 255*i/RY, 0)); + for (i = 0; i < YG; i++) + colorwheel.push_back(Scalar(255-255*i/YG, 255, 0)); + for (i = 0; i < GC; i++) + colorwheel.push_back(Scalar(0, 255, 255*i/GC)); + for (i = 0; i < CB; i++) + colorwheel.push_back(Scalar(0, 255-255*i/CB, 255)); + for (i = 0; i < BM; i++) + colorwheel.push_back(Scalar(255*i/BM, 0, 255)); + for (i = 0; i < MR; i++) + colorwheel.push_back(Scalar(255, 0, 255-255*i/MR)); +} + +// 输入的flow 没一点包含两个值,水平光流 和 垂直光流 +// 输出的 color, 包含3个值,光流转换成的 r,g,b +void motionToColor(Mat flow, Mat &color) +{ +// 彩色光流图3通道============ +if (color.empty()) + color.create(flow.rows, flow.cols, CV_8UC3); + +static vector colorwheel; //Scalar r,g,b +if (colorwheel.empty()) + makecolorwheel(colorwheel); + +// determine motion range +float maxrad = -1; // 综合光流最大值 +// 找到最大的光流值,来归一化 水平和垂直光流=========================== +// Find max flow to normalize fx and fy +for (int i= 0; i < flow.rows; ++i) +{ + for (int j = 0; j < flow.cols; ++j) + { + Vec2f flow_at_point = flow.at(i, j);// 光流值 + float fx = flow_at_point[0]; // 水平光流 + float fy = flow_at_point[1]; // 垂直光流 + // 值过大 就不符合 + if ((fabs(fx) > UNKNOWN_FLOW_THRESH) || (fabs(fy) > UNKNOWN_FLOW_THRESH)) + continue; + // 计算综合光流,两直角边得到 斜边 + float rad = sqrt(fx * fx + fy * fy); + maxrad = maxrad > rad ? maxrad : rad;// 保留最大 综合光流 + } +} + + cout << "max flow: " << maxrad << endl; // 打印一下 最大 综合光流值 + +// 这个flow颜色可视化分成这么几步: +// 1) 对flow归一化后,算出它的极坐标 (angle, radius) +//2) 将angle 映射到色调(hue), 将radius 映射到色度(saturation)。 +// 这里共分了55个色调 +for (int i= 0; i < flow.rows; ++i) // 行 +{ + for (int j = 0; j < flow.cols; ++j) // 列 + { + uchar *data = color.data + color.step[0] * i + color.step[1] * j; // rgb图 + Vec2f flow_at_point = flow.at(i, j); + + + + float tep = sqrt(flow_at_point[0] * flow_at_point[0] + flow_at_point[1] * flow_at_point[1]); + if(tep < 4.0) // 剔除过小的 光流值 + { + data[0] = data[1] = data[2] = 0; + continue; // 光流太大,假 + } + + // 使用最大 综合光流 来归一化 水平和垂直光流 ====== + float fx = flow_at_point[0] / maxrad; + float fy = flow_at_point[1] / maxrad; +// 这里有问题,fx,fy已经归一化了 + if ((fabs(fx) > UNKNOWN_FLOW_THRESH) || (fabs(fy) > UNKNOWN_FLOW_THRESH)) + { + data[0] = data[1] = data[2] = 0; + continue; // 光流太大,假 + } + float rad = sqrt(fx * fx + fy * fy); // 综合光流 赋值 + float angle = atan2(-fy, -fx) / CV_PI; // 综合光流 方向 + + float fk = (angle + 1.0) / 2.0 * (colorwheel.size()-1);// 角度选 颜色轮子 + int k0 = (int)fk; + + int k1 = (k0 + 1) % colorwheel.size(); + float f = fk - k0; + //f = 0; // uncomment to see original color wheel + for (int b = 0; b < 3; b++) + { + float col0 = colorwheel[k0][b] / 255.0; + float col1 = colorwheel[k1][b] / 255.0; + float col = (1 - f) * col0 + f * col1; + if (rad <= 1) + col = 1 - rad * (1 - col); // increase saturation with radius + else + col *= .75; // out of range + data[2 - b] = (int)(255.0 * col); + } + } + } +} + +int main(int, char**) +{ + VideoCapture cap; cap.open(0); + //cap.open("test_02.wmv"); + if( !cap.isOpened() ) + return -1; + Mat prevgray, gray, flow, flow2, cflow, frame, frameSrc; + + //namedWindow("flow", 1); + + Mat motion2color,motion2color2 ; + //cap >> frameSrc; + + // 动/静mask===== + Mat mask; + + for(;;) + { + double t = (double)cvGetTickCount(); + cap >> frameSrc; + mask = cv::Mat::zeros(frameSrc.rows,frameSrc.cols,CV_8U);// 默认0; +// 下采样一下 加快速度====================== 速度 ×3 ================== + pyrDown(frameSrc, frame, Size(frameSrc.cols / 2, frameSrc.rows / 2)); +// ==================================================================================== + + cvtColor(frame, gray, CV_BGR2GRAY); // 转成灰度 + //imshow("original", frame); + if( prevgray.data ) + { + +// CalcOpticalFlowFarneback()函数是利用用Gunnar Farneback的算法, +// 计算全局性的稠密光流算法(即图像上所有像素点的光流都计算出来), +// 由于要计算图像上所有点的光流,故计算耗时,速度慢。 +// 参数说明如下: +// _prev0:输入前一帧图像 +// _next0:输入后一帧图像 +// _flow0:输出的光流 +// pyr_scale:金字塔上下两层之间的尺度关系 +// levels:金字塔层数 +// winsize:均值窗口大小,越大越能denoise并且能够检测快速移动目标,但会引起模糊运动区域 +// iterations:迭代次数 + // poly_n:像素领域大小,一般为5,7等 +// poly_sigma:高斯标注差,一般为1-1.5 +// flags:计算方法。主要包括 OPTFLOW_USE_INITIAL_FLOW 和 OPTFLOW_FARNEBACK_GAUSSIAN + + calcOpticalFlowFarneback(prevgray, gray, flow, 0.5, 3, 15, 3, 5, 1.2, 0); + // motionToColor(flow, motion2color); // 运动图转换到 色彩图 + +// 上采样 ====== + // pyrUp(motion2color, motion2color2, Size(motion2color.cols * 2, motion2color.rows * 2)); + // imshow("flow", motion2color2); + + pyrUp(flow, flow2, Size(flow.cols * 2, flow.rows * 2)); + + /* + // 显示光流方线段===================================== + for(int y=0; y(y, x); + const Point2f flowatxy = xy*10;// 光流值放大10倍 + + float tep = sqrt(xy.x * xy.x + xy.y * xy.y); + if(tep < 4.0) // 剔除过小的 光流值 + continue; // 光流太大,假 + line(frame, Point(x,y), + Point(cvRound(x+flowatxy.x), cvRound(y+flowatxy.y)), + Scalar(255, 0, 0));// 起点到 终点 画线 + circle(frame, Point(x,y), 1, Scalar(0,0,0), -1); // 起点 + } + } + imshow("original", frame); + */ + + // 显示光流方线段===================================== + for(int y=0; y(y, x); + float tep = sqrt(xy.x * xy.x + xy.y * xy.y); + if(tep < 4.0) // 剔除过小的 光流值 + continue; // 光流太大,假 + + mask.at(y,x) = 255; + + const Point2f flowatxy = xy*10;// 光流值放大10倍 + /*line(frameSrc, Point(x,y), + Point(cvRound(x+flowatxy.x), cvRound(y+flowatxy.y)), + Scalar(255, 0, 0));// 起点到 终点 画线 + circle(frameSrc, Point(x,y), 1, Scalar(0,0,0), -1); // 起点 + */ + } + } + //imshow("original", frameSrc); + // 膨胀,选大的 + int dilation_size = 10;// 膨胀核大小=== + cv::Mat kernel = getStructuringElement(cv::MORPH_ELLIPSE, + cv::Size( 2*dilation_size + 1, 2*dilation_size+1 ), + cv::Point( dilation_size, dilation_size ) ); + cv::dilate(mask, mask, kernel);// 膨胀,15×15核内 选最大的 + cv::dilate(mask, mask, kernel);// 膨胀,15×15核内 选最大的 + cv::dilate(mask, mask, kernel);// 膨胀,15×15核内 选最大的 + cv::erode(mask, mask, kernel);// 腐蚀 + imshow("mask", mask); + + } + + + if(waitKey(10)>=0) break; + std::swap(prevgray, gray); // 更新上一帧灰度图 + t = (double)cvGetTickCount() - t; + cout << "cost time: " << t / ((double)cvGetTickFrequency()*1000.) << endl; + } + return 0; +} + + + + + diff --git a/3D_Object_Detection/Object_Tracking/src/readme.md b/3D_Object_Detection/Object_Tracking/src/readme.md new file mode 100644 index 00000000..26d735ce --- /dev/null +++ b/3D_Object_Detection/Object_Tracking/src/readme.md @@ -0,0 +1 @@ +# 光流 跟踪 diff --git a/3D_Object_Detection/Object_Tracking/src/single_tracker.cpp b/3D_Object_Detection/Object_Tracking/src/single_tracker.cpp new file mode 100644 index 00000000..56623f68 --- /dev/null +++ b/3D_Object_Detection/Object_Tracking/src/single_tracker.cpp @@ -0,0 +1,112 @@ +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace cv; + +int main( int argc, char** argv ) +{ + // show help + //! [help] + //! [help] + + // declares all required variables + //! [vars] + Rect2d roi; + Mat frame; + //! [vars] + + // create a tracker object + //! [create] + Ptr tracker = Tracker::create( "KCF" ); + //! [create] +// 跟踪器的创建可选以下几种,代表使用的跟踪算法; +// MIL +// BOOSTING +// MEDIANFLOW +// TLD +// KCF + + // set input video + //! [setvideo] + // std::string video = argv[1]; + VideoCapture cap(0);// 打开摄像头 + //! [setvideo] + if( !cap.isOpened() ) + { + printf("打开摄像头失败\r\n"); + return -1; + } + int track_flag_ok=0; + // get bounding box + //! [getframe] + cap.read(frame);// 读取第一帧=============== + cout<< frame.size() << endl; + //cap >> frame; + //! [getframe] + //! [selectroi] + roi=selectROI("tracker",frame);// 选取目标框============ + //! [selectroi] + + //quit if ROI was not selected + if(roi.width==0 || roi.height==0) + return 0; + + // initialize the tracker + //! [init] + tracker->init(frame,roi);// 初始化 目标框=================== + //! [init] + track_flag_ok=1; + // perform the tracking process + printf("Start the tracking process, press ESC to quit.\n"); + //for ( ;; ){ + while(cap.read(frame)) + { + // get frame from the video + // cap >> frame; + if(!track_flag_ok) + { + roi=selectROI("tracker",frame);// 选取目标框============ + tracker->init(frame,roi);// 初始化 目标框=================== + track_flag_ok=1; + } + // stop the program if no more images + if(frame.rows==0 || frame.cols==0) + break; + + // update the tracking result + //! [update] + int flag_t = tracker->update(frame,roi);// 获得跟踪结果 + // cout<< flag_t << endl; // 发现不了跟踪失败 + //! [update] + + //! [visualization] + // draw the tracked object + + if ( ((roi.x+roi.width/2)<0) || ((roi.x+roi.width/2)>640) || + ((roi.y+roi.height/2)<0) || ((roi.y+roi.height/2)>480) + ) + { + printf("lost.\n"); + track_flag_ok=0; + continue; + } + + rectangle( frame, roi, Scalar( 255, 0, 0 ), 2, 1 );// 绘制目标跟踪结果 + // cout<< roi.x << "\t "<< roi.y << "\t "< 3d检测跟踪 利用光流+ransac 进行目标跟踪 +![](https://github.com/Ewenwan/MVision/blob/master/3D_Object_Detection/img/dynamic.png) + +![](https://github.com/Ewenwan/MVision/blob/master/3D_Object_Detection/img/3dtrack.jpg) + + # 2D Object Detection 2D目标检测 [现代卷积目标检测器 速度/精度调研](https://arxiv.org/pdf/1611.10012.pdf) @@ -138,8 +155,6 @@ [Computer-vision dataset tools that I am using or working on 轨迹处理 误差分析](https://github.com/Ewenwan/dataset-tools) -# ElasticFusion -[代码](https://github.com/Ewenwan/ElasticFusion) # KinectFusion KinectFusion在世界坐标系中定义了一个立方体,并把该立方体按照一定的分辨率切割成小立方体(voxel)。 @@ -153,6 +168,40 @@ 这种方法通常被称为基于体数据的方法(Volumetric-based method)。 该方法的核心思想是,通过不断更新并“融合”(fusion)TSDF这种类型的测量值, 我们能够 越来越接近所需要的真实值。 + + + KinectFusion是微软研究院的一个项目,研究用Kinect来实时地重构3D表面,最终用于人机交互。 + +[其他团队实现](https://github.com/Ewenwan/kfusion) + +[TSDF算法](https://blog.csdn.net/qq_40213457/article/details/82383621) + + 首次实现基于 RGB-D 的实时三位重建 + + 步骤: + 1. 2D深度图(双边滤波+三角变换(需要相机内参数))转换成3D点云,并计算 没一个3D点的法向量 + 2. ICP算法迭代求当前帧2相机位姿 + a. 对每个像素点用投影算法计算匹配点。 + b. 最小化匹配点重投影点坐标误差到 平面的距离 + 迭代 + 3. 根据相机位姿将点云融合到全局三维模型(TSDF模型,3d网格)中 + 网格中的数值代表距离重建场景表面的距离,网格中从正值到负值的穿越点连接线表示重建的表面 + 4. 光线投影算法求当前视角下能够看到的场景表面 + +# ElasticFusion +[代码](https://github.com/Ewenwan/ElasticFusion) + + +# BundleFusion + 2017年斯坦福大学提出的BundleFusion算法,可以说是目前基于RGB-D相机进行稠密三维重建效果最好的方法了。 +[代码](https://github.com/Ewenwan/BundleFusion) + + 它通过slam获取相机的位置信息,关键帧等等,如果是稠密的,那就是每一帧图像都参与融合, + 要是基于关键帧就直接融合关键帧,融合的方式采用bundlefuison 的 integrate 和 deintegrate. + 其中对于实时三维重构要想能在slam获得回环后把位置经过修正的帧重新融合必须有deintegrate功能。 + 笔者真心认为bundlefusion是三维实时重构的里程碑,是最完善的 + + 用 加操作(integration) 和 减操作(de-integration) 的方式解决位姿优化后重建场景更新的问题。 # 车辆3D检测:Deep MANTA 一个针对单目图像联合2D-3D车辆检测的粗到精的多任务网络 diff --git "a/3D_Object_Detection/\346\267\261\345\272\246\345\233\276\350\241\245\345\205\250.md" "b/3D_Object_Detection/\346\267\261\345\272\246\345\233\276\350\241\245\345\205\250.md" new file mode 100644 index 00000000..b0ac3b32 --- /dev/null +++ "b/3D_Object_Detection/\346\267\261\345\272\246\345\233\276\350\241\245\345\205\250.md" @@ -0,0 +1,36 @@ +# 深度图补全 +[参考](https://www.zhihu.com/search?type=content&q=%20ElasticFusion) + +[代码](https://github.com/Ewenwan/DeepCompletionRelease) + +# 深度图补全 深度图修补 化妆 美颜 + + 虽然RGB-D相机前景无限,但是受制于物理硬件的限制,目前深度相机输出的depth图还有很多问题, + 比如对于光滑物体表面反射、半/透明物体、深色物体、超出量程等都会造成深度图缺失。 + 而且很多深度相机是大片的深度值缺失,这对于算法工程师来说非常头疼。 + 因此,深度图补全一直是一个非常有用的研究方向, + 之前的文献大都只能补全比较小范围的深度缺失,对于较大深度值缺失的情况无能无力。 + +# 2018 CVPR 最新的一项研究deep depth completion + 不受RGB-D相机类型的限制,只需要输入一张RGB加一张depth图,可以补全任意形式深度图的缺失。 + 对于算法工程师来说真的是喜大普奔啊,目前主要针对的是室内环境。 + +# 什么原理? +![](https://pic4.zhimg.com/v2-f2d2fdaaf8a063236bf9418291fee227_b.jpg) + + Deep depth completion算法流程如下, + 其输入是RGB-D相机拍摄的一张RGB图像和对应的深度图, + 然后根据分别训练好的两个网络(一个是针对RGB图表面法线的深度学习网络,一个是针对物体边缘遮挡的深度学习网络), + 预测该彩色图像中所有平面的表面法线和物体边缘遮挡。 + 最后用深度图作为正则化,求解一个全局线性优化问题,最终得到补全的深度图。 + +# 数据集准备 +![](https://pic3.zhimg.com/v2-e704bafc1a016437142c6b9a71f132aa_b.jpg) + + 他们利用现有的消费级RGB-D相机拍摄的数据集(Matterport3D、ScanNet、SUN3D、SceneNN)先进行稠密的三维重建,然后再进行优化和渲染。 + 虽然单一视角的深度图可能会有因为不同原因引起的缺失,但是经过多个不同视角的重建和优化,这些缺失的地方都被填补了。 + 然后将其深度结果反投影回到输入深度图。最后得到的深度图就是groundtruth啦,简直完美! + 省时省力省钱,还顺带学习了稠密三维重建,就是这么棒!看看下面的图, + 还是比较形象的,黄色代表不同视点的图,红色是当前视点渲染后的深度图。 + + diff --git a/CNN/Action_Recognition/IDT/IDT/src/readme.md b/CNN/Action_Recognition/IDT/IDT/src/readme.md index 386f11af..6232a99a 100644 --- a/CNN/Action_Recognition/IDT/IDT/src/readme.md +++ b/CNN/Action_Recognition/IDT/IDT/src/readme.md @@ -1 +1,87 @@ # 源文件 + + iDT代码的依赖包括两个库: + OpenCV: readme中推荐用2.4.2, 实际上用最新的2.4.13也没问题。 + 但OpenCV3就不知道能不能用了,没有试过。 + ffmpeg: readme中推荐用0.11.1。实际上装最新的版本也没有问题 + 这两个库的安装教程网上很多,就不再多做介绍了。 + 而且也都是很常用的库。 + 在安装完以上两个库后,就可以进行代码编译了。 + 只需要在代码文件夹下make一下就好, + 编译好的可执行文件在./release/下。 + 使用时输入 视频文件的路径作为参数即可 + ./release/DenseTrackStab ./test_sequences/person01_boxing_d1_uncomp.avi。 + 代码结构 + iDT代码中主要包括如下几个代码文件 + DenseTrackStab.cpp: iDT算法主程序 + DenseTrackStab.h: 轨迹跟踪的一些参数,以及一些数据结构体的定义 + Descriptors.h: 特征相关的各种函数 + Initialize.h: 初始化相关的各种函数 + OpticalFlow.h: 光流相关的各种函数 + Video.cpp: 这个程序与iDT算法无关, + 只是作者提供用来测试两个依赖库是否安装成功的。 + + bound box相关内容 + bound box即提供视频帧中人体框的信息, + 在计算前后帧的投影变换矩阵时,不使用人体框中的匹配点对。 + 从而排除人体运动干扰,使得对相机运动的估计更加准确。 + 作者提供的文件中没有bb_file的格式, + 代码中也没有读入bb_file的接口, + 若需要用到需要在代码中添加一条读入文件语句 + (下面的代码解析中已经添加)。 + bb_file的格式如下所示 + frame_id a1 a2 a3 a4 a5 b1 b2 b3 b4 b5 + 其中frame_id是帧的编号,从0开始。 + 代码中还有检查步骤,保证bb_file的长度与视频的帧数相同。 + 后面的数据5个一组,为人体框的参数。 + 按顺序分别为: + 框左上角点的x,框左上角点的y,框右下角点的x,框右下角点的y,置信度。 + 需要注意的是虽然要输入置信度, + 但实际上这个置信度在代码里也没有用上的样子, + 所以取任意值也不影响使用。 + 因为一帧图像可能框出来的人有好多个, + 这种细粒度的控制比大致框出一个范围能更有效地滤去噪声. + 至于如何获得这些bound box的数据,最暴力的方法当然是手工标注,不过这样太辛苦了。 + 在项目中我们采用了SSD(single shot multibox detector)/yolov3算法检测人体框的位置。算法检测人体框的位置。 + 主程序代码解析 + iDT算法代码的大致思路为: + 1. 读入新的一帧 + 2. 通过SURF特征和光流计算当前帧和上一帧的投影变换矩阵 + 3. 使用求得的投影变换矩阵对当前帧进行warp变换,消除相机运动影响 + 4. 利用warp变换后的当前帧图像和上一帧图像计算光流 + 5. 在各个图像尺度上跟踪轨迹并计算特征 + 6. 保存当前帧的相关信息,跳到1 + 几个头文件: + DenseTrackStab.h 定义了Track等的数据结构。最重要的track类里面可以看出: + std::vector point; //轨迹点 + std::vector disp; //偏移点 + std::vector hog; //hog特征 + std::vector hof; //hof特征 + std::vector mbhX; //mbhX特征 + std::vector mbhY; //mbhY特征 + int index;// 序号 + 基本方法就是在重采样中提取轨迹, + 在轨迹空间中再提取hog,hof,mbh特征, + 这些特征组合形成iDT特征, + 最终作为这个动作的描述。 + Initialize.h:涉及各种数据结构的初始化,usage()可以看看; + OpticalFlow.h: 主要用了Farneback计算光流, + 博客参考: + https://blog.csdn.net/ironyoung/article/details/60884929 + 光流源码: + https://searchcode.com/file/30099587/opencv_source/src/cv/cvoptflowgf.cpp + 把金字塔的方法也写进去了, + 金字塔方法主要是为了消除不同尺寸的影响, + 让描述子有更好的泛化能力。 + Descriptors.h:提供一些工具函数: + 计算直方图描述子 + 计算梯度直方图 + 计算光流直方图 + 计算光流梯度直方图 + 密集采样轨迹点 DenseSample + 载入 人体边框数据 + 创建去除人体区域的mask掩膜 + 对帧图进行单应矩阵反变换 去除相机移动的影响 + BFMatcher 计算匹配点对 + 合并光流匹配点对和 surf匹配点对 + 根据光流得到光流匹配点 diff --git a/CNN/Action_Recognition/readme.md b/CNN/Action_Recognition/readme.md index b743f4e5..57479d09 100644 --- a/CNN/Action_Recognition/readme.md +++ b/CNN/Action_Recognition/readme.md @@ -166,7 +166,17 @@ a. 使用SURF特征算法匹配前后两帧的 匹配点对,这里会使用人体检测,剔除人体区域的匹配点,运动量大,影响较大; b. 利用光流算法计算匹配点对,剔除人体区域的匹配点对; c. 合并SURF匹配点对 和 光流匹配点对,利用RANSAC 随机采样序列一致性算法估计前后两帧的 单应投影变换矩阵H; + d. 利用矩阵H的逆矩阵,计算得到当前帧除去相机运动的状态I’= H.inv * I ; + 如果已知 两帧 T=[R,t] 变换 + Ik = K *P + Ik+1 = K *T*P + K逆 * Ik = T逆 *K逆 * Ik+1 + + I’ = K * T逆 *K逆 * I + + + e. 计算去除相机运动后的帧I' 的 光流。 f. 光流算法 Ft 假设1:光照亮度恒定: diff --git a/CNN/AttentionNet/img/a1j.jpg b/CNN/AttentionNet/img/a1j.jpg new file mode 100644 index 00000000..c207c2cd Binary files /dev/null and b/CNN/AttentionNet/img/a1j.jpg differ diff --git a/CNN/AttentionNet/img/a2j.jpg b/CNN/AttentionNet/img/a2j.jpg new file mode 100644 index 00000000..35440710 Binary files /dev/null and b/CNN/AttentionNet/img/a2j.jpg differ diff --git a/CNN/AttentionNet/img/a3j.jpg b/CNN/AttentionNet/img/a3j.jpg new file mode 100644 index 00000000..b93246b2 Binary files /dev/null and b/CNN/AttentionNet/img/a3j.jpg differ diff --git a/CNN/AttentionNet/img/ilovechina.jpg b/CNN/AttentionNet/img/ilovechina.jpg new file mode 100644 index 00000000..602c7a65 Binary files /dev/null and b/CNN/AttentionNet/img/ilovechina.jpg differ diff --git a/CNN/AttentionNet/img/readme.md b/CNN/AttentionNet/img/readme.md new file mode 100644 index 00000000..82d8c33b --- /dev/null +++ b/CNN/AttentionNet/img/readme.md @@ -0,0 +1 @@ +# 相关图片 diff --git a/CNN/AttentionNet/img/rnn-s2s-decoder-attention.jpg b/CNN/AttentionNet/img/rnn-s2s-decoder-attention.jpg new file mode 100644 index 00000000..0166dcf8 Binary files /dev/null and b/CNN/AttentionNet/img/rnn-s2s-decoder-attention.jpg differ diff --git a/CNN/AttentionNet/img/rnn-s2s-decoder.jpg b/CNN/AttentionNet/img/rnn-s2s-decoder.jpg new file mode 100644 index 00000000..614ee0d4 Binary files /dev/null and b/CNN/AttentionNet/img/rnn-s2s-decoder.jpg differ diff --git a/CNN/AttentionNet/img/rnn-s2s-decoder2.jpg b/CNN/AttentionNet/img/rnn-s2s-decoder2.jpg new file mode 100644 index 00000000..9ab176bb Binary files /dev/null and b/CNN/AttentionNet/img/rnn-s2s-decoder2.jpg differ diff --git a/CNN/AttentionNet/img/rnn-s2s-encoder.jpg b/CNN/AttentionNet/img/rnn-s2s-encoder.jpg new file mode 100644 index 00000000..f1f4696a Binary files /dev/null and b/CNN/AttentionNet/img/rnn-s2s-encoder.jpg differ diff --git a/CNN/AttentionNet/img/rnn_1.jpg b/CNN/AttentionNet/img/rnn_1.jpg new file mode 100644 index 00000000..caa59035 Binary files /dev/null and b/CNN/AttentionNet/img/rnn_1.jpg differ diff --git a/CNN/AttentionNet/img/rnn_1_n.jpg b/CNN/AttentionNet/img/rnn_1_n.jpg new file mode 100644 index 00000000..c715b0d2 Binary files /dev/null and b/CNN/AttentionNet/img/rnn_1_n.jpg differ diff --git a/CNN/AttentionNet/img/rnn_1n_n.jpg b/CNN/AttentionNet/img/rnn_1n_n.jpg new file mode 100644 index 00000000..f08bd84f Binary files /dev/null and b/CNN/AttentionNet/img/rnn_1n_n.jpg differ diff --git a/CNN/AttentionNet/img/rnn_2.jpg b/CNN/AttentionNet/img/rnn_2.jpg new file mode 100644 index 00000000..30ba7ba4 Binary files /dev/null and b/CNN/AttentionNet/img/rnn_2.jpg differ diff --git a/CNN/AttentionNet/img/rnn_3.jpg b/CNN/AttentionNet/img/rnn_3.jpg new file mode 100644 index 00000000..2f99e164 Binary files /dev/null and b/CNN/AttentionNet/img/rnn_3.jpg differ diff --git a/CNN/AttentionNet/img/rnn_4.jpg b/CNN/AttentionNet/img/rnn_4.jpg new file mode 100644 index 00000000..609998e9 Binary files /dev/null and b/CNN/AttentionNet/img/rnn_4.jpg differ diff --git a/CNN/AttentionNet/img/rnn_5.jpg b/CNN/AttentionNet/img/rnn_5.jpg new file mode 100644 index 00000000..0ac364ae Binary files /dev/null and b/CNN/AttentionNet/img/rnn_5.jpg differ diff --git a/CNN/AttentionNet/img/rnn_n_1.jpg b/CNN/AttentionNet/img/rnn_n_1.jpg new file mode 100644 index 00000000..a05add55 Binary files /dev/null and b/CNN/AttentionNet/img/rnn_n_1.jpg differ diff --git a/CNN/AttentionNet/img/single_cnn.jpg b/CNN/AttentionNet/img/single_cnn.jpg new file mode 100644 index 00000000..3e36b5e5 Binary files /dev/null and b/CNN/AttentionNet/img/single_cnn.jpg differ diff --git a/CNN/AttentionNet/readme.md b/CNN/AttentionNet/readme.md new file mode 100644 index 00000000..bdfac4ce --- /dev/null +++ b/CNN/AttentionNet/readme.md @@ -0,0 +1,263 @@ +# Attention Net Attention Model(注意力模型) + +[台大李宏毅老师 Machine Learning, Deep Learning and Structured Learning 包含RNN Attention模块](http://speech.ee.ntu.edu.tw/~tlkagk/courses_MLSD15_2.html) + +[浅谈Attention-based Model【原理篇】 上述课程 部分笔记](https://blog.csdn.net/u010159842/article/details/80473462) + +[完全图解RNN、RNN变体、Seq2Seq、Attention机制-知乎](https://zhuanlan.zhihu.com/p/28054589) + +[Attention Is All You Need](https://arxiv.org/pdf/1706.03762.pdf) + +Attention即为注意力,人脑在对于的不同部分的注意力是不同的。需要attention的原因是非常直观的,比如,我们期末考试的时候,我们需要老师划重点,划重点的目的就是为了尽量将我们的attention放在这部分的内容上,以期用最少的付出获取尽可能高的分数;再比如我们到一个新的班级,吸引我们attention的是不是颜值比较高的人?普通的模型可以看成所有部分的attention都是一样的,而这里的attention-based model对于不同的部分,重要的程度则不同。 + +Attention-based Model其实就是一个相似性的度量,当前的输入与目标状态越相似,那么在当前的输入的权重就会越大,说明当前的输出越依赖于当前的输入。严格来说,Attention并算不上是一种新的model,而仅仅是在以往的模型中加入attention的思想,所以Attention-based Model或者Attention Mechanism是比较合理的叫法,而非Attention Model。 + +Attention Mechanism可以帮助模型对输入的X每个部分赋予不同的权重,抽取出更加关键及重要的信息,使模型做出更加准确的判断,同时不会对模型的计算和存储带来更大的开销,这也是Attention Mechanism应用如此广泛的原因。 + +> 从Attention的作用角度出发,Attention分为两类: + +* **1.空间注意力 Spatial Attention,同一时期不同部分的关联** +* **2.时间注意力 Temporal Attention,不同时期内容的关联** + +这样的分类更多的是从应用层面上,而从 Attention的作用方法上,可以将其分为 Soft Attention 和 Hard Attention,这既我们所说的, Attention输出的向量分布是一种one-hot的独热分布还是soft的软分布,这直接影响对于上下文信息的选择作用。 + +> CNN with Attention + +主要分为两种,一种是spatial attention, 另外一种是channel attention。 +CNN每一层都会输出一个C x H x W的特征图,C就是通道,代表卷积核的数量,亦为特征的数量,H 和W就是原始图片经过压缩后的图,spatial attention就是对于所有的通道,在二维平面上,对H x W尺寸的图学习到一个权重,对每个像素都会学习到一个权重。你可以想象成一个像素是C维的一个向量,深度是C,在C个维度上,权重都是一样的,但是在平面上,权重不一样。这方面的论文已经很多了,重点关注一下image/video caption。相反的,channel attention就是对每个C,在channel维度上,学习到不同的权重,平面维度上权重相同。spatial 和 channel attention可以理解为关注图片的不同区域和关注图片的不同特征。channel attention写的最好的一篇论文个人感觉是SCA-CNN + +> attention机制听起来高达上,其实就是学出一个权重分布,再拿这个权重分布施加在原来的特征之上,就可以叫做attention。简单来说: + +**(1)这个加权可以是保留所有分量均做加权(即soft attention);也可以是在分布中以某种采样策略选取部分分量(即hard attention)。** + +**(2)这个加权可以作用在空间尺度上,给不同空间区域加权;也可以作用在channel尺度上,给不同通道特征加权;甚至特征图上每个元素加权。 ** + +**(3)这个加权还可以作用在不同时刻历史特征上,如Machine Translation,以及我前段时间做的视频相关的工作。** + + +深度学习里的Attention model其实模拟的是人脑的注意力模型,举个例子来说,当我们观赏一幅画时,虽然我们可以看到整幅画的全貌,但是在我们深入仔细地观察时,其实眼睛聚焦的就只有很小的一块,这个时候人的大脑主要关注在这一小块图案上,也就是说这个时候人脑对整幅图的关注并不是均衡的,是有一定的权重区分的。这就是深度学习里的Attention Model的核心思想。 + +Attention模型最初应用于图像识别,模仿人看图像时,目光的焦点在不同的物体上移动。当神经网络对图像或语言进行识别时,每次集中于部分特征上,识别更加准确。如何衡量特征的重要性呢?最直观的方法就是权重,因此,Attention模型的结果就是在每次识别时,首先计算每个特征的权值,然后对特征进行加权求和,权值越大,该特征对当前识别的贡献就大。 + +[RAM: Recurrent Models of Visual Attention 学习笔记](https://blog.csdn.net/c602273091/article/details/79059445) + +RAM model讲得是视觉的注意力机制,说人识别一个东西的时候,如果比较大的话,是由局部构造出整体的概念。人的视觉注意力在选择局部区域的时候,是有一种很好的机制的,会往需要更少的步数和更能判断这个事物的方向进行的,我们把这个过程叫做Attention。由此,我们把这个机制引入AI领域。使用RNN这种可以进行sequential decision的模型引入,然后因为在选择action部分不可导,因为找到目标函数无法进行求导,只能进采样模拟期望,所以引入了reinforcment leanrning来得到policy进而选择action。 + +首先输入时一副完整的图片,一开始是没有action的,所以随机挑选一个patch,然后送入了RNN网络中,由RNN产生的输出作为action,这个action可以是hard attention,就是根据概率a~P(a|X)进行采样,或者是直接由概率最大的P(a|X)执行。有了action以后就可以从图片中选择某个位置的sub image送到RNN中作为input,另外一方面的input来自于上一个的hidden layer的输出。通过同样的网络经过T step之后,就进行classification,这里得到了最终的reward,(把calssification是否判断正确作为reward)就可以进行BPTT,同时也可以根据policy gradient的方法更新policy function。可以发现这个网络算是比较简单,也只有一个hidden layer,我觉得应该是加入了RL之后比较难训练。 + + +将卷积神经网络应用于大型图像的计算量很大,因为计算量与图像像素数成线性关系。我们提出了一种新颖的循环神经网络模型,可以从图像或视频中提取信息,方法是自适应地选择一系列区域或位置,并仅以高分辨率处理选定区域。与卷积神经网络一样,所提出的模型具有内置的平移不变性程度,但其执行的计算量可以独立于输入图像大小进行控制。虽然模型是不可区分的,但可以使用强化学习方法来学习,以学习特定于任务的策略。 + +人类感知的一个重要特性是不倾向于一次处理整个场景。 相反,人类有选择地将注意力集中在视觉空间的某些部分上,以获取需要的信息,并随时间将不同视角的信息相结合,以建立场景的内部表示,指导未来的眼球运动和决策制定。 由于需要处理更少的“像素”,因此将场景中的部分计算资源集中在一起可节省“带宽”。 但它也大大降低了任务的复杂性,因为感兴趣的对象可以放置在固定的中心,固定区域之外的视觉环境(“杂乱”)的不相关特征自然被忽略。 + +该模型是一个循环神经网络(RNN),它按顺序处理输入,一次一个地处理图像(或视频帧)内的不同位置,并递增地组合来自这些注视的信息以建立场景的动态内部表示,或环境。基于过去的信息和任务的需求,模型不是一次处理整个图像甚至是边界框,而是在每一步中选择下一个要注意的位置。我们的模型中的参数数量和它执行的计算量可以独立于输入图像的大小来控制,而卷积网络的计算需与图像像素的数量线性地成比例。我们描述了一个端到端的优化程序,该程序允许模型直接针对给定的任务进行训练,并最大限度地提高可能取决于模型做出的整个决策序列的性能测量。该过程使用反向传播来训练神经网络组件和策略梯度以解决由于控制问题导致的非差异性。 + +我们表明,我们的模型可以有效的学习特定于任务的策略,如多图像分类任务以及动态视觉控制问题。 我们的结果还表明,基于关注的模型可能比卷积神经网络更好地处理杂波和大输入图像。 + +对于对象检测,已经做了很多工作来降低广泛的滑动窗口范例的成本,主要着眼于减少评估完整分类器的窗口的数量. + +循环注意力模型 Attention rnn + +[参考](https://github.com/scutan90/DeepLearning-500-questions/blob/master/ch06_%E5%BE%AA%E7%8E%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C(RNN)/%E7%AC%AC%E5%85%AD%E7%AB%A0_%E5%BE%AA%E7%8E%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C(RNN).md) + +### **1.单个神经元 基本的单层网络结构** + +在进一步了解RNN之前,先给出最基本的单层网络结构,输入是x,经过变换Wx+b和激活函数f得到输出y: + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/AttentionNet/img/single_cnn.jpg) + + +### **2.图解经典RNN结构 + +在实际应用中,我们还会遇到很多序列形的数据,如: + +a.自然语言处理问题,x1可以看做是第一个单词,x2可以看做是第二个单词,依次类推。 + +b.语音处理,此时,x1、x2、x3……是每帧的声音信号。 + +c.时间序列问题,例如每天的股票价格等等。 + +序列形的数据就不太好用原始的神经网络处理了。为了建模序列问题,RNN引入了隐状态h(hidden state)的概念,h可以对序列形的数据提取特征,接着再转换为输出。 + +为了便于理解,先从h1的计算开始看: + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/AttentionNet/img/rnn_1.jpg) + +注:h0是初始隐藏状态,图中的圆圈表示向量,箭头表示对向量做变换。 + +h2的计算和h1类似。要注意的是,在计算时,每一步使用的参数U、W、b都是一样的,也就是说每个步骤的参数都是共享的,这是RNN的重要特点,一定要牢记。 + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/AttentionNet/img/rnn_2.jpg) + +依次计算剩下来的h3、h4也是类似的(使用相同的参数U、W、b,计算隐藏层共享参数 U W b): + + h3 =f(U*h2 + W*x3 + b) + + h4 =f(U*h3 + W*x3 + b) + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/AttentionNet/img/rnn_3.jpg) + +我们这里为了方便起见,只画出序列长度为4的情况,实际上,这个计算过程可以无限地持续下去。 + +我们目前的RNN还没有输出,得到输出值的方法就是直接通过对隐藏状态h进行类似 最开始x的计算方式: + +采用 Softmax 作为激活函数, + + y1=Softmax(V*h1 + c) + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/AttentionNet/img/rnn_4.jpg) + +剩下的输出类似进行(使用和y1同样的参数V和c 同样隐藏层解码也共享参数V和c): + + y2 = Softmax(V*h2 + c) + y3 = Softmax(V*h3 + c) + y4 = Softmax(V*h4 + c) + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/AttentionNet/img/rnn_5.jpg) + +这就是最经典的RNN结构,它的输入是x1, x2, .....xn,输出为y1, y2, ...yn,也就是说,输入和输出序列必须要是等长的。 + +> **由于这个限制的存在,经典RNN的适用范围比较小,但也有一些问题适合用经典的RNN结构建模,如:** + +计算视频中每一帧的分类标签。因为要对每一帧进行计算,因此输入和输出序列等长。 +输入为字符,输出为下一个字符的概率。 + +这就是著名的[Char RNN](https://zhuanlan.zhihu.com/p/29212896) + +可以用来生成文章,诗歌,甚至是代码,非常有意思)。 + +### **3.vector-to-sequence结构 一入多出** + + 有时我们要处理的问题输入是一个单独的值,输出是一个序列。此时,有两种主要建模方式: + +方式一:可只在其中的某一个序列进行计算,比如序列第一个进行输入计算,其建模方式如下: + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/AttentionNet/img/rnn_1_n.jpg) + +方式二:把输入信息X作为每个阶段的输入,其建模方式如下: + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/AttentionNet/img/rnn_1n_n.jpg) + +> **这种 1 VS N 的结构可以处理的问题有:** + +a.从图像生成文字(image caption),此时输入的X就是图像的特征,而输出的y序列就是一段句子. + +b.从类别(图像)生成语音或音乐等 + +### **4.sequence-to-vector结构 多入一出** + + 有时我们要处理的问题输入是一个序列,输出是一个单独的值,此时通常在最后的一个隐含状态h上进行输出变换,其建模如下所示: + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/AttentionNet/img/rnn_n_1.jpg) + +> **这种结构通常用来处理序列分类问题。如:** + +a.输入一段文字判别它所属的类别; + +b.输入一个句子判断其情感倾向; + +c.输入一段视频并判断它的类别等等; + + ### **4.sequence-to-sequence结构 不等长多入多出** + +原始的N vs N RNN要求序列等长,然而我们遇到的大部分问题序列都是不等长的,如机器翻译中,源语言和目标语言的句子往往并没有相同的长度。 + +下面我们来介绍RNN最重要的一个变种:N vs M。这种结构又叫Encoder-Decoder模型,也可以称之为Seq2Seq模型。 + +其建模步骤如下: + +步骤一:将输入数据x 通过隐含状态h 编码成一个上下文向量c,这部分称为Encoder编码。 + +得到c有多种方式: + +a.最简单的方法就是把Encoder的最后一个隐状态hn赋值给c = hn, + +b.还可以对最后的隐状态做一个变换得到 c=q(hn), + +c.也可以对所有的隐状态做变换 c=q(h1,h2,...,hn)。 + +其示意如下所示: + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/AttentionNet/img/rnn-s2s-encoder.jpg) + +步骤二:拿到 编码数据c 之后,就用另一个RNN网络对其进行解码,这部分RNN网络被称为Decoder。 + +方法一:具体做法就是将c当做之前的初始状态h0输入到Decoder中: + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/AttentionNet/img/rnn-s2s-decoder.jpg) + +方法二是将 编码数据c 作为Decoder的每一步输入,示意图如下所示: + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/AttentionNet/img/rnn-s2s-decoder2.jpg) + +> **由于这种Encoder-Decoder结构不限制输入和输出的序列长度,因此应用的范围非常广泛,比如:** + +a.机器翻译。Encoder-Decoder的最经典应用,事实上这一结构就是在机器翻译领域最先提出的; + +b.文本摘要。输入是一段文本序列,输出是这段文本序列的摘要序列; + +c.阅读理解。将输入的文章和问题分别编码,再对其进行解码得到问题的答案; + +d.语音识别。输入是语音信号序列,输出是文字序列。 + + +### 5.RNN中的Attention机制 + +在Encoder-Decoder结构中,Encoder把所有的输入序列都编码成一个统一的语义特征c再解码,因此, c中必须包含原始序列中的所有信息,它的长度就成了限制模型性能的瓶颈。如机器翻译问题,当要翻译的句子较长时,一个c可能存不下那么多信息,就会造成翻译精度的下降。 + +Attention机制通过在每个时间输入不同的c来解决这个问题,下图是带有Attention机制的Decoder: + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/AttentionNet/img/rnn-s2s-decoder-attention.jpg) + +每一个c会自动去选取与当前所要输出的y最合适的上下文信息。具体来说,我们用 a_ij 衡量Encoder中第j阶段的hj和解码时第i阶段的相关性,最终Decoder中第i阶段的输入的上下文信息 c_i 就来自于所有 h_j 对 a_ij 的加权和。 + +以机器翻译为例(将中文“我爱中国”翻译成英文I love china): + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/AttentionNet/img/ilovechina.jpg) + +输入的序列是“我爱中国”,因此,Encoder中的h1、h2、h3、h4就可以分别看做是“我”、“爱”、“中”、“国”经过编码器得到的特征信息(隐藏信息)。在翻译成英语时,第一个上下文c1应该和“我”这个字最相关,因此对应的 a_11 就比较大,而相应的 a_12 、 a_13 、 a_14 就比较小。c2应该和“爱”最相关,因此对应的 a_22 就比较大。最后的c3和h3、h4最相关,因此 a_33 、 a_34 的值就比较大。 + +**至此,关于Attention模型,我们就只剩最后一个问题了,那就是:这些权重 a_{ij} 是怎么来的?** + +事实上, a_ij 同样是从模型中学出的,它实际和Decoder的第i-1阶段的隐状态h' 、Encoder第j个阶段的隐状态 h 有关。 + +同样还是拿上面的机器翻译举例, a_1j 的计算(此时箭头就表示对h'和 h_j 同时做变换): + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/AttentionNet/img/a1j.jpg) + +a2j: h1\h2\h3\h4 是编码阶段的隐状态,h1'是解码阶段的隐藏状态 +![](https://github.com/Ewenwan/MVision/blob/master/CNN/AttentionNet/img/a2j.jpg) + +a3j: +![](https://github.com/Ewenwan/MVision/blob/master/CNN/AttentionNet/img/a3j.jpg) + +以上就是带有Attention的Encoder-Decoder模型计算的全过程。 + + +![]() + +![]() + +![]() + +![]() + +![]() + + +![]() + +![]() + + +![]() + +![]() + + +![]() + +![]() + + +![]() diff --git a/CNN/CTC/readme.md b/CNN/CTC/readme.md new file mode 100644 index 00000000..666d9da4 --- /dev/null +++ b/CNN/CTC/readme.md @@ -0,0 +1,247 @@ +# 联结主义时间分类器 Connectionist Temporal Classifier + +为什么要发明CTC,对于真实世界的序列学习任务,数据往往含有噪声和没有预先分割。RNN是一个强大的序列学习模型,但是需要对数据进行预先处理,所以有了CTC我们就能够提升RNN的性能。 + +用来解决输入序列和输出序列难以一一对应的问题。 + +举例来说,在语音识别中,我们希望音频中的音素和翻译后的字符可以一一对应,这是训练时一个很天然的想法。但是要对齐是一件很困难的事,有人说话块,有人说话慢,每个人说话快慢不同,不可能手动地对音素和字符对齐,这样太耗时。 + +再比如,在OCR中使用RNN时,RNN的每一个输出要对应到字符图像中的每一个位置,要手工做这样的标记工作量太大,而且图像中的字符数量不同,字体样式不同,大小不同,导致输出不一定能和每个字符一一对应。 + +[一文读懂 CRNN文字检测 + CTC文字识别](https://zhuanlan.zhihu.com/p/43534801) + +[CTC(Connectionist Temporal Classification)介绍](https://www.cnblogs.com/liaohuiqiang/p/9953978.html) + +[关于CTC模型的理解](https://blog.csdn.net/gzj_1101/article/details/80153686) + +[tensorflow LSTM+CTC实现端到端的不定长数字串识别](https://www.jianshu.com/p/45828b18f133) + +[Use CTC + tensorflow to OCR ](https://github.com/ilovin/lstm_ctc_ocr) + +[caffe + WarpCTC](https://github.com/xmfbit/warpctc-caffe) + + 适合于输入特征和输出标签之间对齐关系不确定的时间序列问题, + CTC可以自动端到端地同时优化模型参数和对齐切分的边界。 + + 比如本文例子,32 x 256大小的图片,最大可切分256列,也就是输入特征最大256, + 而输出标签的长度最大设定是18,这种就可以用CTC模型进行优化。 + 关于CTC模型,笔者认为可以这样理解,假设32 x 256的图片,数字串标签是"123", + 把图片按列切分(CTC会优化切分模型),然后分出来的每块再去识别数字, + 找出这块是每个数字或者特殊字符的概率(无法识别的则标记为特殊字符"-"), + 这样就得到了基于输入特征序列(图片)的每一个相互独立建模单元个体(划分出来的块)(包括“-”节点在内)的类属概率分布。 + 基于概率分布,算出标签序列是"123"的概率P(123),当然这里设定"123"的概率为所有子序列之和, + 这里子序列包括'-'和'1'、'2'、'3'的连续重复. + + + +## 文字识别 OCR + +[文字识别OCR方法整理](https://zhuanlan.zhihu.com/p/65707543) + +文字识别也是图像领域一个常见问题。然而,对于自然场景图像,首先要定位图像中的文字位置,然后才能进行识别。 + +所以一般来说,从自然场景图片中进行文字识别,需要包括2个步骤: + +1.文字检测:解决的问题是哪里有文字,文字的范围. +2.文字识别:对定位好的文字区域进行识别,主要解决的问题是每个文字是什么,将图像中的文字区域进转化为字符信息. + +[场景文字检测 — CTPN原理与实现 ](https://zhuanlan.zhihu.com/p/34757009) + +对于复杂场景的文字识别,首先要定位文字的位置,即文字检测。 + +### 文字检测(Text Detection) +文字检测定位图片中的文本区域,而Detection定位精度直接影响后续Recognition结果。 + +EAST/CTPN/SegLink/PixelLink/TextBoxes/TextBoxes++/TextSnake/MSR/... + +CTPN是在ECCV 2016提出的一种文字检测算法。CTPN结合CNN与LSTM深度网络,能有效的检测出复杂场景的横向分布的文字,是目前比较好的文字检测算法。 + +由于CTPN是从Faster RCNN改进而来,本文默认读者熟悉CNN原理和Faster RCNN网络结构。 + +[一文读懂Faster RCNN](https://zhuanlan.zhihu.com/p/31426458) + +> Faster RCNN其实可以分为4个主要内容: + +1.Conv layers。作为一种CNN网络目标检测方法,Faster RCNN首先使用一组基础的conv+relu+pooling层提取image的feature maps。该feature maps被共享用于后续RPN层和全连接层。 +2.Region Proposal Networks。RPN网络用于生成region proposals。该层通过softmax判断anchors属于foreground或者background,再利用bounding box regression修正anchors获得精确的proposals。 +3.Roi Pooling。该层收集输入的feature maps和proposals,综合这些信息后提取proposal feature maps,送入后续全连接层判定目标类别。 +4.Classification。利用proposal feature maps计算proposal的类别,同时再次bounding box regression获得检测框最终的精确位置。 + +[CTPN相关:caffe代码](https://github.com/tianzhi0549/CTPN) + +原始CTPN只检测横向排列的文字。CTPN结构与Faster R-CNN基本类似,但是加入了LSTM层。 + +卷积网络之后 使用 双向 LSTM提取特征 (包含空间特征,也包含了LSTM学习到的序列特征) 再经过“FC”卷积层,最后经过类似Faster R-CNN的RPN网络,获得text proposals。 + +[完全解析RNN, Seq2Seq, Attention注意力机制](https://zhuanlan.zhihu.com/p/51383402) + +循环神经网络RNN结构被广泛应用于机器翻译,语音识别,文字识别OCR等方向。 + +CNN学习的是感受野内的空间信息,LSTM学习的是序列特征。对于文本序列检测,显然既需要CNN抽象空间特征,也需要序列特征(毕竟文字是连续的)。 + +CTPN中使用双向LSTM,相比一般单向LSTM有什么优势?双向LSTM实际上就是将2个方向相反的LSTM连起来. + +> 总结: + +1.由于加入LSTM,所以CTPN对水平文字检测效果超级好。 +2.因为Anchor设定的原因,CTPN只能检测横向分布的文字,小幅改进加入水平Anchor即可检测竖直文字。但是由于框架限定,对不规则倾斜文字检测效果非常一般。 + +倾斜文字 可以想办法 校准为 水平文字??? + +3.CTPN加入了双向LSTM学习文字的序列特征,有利于文字检测。但是引入LSTM后,在训练时很容易梯度爆炸,需要小心处理。 + +### 文字识别(Text Recognition) + +识别水平文本行,一般用CRNN或Seq2Seq两种方法. + +> 常用文字识别算法主要有两个框架: + +1. CNN+RNN+CTC(CRNN+CTC) + +2. CNN+Seq2Seq+Attention + +CNN+Seq2Seq+Attention+word2vec + +对于特定的弯曲文本行识别,早在CVPR2016就已经有了相关paper: + +[Robust Scene Text Recognition with Automatic Rectification](https://arxiv.org/pdf/1603.03915.pdf) + +对于弯曲不规则文本,如果按照之前的识别方法,直接将整个文本区域图像强行送入CNN+RNN,由于有大量的无效区域会导致识别效果很差。所以这篇文章提出一种通过**STN网络Spatial Transformer Network(STN)**学习变换参数,将Rectified Image对应的特征送入后续RNN中识别。 + +[STN网络Spatial Transformer Network(STN)](https://arxiv.org/pdf/1506.02025.pdf) + +对于STN网络,可以学习一组点 (x_i^s,y_i^s) 到对应点 (x_i^t,y_i^t) 的变换。而且STN可以插入轻松任意网络结构中学习到对应的变换。 + + (x_i^s, + y_i^s) = (c11, c12, c13 + c21, c22, c23) * (x_i^t, + y_i^t, + 1) +**核心就是将传统二维图像变换(如旋转/缩放/仿射等)End2End融入到网络中。** + +文字检测和文字识别是分为两个网络分别完成的,所以一直有研究希望将OCR中的Detection+ Recognition合并成一个End2End网络。目前End2End OCR相关研究如下: + +[Li_Towards_End-To-End_Text](http://openaccess.thecvf.com/content_ICCV_2017/papers/Li_Towards_End-To-End_Text_ICCV_2017_paper.pdf) + +该篇文章采用Faster R-CNN的Two-stage结构:首先Text Proposal Network(即RPN)生成对应的文本区域Text Proposal,后续通过Bounding Box regression和Box Classification进一步精修文本位置。但是不同的是,在RoI Pooling后接入一个LSTM+Attention的文字识别分支中. + +但是这样的结构存在问题。举例说明:Faster R-CNN的RPN只是初步产生Proposal,后续还需要再经过一次Bounding Box regression才能获取准确的检测框. + +所以Text Proposal不一定很准会对后续识别分支产生巨大影响,导致该算法在复杂数据集上其实并不是很work。 + + + +#### 1. CNN+RNN+CTC(CRNN+CTC) + +[OCR_TF_CRNN_CTC 代码 ](https://github.com/bai-shang/OCR_TF_CRNN_CTC) + +[论文](https://arxiv.org/pdf/1507.05717.pdf) + +> **CRNN=CNN+RNN(LSTM):** + +为了将特征输入到Recurrent Layers,做如下处理: + +先通过CNN提取文本图片的Feature map,然后将每一个channel作为 D=512 的时间序列输入到LSTM中。 + +1.首先会将图像缩放到 32* W(例如100) * 3 大小, H * W * C的顺序。 +2.然后经过CNN后变为 1* (W/4) * 512。 +3.接着针对LSTM,设置时间长度 T=(W/4)(即有25个时间输入) , 每个输入的维度 D=512 ,即可将特征输入LSTM。 + +所以在处理输入图像的时候,建议在保持长宽比的情况下将高缩放到 32,这样能够尽量不破坏图像中的文本细节。当然也,也可以将输入图像缩放到固定宽度,但是这样肯定会造成性能下降。 + + +> **CTC的存在理由** +问题引入: + +对于Recurrent Layers,如果使用常见的Softmax Loss,则每一列输出都需要对应一个字符元素。那么训练时候每张样本图片都需要标记出每个字符在图片中的位置,再通过CNN感受野对齐到Feature map的每一列获取该列输出对应的Label才能进行训练。 + +在实际情况中,标记这种对齐样本非常困难,工作量非常大。另外,由于每张样本的字符数量不同,字体样式不同,字体大小不同,导致每列输出并不一定能与每个字符一一对应。 + +当然这种问题同样存在于语音识别领域。例如有人说话快,有人说话慢,那么如何进行语音帧对齐,是一直以来困扰语音识别的巨大难题。 + +所以CTC提出一种对不需要对齐的Loss计算方法,用于训练网络,被广泛应用于文本行识别和语音识别中。 + + +在看懂CTC之前需要了解隐马尔可夫模型和EM算法。其实CTC里面的思想和HMM很相似,但是又有所区别,如果搞懂了HMM,那么对于CTC的理解就会轻松很多。如果有对HMM不太懂的可以参考我前面几篇博客。 + +[EM算法(Expectation maximization algorithm) 期望最大化](https://blog.csdn.net/gzj_1101/article/details/79924655) + +[隐马尔科夫HMM模型一(概念理解)](https://blog.csdn.net/gzj_1101/article/details/79955340) + +[隐马尔可夫HMM模型二(公式推导)](https://blog.csdn.net/gzj_1101/article/details/80031298) + +[CTC原理 !!!!!!](https://x-algo.cn/index.php/2017/05/31/2345/) + +[TensorFLow 中 CTC 的相关函数介绍](https://blog.csdn.net/mzpmzk/article/details/81586245) + +图像经过CNN网络得到 CNN Feature map X 维度为 m * T + + X =(x1,x2,...,xT) T=25 + xi=(xi1,xi2,...,xim) m=512 + +CNN Feature map输入到 LSTM网络,得到 LSTM特征(时间片特征) + +LSTM的每一个时间片后接softmax,输出 y 是一个后验概率矩阵y,维度为 n * T + + y =(y1,y2,...,yT) T = 时间片段数量 + 其中每一列为: yi=(yi1,yi2,...,yin) n = 需要识别的字符集合长度(应该考虑空白字符) + sum(yin) = 1. + 对 y 每一列进行 argmax() (最大概率所在的字符index)操作,即可获得每一列输出字符的类别。 + +使用CTC在这个概率矩阵状态图中选择一个概率最大的路径。 + +CTC是一种Loss计算方法,用CTC代替Softmax Loss,训练样本无需对齐。CTC特点: + +1.引入blank字符,解决有些位置没有字符的问题。 +2.通过递推,快速计算梯度。 + + +> **CRNN+CTC总结** + +将CNN/LSTM/CTC三种方法结合: + +1.首先CNN提取图像卷积特征 +2.然后LSTM进一步提取图像卷积特征中的序列特征 +3.最后引入CTC解决训练时字符无法对齐的问题 + + +#### 2. CNN+Seq2Seq+Attention + +> 整个CRNN网络可以分为三个部分: + +0.假设输入图像大小为 (32, 100,3),注意提及图像都是 [\text{Height},\text{Width},\text{Channel}] 形式。 + +1.Convlutional Layers + +这里的卷积层就是一个普通的CNN网络,用于提取输入图像的Convolutional feature maps,即将大小为 (32, 100,3) 的图像转换为 (1,25,512) 大小的卷积特征矩阵。 + +2. Recurrent Layers + +这里的循环网络层是一个深层双向LSTM网络,在卷积特征的基础上继续提取文字序列特征。 + +所谓深层RNN网络,是指超过两层的RNN网络。 + +3. Transcription Layers + +将RNN输出做softmax后,通过转化为字符。 + +对于Recurrent Layers,如果使用常见的Softmax Loss,则每一列输出都需要对应一个字符元素。那么训练时候每张样本图片都需要标记出每个字符在图片中的位置,再通过CNN感受野对齐到Feature map的每一列获取该列输出对应的Label才能进行训练,如图8。 + +在实际情况中,标记这种对齐样本非常困难,工作量非常大。另外,由于每张样本的字符数量不同,字体样式不同,字体大小不同,导致每列输出并不一定能与每个字符一一对应。 + +当然这种问题同样存在于语音识别领域。例如有人说话快,有人说话慢,那么如何进行语音帧对齐,是一直以来困扰语音识别的巨大难题。 + +所以Connectionist Temporal Classification(CTC)提出一种对不需要对齐的Loss计算方法,用于训练网络,被广泛应用于文本行识别和语音识别中。' + +CRNN+CTC总结将CNN/LSTM/CTC三种方法结合: + +1.首先CNN提取图像卷积特征 +2.然后LSTM进一步提取图像卷积特征中的序列特征 +3.最后引入CTC解决训练时字符无法对齐的问题 +即提供了一种end2end文字图片识别算法,也算是OCR方向的简单入门文章。 + + + + + + diff --git a/CNN/Deep_Compression/quantization/readme.md b/CNN/Deep_Compression/quantization/readme.md index 7b5f4971..06f0e763 100644 --- a/CNN/Deep_Compression/quantization/readme.md +++ b/CNN/Deep_Compression/quantization/readme.md @@ -6,9 +6,19 @@ [论文合集](https://github.com/Ewenwan/MVision/blob/master/CNN/Deep_Compression/quantization/quantizedNN_paper.md) +[低数值精度深度学习推理与训练](https://software.intel.com/zh-cn/articles/lower-numerical-precision-deep-learning-inference-and-training) + +![](https://pic3.zhimg.com/80/v2-e9348fa8928c882d7978cc469b3cc312_720w.jpg) + +我们将conv2d-fp32的操作,转化成了如下几个操作的组合:权重编码、fp32-to-int8-IO、输入编码、fp32-int8-IO、conv2d-int8操作、输出反编码、int32-to-fp32-IO。假设当前计算的寄存器位宽为128,理论上fp32算子的峰值加速比为4,int8算子的峰值加速比为16。但为什么我们量化后,从fp32到int8的加速比达不到4呢?因为我们还做了很多额外的操作,IO上的操作如两个fp32-to-int8-IO、一个int32-to-fp32-IO,编码操作如一个权重编码和一个输入编码,反编码操作int32-to-fp32-IO。在经过这一系列额外的操作后,很多情况下,我们依然还能达到约1.2~1.5的加速比。与此同时,量化还能减轻模型的存储压力和内存压力(fp32的权值转由int8权值进行存储)。缺点嘛,会带来精度损失!如何最小化精度损失呢? + +[谈谈MNN的模型量化(一)数学模型](https://zhuanlan.zhihu.com/p/81243626) + # 具体量化方法 [参考](https://github.com/Ewenwan/pytorch-playground/blob/master/utee/quant.py) + + ```python # 线性量化 def linear_quantize(input, sf, bits): diff --git a/CNN/Deep_Compression/readme.md b/CNN/Deep_Compression/readme.md index d5e37082..93a62586 100644 --- a/CNN/Deep_Compression/readme.md +++ b/CNN/Deep_Compression/readme.md @@ -6,11 +6,22 @@ description: "量化 剪枝 ncnn Ristretto" tag: 深度学习 --- # 背景 + 近几年来,深度学习技术在计算机视觉、语音识别和自然语言处理等诸多领域取得的了一系列重大突破。 然而,深度学习的发展依然面临诸多问题。 尤为突出的是,时下主流的深度神经网络,一般包含数千万甚至是过亿的学习参数, 而如此海量的参数给神经网络模型在存储、计算和功耗开销等方面带来了严峻的考验。 +[阿里巴巴的轻量网络训练方法: 剪枝和压缩 轻量级 知识蒸馏 模型量化 算子融合](https://github.com/Captain1986/CaptainBlackboard/blob/master/D%230034-%E7%81%AB%E7%AE%AD%E5%8F%91%E5%B0%84%EF%BC%9A%E9%98%BF%E9%87%8C%E5%B7%B4%E5%B7%B4%E7%9A%84%E8%BD%BB%E9%87%8F%E7%BD%91%E7%BB%9C%E8%AE%AD%E7%BB%83%E6%96%B9%E6%B3%95/D%230034.md) + + +[DeepCompression-caffe](https://github.com/Ewenwan/DeepCompression-caffe/blob/master/README.md) + +[使用Caffe实现,需要加入一个mask来表示剪枝。剪枝的阈值,是该layer的权重标准差乘上某个超参数。有人基于Caffe官方的repo给FC层加上了剪枝](https://github.com/BVLC/caffe/pull/4294/files) + +[model-pruning 模型剪枝总结](https://xmfbit.github.io/2018/10/03/paper-summary-model-pruning/#more) + +[iccv2019 通道自动搜索剪裁 网络编码 随机搜索 测试性能 进化算法获得最优剪裁方案](https://github.com/Ewenwan/MetaPruning) # 性能提升方法 [本文github链接](https://github.com/Ewenwan/MVision/blob/master/CNN/Deep_Compression/readme.md) diff --git a/CNN/Deep_Compression/stretegy.md b/CNN/Deep_Compression/stretegy.md index d7902faf..ac90dc71 100644 --- a/CNN/Deep_Compression/stretegy.md +++ b/CNN/Deep_Compression/stretegy.md @@ -390,9 +390,7 @@ YOLOv2:voc2007 map0.5: 76.8; YOLOv2 544x544:voc2007 map0.5: 78.6; YOLOv2 608x608:coco上 map0.5: 48.1 - - caffe下 - 448*448尺寸caffeinemodel https://pan.baidu.com/s/1c71EB-6A1xQb2ImOISZiHA password: 9u5v + #### 裁剪 #### 量化 diff --git "a/CNN/HighPerformanceComputing/ARM_NEON_CNN_\347\272\257\346\261\207\347\274\226\347\274\226\347\250\213_MNN.md" "b/CNN/HighPerformanceComputing/ARM_NEON_CNN_\347\272\257\346\261\207\347\274\226\347\274\226\347\250\213_MNN.md" new file mode 100644 index 00000000..707061bb --- /dev/null +++ "b/CNN/HighPerformanceComputing/ARM_NEON_CNN_\347\272\257\346\261\207\347\274\226\347\274\226\347\250\213_MNN.md" @@ -0,0 +1,312 @@ +# ARM_NEON_CNN_纯汇编编程_MNN + +[参考1](https://blog.csdn.net/jxt1234and2010/article/details/104012746) + +纯汇编开发,优化策略相应的简单很多,基本上**循环展开、指令重排**之后,就有立竿见影的效果。 + +> 基本流程 + +1.梳理代码,设计实现方案,提炼出核心的运算部分,先用C实现一遍,保证正确; + +2.32位汇编代码初步实现,保证功能正确; + +3.汇编代码优化:这一步优化只做循环展开和指令重排,如果有更好的计算方案,先退回 C 重新写; + +4.64位的也支持一下:替换一下寄存器名和指令名(可以写脚本完成),然后微调一下函数前后读参数、入出栈与返回的地方(可选)64位的进一步优化一下,毕竟寄存器多了一倍; + +## Procedure Call Standard【函数调用标准】 + +### ARM 32(v7a) + +> 通用寄存器 32bit r0 r1 ... r15 + +传参数用: r0 r1 r2 r3 用完要恢复(进栈保存后出栈): **r4 r5 ... r11** + +随便使用: r0 r1 r2 r3, r12 不能使用(谨慎使用): r13 r14 r15 + +> 向量寄存器128bit q0 q1 ... q15 可以64bit形式使用 即 d0 d1 d2 d3 ... d30 d31 + +用完要恢复(进栈保存后出栈): **q4 q5 q6 q7** + +随便使用: q0 q1 q2 q3, q8 q9 ... q15 + +用完恢复是指相应的寄存器在函数返回前必须恢复进入时的值,比如我们要在代码中用 q4,就必须在函数前写一句 +```c +vpush {q4} // 进栈保存 保护 向量寄存器使用 vpush {} +push {r4, lr} // 进栈保存 保护 通用寄存器使用 push {} +``` +函数返回前写一句: +```c +vpop {q4} // 出栈恢复 +pop {r4, pc} // 出栈恢复 通用寄存器使用 pop {} +``` + + r12用作子程序间scratch寄存器,记作ip; 在子程序的连接代码段中经常会有这种使用规则. + r13用作数据栈指针,记做SP,在子程序中寄存器R13不能用做其他用途. 寄存器SP在进入子程序时的值和退出子程序时的值必须相等. + r14用作连接寄存器,记作lr ; 它用于保存子程序的返回地址,如果在子程序中保存了返回地址,则R14可用作其它的用途. + r15是程序计数器,记作PC ; 它不能用作其他用途. + +### ARM 64(v8) + + +> 通用寄存器 64bit x0 x1 ... x31 可以32bit形式使用 w0 w1 ... w31 使用低32位 + +传参数用: x0-x7 用完要恢复(进栈保存后出栈): x19-x28 + +随便使用: x0-x15 不能使用(谨慎使用): x16 x17 x18, x29 x30 x31 + +> 向量寄存器128bit v0 v1 ... v31 + +可以另外四种形式使用: **64位:d 32位:s 16位:h 8位:b** + +传参数用: 浮点数据传到 v0 v1 + +用完要恢复(进栈保存后出栈): **v8-v15** + +随便使用: v0-v7 v16-v31 + +值得注意的是,arm64 的传参为浮点时,会传到 v0.s[0], v0.s[1] …… 而非通用寄存器,这个很坑,建议不要用浮点传参 + +## 汇编优化实例 +> c版本Relu代码 + +```c +void ReluForward(float* dst, const float* src, size_t sizeDiv4) +{ + for (int i=0; i<4*sizeDiv4; ++i) // 确保数据长度4对齐 + { + dst[i] = src[i] >0 ? src[i] : 0; // 小于0截断为0 + } +} +``` + +> c的NEON版本代码 +```c +void ReluCNeon(float* dst, const float* src, size_t sizeDiv4) +{ + float32x4_t limit = vdupq_n_f32(0.0f); // 4个32位浮点数据 装载到寄存器里面 + for (int i=0; i 基础汇编 + +由于ios和android上面函数编译的符号不一致,这里引入一个头文件,定义一个函数声明宏,去屏蔽这种差异: + +ArmAsmGlobal.h +```c +.macro asm_function fname +#ifdef __APPLE__ +.globl _\fname +_\fname: +#else +.global \fname +\fname: +#endif + +``` + +> 汇编:ReluBasic +```asm +//汇编:ReluBasic +#include "ArmAsmGlobal.h" +asm_function ReluBasic //指定 汇编函数的 函数名 + +//函数参数规定 +//按照 arm32 的 函数调用标准,以下变量由调用方传至寄存器 +//r0: dst, r1: src, r2: sizeDiv4 + +push {lr} +vmov.i32 q15, #0 // 限制值 limit值 0 存入 q15寄存器 4个32位 0.0数据 + +cmp r2, #0 // 剩余数据量大小 sizeDiv4 等于0的话就结束循环 +beq End //跳转:beq 表示 r2 等于0时跳转 + +Loop: //标志,供跳转用 +vld1.32 {q0}, [r1]! // 读取源数据 4个32位 数据到q0寄存器 从地址r1处 !表示 数据取过后 r1 += 4 +vmax.f32 q0, q0, q15 // q0 = max(q0,0) +vst1.32 {q0}, [r0]! // 更新的值 存入 目的地址r0 !表示 数据存过后 r0 += 4 +subs r2, r2, #1 // 这一句 相当于 sub r2, r2, #1 && cmp r2, #0 +bne Loop // 跳转:bne 表示 r2 不等于0时跳转 + +End: +pop {pc} + +``` + +#### 汇编优化 指令流水 循环展开 + +我们注意到循环主体,语句前后有较强依赖关系 + +```asm +vld1.32 {q0}, [r1]! +vmax.f32 q0, q0, q15 //q0 依赖于 前一行的读 从内存载入数据到 寄存器q0 +vst1.32 {q0}, [r0]! //q0 依赖于前一行的计算 q0 = max(q0,0) +``` + +ARM 的CPU一般都有双通道发射能力(跟多核多线程不是同一个概念),在执行如下类型的语句时,可以并发执行,提升效率: +```asm +vld1.32 {q0}, [r1]! +vmax.f32 q1, q1, q15 //不使用 q0,无依赖关系 可以和上面的指令 并发执行 +``` + +为了让我们的汇编代码解除语句前后的依赖关系,先进行一次循环展开: + + +> 汇编:ReluUnroll 就是每次循环 多操作一些数据 每次干的活 量增大 提高CPU利用率 + +```asm + +//汇编:ReluUnroll +#include "ArmAsmGlobal.h" +asm_function ReluUnroll //指定 汇编函数的 函数名 + +//函数参数规定 +//按照 arm32 的 函数调用标准,以下变量由调用方传至寄存器 +//r0: dst, r1: src, r2: sizeDiv4 + +vmov.i32 q15, #0 // 限制值 limit值 0 存入 q15寄存器 4个32位 0.0数据 + +push {lr} + +L4: +cmp r2, #3 // 进入的时候是 除4这里相当于 3*4 = 12 +ble L1 // 数据量 <= 12 就不够一次处理16个了 + + +// 一次处理16个数据 +L4Loop: +// 载入源数据 +vld1.32 {q0, q1}, [r1]! // 载入8个32位浮点 +vld1.32 {q2, q3}, [r1]! // 再载入8个32位浮点 + +// 计算16个数据 x = max(x,0) +vmax.f32 q0, q0, q15 //一次处理多点数据 利用cpu并发 提高cpu利用率 +vmax.f32 q1, q1, q15 +vmax.f32 q2, q2, q15 +vmax.f32 q3, q3, q15 + +// 更新后的数据存入 目标地址 +vst1.32 {q0, q1}, [r0]! +vst1.32 {q2, q3}, [r0]! + +// 循环条件检测 +sub r2, r2, #4 //剩余数据量 - 4*4 +cmp r2, #4 +bge L4Loop // 剩余数据/4 >= 4, 会再循环, 进入的时候是 除4,这个相当于 4*4=16 + + +// 处理剩余 的 4/8/12个数据 +L1: +cmp r2, #0 +beq End + +L1Loop: +// 载入4个数据 +vld1.32 {q0}, [r1]! +// 处理4个数据 +vmax.f32 q0, q0, q15 +// 保存4个数据 +vst1.32 {q0}, [r0]! +// 循环条件检查 +subs r2, r2, #1 // 剩余数据量 - 1*4 +bne L1Loop + + +End: +pop {pc} // 程序指针寄存器 + +// 其他剩余的1~3个数据可以再外部使用C语言单独处理 +``` + + +> 展开之后,L4Loop 内部的语句已经大部分解除了依赖,但还不完全,为了完全解除,我们需要用个小技巧【汇编重点技巧】: + +这个技巧就是将循环主体代码拆成两半,原先的 Loop[AB] 就变成了 A->Loop[BA]->B,然后 BA 由于顺序颠倒,可以实现错排并发。 + +**汇编:ReluUnrollReorder** + +```asm +//汇编:ReluUnrollReorder +#include "ArmAsmGlobal.h" +asm_function ReluUnrollReorder + +push {lr} +vmov.i32 q15, #0 // 限制值 limit值 0 存入 q15寄存器 4个32位 0.0数据 + +L4: +cmp r2, #3 // 数据量 <= 12 转 L1 处理剩余数据 +ble L1 + +vld1.32 {q0, q1}, [r1]! // 载入8个 +vmax.f32 q0, q0, q15 // 处理4个 +vld1.32 {q2, q3}, [r1]! // 载入8个 +vmax.f32 q1, q1, q15 // 处理最前面载入的4个 + +sub r2, r2, #4 // 数据量 -16 +cmp r2, #3 +ble L4End // 数据量 = 16 转 L4End 处理最后16个数据 + +L4Loop: + +vst1.32 {q0, q1}, [r0]! // 存储 上面L4 中处理好的 8个数据 +vmax.f32 q2, q2, q15 // 处理4个 +vld1.32 {q0, q1}, [r1]! // 载入8个 +vmax.f32 q3, q3, q15 // 处理4个 +vst1.32 {q2, q3}, [r0]! // 存储8个 +vmax.f32 q0, q0, q15 // 处理4个 +vld1.32 {q2, q3}, [r1]! // 载入8个 +vmax.f32 q1, q1, q15 // 处理4个 + +// 循环条件检测 +sub r2, r2, #4 +cmp r2, #4 +bge L4Loop + +L4End: +vst1.32 {q0, q1}, [r0]! // 存储8个 上面L4Loop 有两次处理4个 还未存储到内存 +vmax.f32 q2, q2, q15 // 处理4个 +vmax.f32 q3, q3, q15 // 处理4个 +vst1.32 {q2, q3}, [r0]! // 存储8个 + +// 处理数据量 <= 12 0/4/8/12 +L1: +cmp r2, #0 +beq End + +L1Loop: +vld1.32 {q0}, [r1]! // 一次处理4个数据 +vmax.f32 q0, q0, q15 +vst1.32 {q0}, [r0]! +subs r2, r2, #1 +bne L1Loop + + +End: +pop {pc} + +``` + + +性能对比 + + 魅蓝 mental 上测试 + sizeDiv4 = 100000,连续跑10000次(由于 relu 是一个十分简单的op,跑大批量的才能看到效果) + C-neon Cost time : 4856.960449 ms + 汇编ReluBasic Cost time : 4716.672363 ms + 汇编ReluUnroll Cost time : 2814.848145 ms + 汇编ReluUnrollReorder Cost time : 2359.424072 ms + +可以看到: + + 1、最简单的汇编和用 neon api 的 C差不大多 + 2、同样是汇编,ReluUnrollReorder较ReluBasic足足提升了100% + diff --git "a/CNN/HighPerformanceComputing/ARM_NEON_CNN\347\274\226\347\250\213.md" "b/CNN/HighPerformanceComputing/ARM_NEON_CNN\347\274\226\347\250\213.md" new file mode 100644 index 00000000..22e471ad --- /dev/null +++ "b/CNN/HighPerformanceComputing/ARM_NEON_CNN\347\274\226\347\250\213.md" @@ -0,0 +1,2818 @@ +# ARM_NEON_CNN编程 + +内联函数优化的越来越好了,甚至在ARMv8 平台下有优于汇编的性能,同时兼容性方面又比汇编好,因此使用内联函数是上上之选。 +毕竟,NEON肯定会更新的,到时一更新你的底层汇编得全部跟着更新,但是使用内联函数的话就不要考虑这些了,反正编译器都帮我们做了嘛! +最后关于内联函数告诉后辈们几点人生经验: + +使用的寄存器数量要考虑周全; +编译器注意好啊! +一定要看看产生的汇编代码啊! + +[图像算法的工程优化技术: 算法流程优化 CPU多线程 SIMD GPU编程 专用芯片](https://blog.csdn.net/jxt1234and2010/article/details/50768263) + +[AI 移动端框架常用指令·汇总 v7 v8 差异](https://www.jianshu.com/p/5f75fa02c5d0) + +[什么?!NEON还要优化?](https://www.jianshu.com/p/16d60ac56249) + +[神经网络arm neon加速实现](https://blog.csdn.net/fuwenyan/article/details/78793907) + +[常用NEON 内置函数记录备用](https://blog.csdn.net/fuwenyan/article/details/78811034) + +[ARM Cortex系列(A8/A9/A15/A7) NEON多媒体处理SIMD引擎优化](https://blog.csdn.net/yxnyxnyxnyxnyxn/article/details/18267955) + +[aarch64 armv8 neon intrinsics 和内嵌汇编混用](https://github.com/Tencent/ncnn/wiki/aarch64-neon-intrinsics-%E5%92%8C%E5%86%85%E5%B5%8C%E6%B1%87%E7%BC%96%E6%B7%B7%E7%94%A8) + +[32位 armv7 neon intrinsics 和内嵌汇编混用](https://github.com/Tencent/ncnn/wiki/armv7-neon-intrinsics-%E5%92%8C%E5%86%85%E5%B5%8C%E6%B1%87%E7%BC%96%E6%B7%B7%E7%94%A8) + +[ARM NEON 社区](https://community.arm.com/cn/f/tags/NEON) + +[ARM平台NEON指令的编译和优化 编译选项](https://blog.csdn.net/heli200482128/article/details/79303286) + +[程序优化方法经验大全——神文](https://blog.csdn.net/STN_LCD/article/details/77606256) + +> 术语: + +System-on-Chip(SOC) 片上系统:核心、内存控制器、片上内存、外围设备、总线互连和其他逻辑(可能包括模拟或射频组件),以便产生系统。 SOC通常指集成度较高的设备,包括单个设备中系统的许多部分,可能包括模拟、混合信号或射频电路。 + +专用集成电路Application Specific Integrated Circuit(ASIC) :包含ARM内核、内存和其他组件。显然,ASIC和SOC之间有很大的重叠。 + +嵌入式系统 Embedded systems, +内存消耗 Memory Footprint(memory usage), +SIMD(Single Instruction, Multiple Data) 单指令多数据流, +MMU(Memory Management Unit) 内存管理单元, +MPE(Media Processing Engine) 媒体处理引擎。 +VFP(Vector Floating Point) 向量浮点 + +[参考1 ARM NEON 编程系列](http://hongbomin.com/2016/05/13/arm_neon_introduction/) + +[arm官方数据手册](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.subset.swdev.sdt/index.html) + +[Cortex-A Series Programmer’s Guide Version: 4.0](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.subset.swdev.sdt/index.html) + +ARM CPU最开始只有普通的寄存器,可以进行基本数据类型的基本运算。 +自ARMv5开始引入了VFP(Vector Floating Point)指令,该指令用于向量化加速浮点运算。 +自ARMv7开始正式引入NEON指令,NEON性能远超VFP,因此VFP指令被废弃。 + +SIMD即单指令多数据指令,目前在x86平台下有MMX/SSE/AVX系列指令,arm平台下有NEON指令。 +一般SIMD指令通过intrinsics(内部库C函数接口的函数) 或者 汇编 实现。 + +Intrinsics(内联函数)是使用C语言的方式对NEON寄存器进行操作,因为相比于传统的使用纯汇编语言,具有可读性强,开发速度快等优势。如果需要在代码中调用NEON Intrinsics函数,需要加入头文件"arm_neon.h"。 + +NEON C内联函数(intrinsics)是由ARM定义的一组全新的数据类型和内联函数,便于使用C语言直接访问NEON单元。在C/C++程序中,内联函数就同普通函数一样,但在编译时,这些内联函数会直接映射为NEON提供的向量指令。当前GCC编译器和ARM编译器都支持相同的NEON内联语法,只需在程序中添加“arm_neon.h”头文件,就可以使用NEON内联函数。 + +[ARM NEON常用 intrinsics 函数总结 !!!!](https://blog.csdn.net/may0324/article/details/72847800) + +**优势**:使用内联函数进行优化,开发人员无需关注寄存器分配和互锁等问题,这些都交由编译器处理,而且编写程序比较容易,优化后的性能相对较高。 + +**不足**:目前内联函数所提供的功能和灵活性仍远远比不上汇编指令,并且经过编译器编译后,会反复加载/存取寄存器数据,导致系统时钟的浪费。  + + +采用汇编语言进行NEON(**NEON 汇编(assembly)**)的最底层优化,可以使优化性能最大化,但汇编语言比较灵活,手写汇编程序对开发人员来说具有较大挑战,如果使用不恰当,反而会影响优化性能。 + + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/HighPerformanceComputing/img/simd.PNG) + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/HighPerformanceComputing/img/simd_add-op.PNG) + +![](https://upload-images.jianshu.io/upload_images/3270173-633789004154255f.gif?imageMogr2/auto-orient/strip%7CimageView2/2/w/634/format/webp) + +在这里,一条SIMD加法指令可以同时得到8个加法结果。就计算步骤本身而言,比单独使用8条加法指令能够获得8倍的加速比。从该示例也可以看出,随着寄存器长度的变长,单指令能够处理的数据量也越来越大,从而获得更高的加速性能。 +在Intel最新的AVX2指令集中,寄存器最大长度已经达到512位。 + +类似于Intel CPU下的MMX/SSE/AVX/FMA指令,ARM CPU的NEON指令同样是通过向量化计算来进行速度优化,通常应用于图像处理、音视频处理等等需要大量计算的场景。 + +> **SISD(Single Instruction Single Data)单指令单数据** +```asm +add r0, r5 # 单条指令执行一个运算 +add r1, r6 +add r2, r7 +add r3, r8 +``` +> **SIMD(Single Instruction Multiple Data (vector mode向量模式))单指令多数据** +```c +VADD.F32 S24, S8, S16 +// four operations occur 单条指令并行执行四个运算 +// S24 = S8 +S16 +// S25 = S9 +S17 +// S26 = S10 +S18 +// S27 = S11 +S20 + +``` + +> **SIMD(Single Instruction Multiple Data (packed data mode)包数据模式)** +```c +VADD.I16 Q10, Q8, Q9 +// One operation adds two 64-bit registers, 128位寄存器 +// but each of the four 16-bit lanes in the register is added separately. +// 单个数据为16位,所以有8个数据并行计算加法运算 +``` + +> NEON支持的数据类型: + +* 32bit single precision floatingpoint , 32bit 单精度浮点数; +* 8, 16, 32 and 64bit unsigned and signed integers , 8, 16, 32 and 64bit 无符号/有符号 整型; +* 8 and 16bit polynomials 8 and 16bit 多项式。 + + + B字节Byte: 8 bits. + H半字Halfword: 16 bits. 半精度浮点16位 + S字Word: 32 bits. 单精度浮点32位 + D双字Doubleword:64 bits. 双精度浮点64位 + Q四字Quadword: 128 bits. + +> 浮点数取整: + +向负无穷取整(向左取整) Round towards Minus Infinity (RM) roundTowardsNegative + +向正无穷取整(向右取整) Round towards Plus Infinity (RP) roundTowardsPositive + +向零取整(向中间取整)Round towards Zero (RZ) roundTowardZero + +就近取整 Round to Nearest (RN) roundTiesToEven + +随机取整 + +>NEON数据类型说明符: + +* Unsigned integer 无符号整形 U8 U16 U32 U64 +* Signed integer 有符号整形 S8 S16 S32 S64 +* Integer of unspecified type 未指定类型的整数 I8 I16 I32 I64 +Floating point number F16 F32 浮点数 16位浮点数(半精度) 32位浮点数(全精度) +Polynomial over {0,1} P8 多项式 + +注:F16不适用于数据处理运算,只用于数据转换,仅用于实现半精度体系结构扩展的系统。 + +多项式算术在实现某些加密、数据完整性算法中非常有用。 + +寄存器 ARMV7架构包含: + +16个通用寄存器(32bit),R0-R15 register + +16个NEON寄存器(128bit),Q0-Q15 quad四字寄存器(同时也可以被视为32个64bit的寄存器,D0-D31 double双字寄存器) + +16个VFP寄存器(32bit),S0-S15,single 单字寄存器 + +NEON和VFP的区别在于VFP是加速浮点计算的硬件不具备数据并行能力,同时VFP更尽兴双精度浮点数(double)的计算,NEON只有单精度浮点计算能力。 + +16个通用寄存器 + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/HighPerformanceComputing/img/register.PNG) + +寄存器 r0 到 r7 称为低位寄存器。 寄存器 r8 到r15 称为高位寄存器。 + +下列寄存器名称是预先声明的: + +* r0-r15 和 R0-R15 +* a1-a4(自变量、结果或暂存寄存器,r0 到 r3 的同义词) +* v1-v8(变量寄存器,r4 到 r11) +* sb 和 SB(静态基址,r9) +* ip 和 IP(内部程序调用暂存寄存器,r12) +* sp 和 SP(堆栈指针,r13) +* lr 和 LR(链接寄存器,r14) +* pc 和 PC(程序计数器,r15)。 + +> NEON寄存器有几种形式: + +* 16×128bit寄存器(Q0-Q15); 16个128位的寄存器 +* 或32×64bit寄存器(D0-D31) 32个64位的寄存器 +* 或上述寄存器的组合。 + +以下扩展寄存器名称是预先声明的: + +* q0-q15 和 Q0-Q15(NEON™ 四字寄存器) +* d0-d31 和 D0-D31(NEON 双字寄存器,VFP 双精度寄存器) +* s0-s31 和 S0-S31(VFP 单精度寄存器)。 + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/HighPerformanceComputing/img/neon.PNG) + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/HighPerformanceComputing/img/neon-regest.PNG) + +一个D寄存器64位是双字宽度,一个Q寄存器是128位是四字宽度。 + +注:每一个Q0-Q15寄存器映射到 一对D寄存器。 + +> 寄存器之间的映射关系: + +* D<2n> 偶数 映射到 Q 的最低有效半部; +* D<2n+1> 奇数 映射到 Q 的最高有效半部; +* S<2n> 映射到 D 的最低有效半部 +* S<2n+1> 映射到 D 的最高有效半部 + +例如,通过引用 D12 可以访问 Q6 中向量元素的最低有效半部,通过引用 D13 可以访问这些元素的最高有效半部。 + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/HighPerformanceComputing/img/extern-regest.PNG) + +## 指令集概述 +所有 ARM 指令的长度都是 32 位。 这些指令是按字对齐方式存储的,因此在ARM 状态下,指令地址的两个最低有效位始终为零。 + +> **跳转指令**,此类指令用于: + +* 1.向后跳转以构成循环 +* 2.在条件结构中向前跳转 +* 3.跳转到子例程 +* 4.在 ARM 状态和 Thumb 状态之间转换处理器状态。 + +> **寄存器加载和存储指令** + +此类指令用于从内存加载单个寄存器的值,或者在内存中存储单个寄存器的值。它们可加载或存储 32 位字、16 位半字或 8 位无符号字节。 可以用符号或零扩展字节和半字加载以填充 32 位寄存器。此外,还定义了几个可将 64 位双字值加载或存储到两个 32 位寄存器的指令。 + +> **数据处理指令** + +此类指令用于对通用寄存器执行运算。 它们可对两个寄存器的内容执行加法、减法或按位逻辑等运算,并将结果存放到第三个寄存器中。 此外,它们还可以对单个寄存器中的值执行运算,或者对寄存器中的值与指令中提供的常数(立即值)执行运算。 + +> NEON 数据处理指令可分为: + +* 1. 正常指令 Normal instructions 结果 同 操作数 同大小同类型。 + + 生成大小相同且类型通常与操作数向量相同到结果向量。 + + 正常指令可对上述任意向量类型执行运算,并生成大小相同且类型通常与操作数向量相同的结果向量。 + + **通过将 Q 附加到指令助记符,可以指定正常指令的操作数和结果必须全部为四字。** + + 这样指定后,如果操作数或结果不是四字,则汇编程序会生成错误。 + + +* 2. 长指令 Long instructions 操作双字vectors,生成四倍长字vectors 结果的宽度一般比操作数加倍,同类型。 + + 在指令中加L + + 长指令对双字向量操作数执行运算,并生成四字向量结果。 所生成的元素通常是操作数元素宽度的两倍,并属于同一类型。通过将 L 追加到指令助记符来指定长指令。 + + 对双字向量操作数执行运算,生成四字向量到结果。所生成的元素一般是操作数元素宽度到两倍,并属于同一类型。L标记,如VMOVL。 + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/HighPerformanceComputing/img/long.PNG) + +* 3. 宽指令 Wide instructions 操作 双字+四倍长字,生成四倍长字,结果和第一个操作数都是第二个操作数的两倍宽度。 + + 在指令中加W + + 一个双字向量操作数和一个四字向量操作数执行运算,生成四字向量结果。W标记,如VADDW。 + + 宽指令对一个双字向量操作数和一个四字向量操作数执行运算。 此类指令生成四字向量结果。 所生成的元素和第一个操作数的元素是第二个操作数元素宽度的两倍。 + + 通过将 W 追加到指令助记符来指定宽指令。 + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/HighPerformanceComputing/img/wide.PNG) + +* 4. 窄指令 Narrow instructions 操作四倍长字,生成双字 结果宽度一般是操作数的一半 + + 在指令中加N + + 四字向量操作数执行运算,并生成双字向量结果,所生成的元素一般是操作数元素宽度的一半。N标记,如VMOVN。 + + 窄指令对四字向量操作数执行运算,并生成双字向量结果。 所生成的元素通常是操作数元素宽度的一半。 + + 通过将 N 追加到指令助记符来指定窄指令。 + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/HighPerformanceComputing/img/narrow.PNG) + +* 5. 饱和指令 Saturating variants + + 通过在 V 和指令助记符之间使用 Q 前缀来指定饱和指令。 + + 对于有符号饱和运算,如果结果小于 –2^n,则返回的结果将为 –2^n; + + 对于无符号饱和运算,如果整个结果将是负值,那么返回的结果是 0;如果结果大于 2^n–1,则返回的结果将为 2^n–1; + + NEON中的饱和算法:通过在V和指令助记符之间使用Q前缀可以指定饱和指令,原理与上述内容相同。 + + 饱和指令:当超过数据类型指定到范围则自动限制在该范围内。Q标记,如VQSHRUN + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/HighPerformanceComputing/img/data-range.PNG) + +数据类型 x 的饱和范围 (s 就是signed,有符号的意思,u就是unsigned,无符号的意思) + + s8 –2^7 <= x < 2^7 + s16 –2^15 <= x < 2^15 + s32 –2^31 <= x < 2^31 + s64 –2^63 <= x < 2^63 + u8 0 <= x < 2^8 + u16 0 <= x < 2^16 + u32 0 <= x < 2^32 + u64 0 <= x < 2^64 + + +> **NEON指令集(重点)ARMv7/AArch32指令格式** + +所有的支持NEON指令都有一个助记符V,下面以32位指令为例,说明指令的一般格式: + +V{}{}{}{.}{}, src1, src2 + +> 可选: + + Q: Staturating饱和结果,The instruction uses saturating arithmetic, so that the result is saturated within the range of the specified data type, such as VQABS, VQSHLetc. + + VQADD.S16 D0, D2, D3 + + H: Halving,半结果,结果右移动移位,相当于得到结构后在除以2 The instruction will halve the result. It does this by shifting right by one place (effectively a divide by two with truncation), such as VHADD,VHSUB. + + VHADD.S16 Q0, Q1, Q4 + + D: Doubling,双倍结果 The instruction doubles the result, such as VQDMULL, VQDMLAL, VQDMLSL and VQ{R}DMULH. + + VQDMULL.S16 Q0, D1, D3 双倍+饱和+长指令 + + + R: Rounding,取整 The instruction will perform rounding on the result, equivalent to adding 0.5 to the result before truncating, such as VRHADD, VRSHR. + + VRSUBHN.I16 D0, Q1, Q3 + + +> : 必须 + +the operation (for example, ADD加, SUB减, MUL乘). + +NEON指令按照作用可以分为:加载数据、存储数据、加减乘除运算、逻辑AND/OR/XOR运算、比较大小运算 + +> shape指令类型 可选: + +即前文中的Long (L长指令,结果数据位扩大), Wide (W), Narrow (N结果数据位变窄). + +> Condition 可选, + + used with IT instruction. +> <.dt> Datatype 可选 数据类型 .数据类型 前面有点 + + such as .s8, .u8, .f32 , .I16, .S16 etc. + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/HighPerformanceComputing/img/dtypr.PNG) + + +> Destination. 可选 目标操作数地址 + +> Source operand 1. 必须 源操作数地址 +> Source operand 2. 必须 源操作数地址 + + +注: {} 表示可选的参数。 + +比如: + +VADD.I16 D0, D1, D2 @ 16位整数 加法 + +VMLAL.S16 Q2, D8, D9 @ 有符号16位整数 乘加 + +> 使用NEON主要有四种方法: + +* 1. NEON优化库(Optimized libraries) +* 2. 向量化编译器(Vectorizing compilers) +* 3. NEON intrinsics +* 4. NEON assembly + +根据优化程度需求不同,第4种最为底层,若熟练掌握效果最佳,一般也会配合第3种一起使用。 + +1. 优化库 Libraries:直接在程序中调用优化库 + + OpenMax DL:支持加速视频编解码、信号处理、色彩空间转换等; + + Ne10:一个ARM的开源项目,提供数学运算、图像处理、FFT函数等。 + +2. 向量化编译 Vectorizing compilers:GCC编译器的向量优化选项 + +在GCC选项中加入向量化表示能有助于C代码生成NEON代码,如‐ftree‐vectorize。 + + +3. NEON intrinsics:提供了一个连接NEON操作的C函数接口,编译器会自动生成相关的NEON指令,支持ARMv7或ARMv8平台。 + +[所有的intrinsics函数都在GNU官方说明文档 ](https://gcc.gnu.org/onlinedocs/gcc-4.7.4/gcc/ARM-NEON-Intrinsics.html#ARM-NEON-Intrinsics) + +## 3. NEON Instrinsic函数 + +NEON Instrinsic是编译器支持的一种buildin类型和函数的集合,基本涵盖NEON的所有指令,通常这些Instrinsic包含在arm_neon.h头文件中。 + +[ARM-NEON-Intrinsics](https://gcc.gnu.org/onlinedocs/gcc-4.6.1/gcc/ARM-NEON-Intrinsics.html) + +[使用ARM NEON Intrinsics加速Video Codec 参考](https://www.jianshu.com/p/70601b36540f) + +### 数据类型 + +NEON 向量数据类型是根据以下模式命名的:x_t + +例如,int16x4_t 是一个包含四条向量线的向量,每条向量线包含一个有符号 16位整数。 + +NEON Intrinsics内置的整数数据类型主要包括以下几种: + +* (u)int8x8_t; +* (u)int8x16_t; +* (u)int16x4_t; +* (u)int16x8_t; +* (u)int32x2_t; +* (u)int32x4_t; +* (u)int64x1_t; + +其中,第一个数字代表的是数据类型宽度为8/16/32/64位,第二个数字代表的是一个寄存器中该类型数据的数量。如int16x8_t代表16位有符号数,寄存器中共有8个数据。 + +某些内在函数使用以下格式的向量类型数组: + +xx_t + +这些类型被视为包含名为 val 的单个元素的普通 C 结构。 + +以下是一个结构定义示例: +```c +struct int16x4x2_t +{ +int16x4_t val[2]; +}; +``` + +标号和具体类型转换: + + 标记 双字64位D寄存器 四字128位寄存器 + s8 int8x8_t int8x16_t 有符号整数 + s16 int16x4_t int16x8_t + s32 int32x2_t int32x4_t + s64 int64x1_t int64x2_t + u8 uint8x8_t uint8x16_t 无符号整数 + u16 uint16x4_t uint16x8_t + u32 uint32x2_t uint32x4_t + u64 uint64x1_t uint64x2_t + f16 float16x4_t float16x8_t 浮点数 + f32 float32x2_t float32x4_t + p8 poly8x8_t poly8x16_t 多项式数 + p16 poly16x4_t poly16x8_t + +vcombine_type() 连接组合函数 结果类型长度加倍 + +vget_high_type() 获取高位 结果类型长度减半 + +vget_low_type() 获取低位 结果类型长度减半 + +长指令类型 结果类型长度加倍 + +窄指令类型 结果类型长度减半 + + + +### 内在函数 inline function +每个内在函数的格式如下: + +_ + +另外提供 q 标记来指定内在函数对 128 位向量进行运算。 + +例如: + +* vmul_s16,表示两个有符号 16 位值的向量相乘multiply。 +这编译为 VMUL.I16 d2, d0, d1。 + +* vaddl_u8,l为long长指令标识,是指两个包含无符号 8 位值的 64 位向量按长型相加,结果为无符号 16 位值的 128 位向量。 +这编译为 VADDL.U8 q1, d0, d1。 + +* int8_t vget_lane_s8 (int8x8_t __a, const int __b); + +v是向量操作,可以认为就是neon函数,shr是右移位,lane表示操作向量中的某个元素,s8表示结果是s8类型(向量) + +* int8x8_t vget_high_s8 (int8x16_t __a); //ri = a(i+4); + +v是向量操作,可以认为就是neon函数,get是取值,high表示取高64位,s8表示结果是s8类型(向量) + +* int8x8_t vget_low_s8 (int8x16_t __a); //ri = ai; + +v是向量操作,可以认为就是neon函数,get是取值,low表示取低64为,s8表示结果是s8类型(向量) + + vq<饱和操作>ops<具体操作>tyep<指令类型 q,l,w,n>_flag<标识 n,lane,high or low>_dtype<返回值类型或参数类型> + + add 加法 + mul 乘法 + sub 减法 + mla 乘加 + mls 乘减 + ceq 比较,类似与 == + cge 比较,类似与 >= + cle 比较,类似与 <= + cgt 比较,类似与 > + clt 比较,类似与 < + tst 做与运算后,判断是否等于0 ,ri = (ai & bi != 0) ? 1…1:0…0; + abd 两个向量相减后的绝对值,vabd -> ri = |ai - bi|; + max 求最大值,ri = ai >= bi ? ai : bi; + min 求最小值,ri = ai >= bi ? bi : ai; + shl 左移位, ri = ai << b; + shr 右移位, ri = ai >> b; + abs 求绝对值,ri = |ai|; + neg 取反,ri = -ai; + mvn 按位取反,ri = ~ai; + and 与运算,ri = ai & bi; + orr 或运算,ri = ai | bi; + eor 异或运算,ri = ai ^ bi; + cls 计算连续相同的位数 + get 取值,从向量中取出一个值,所谓的向量可以认为是一个数组,给数组中的某个元素赋值 + set 赋值,给向量中赋值 + dup 构造一个向量,并赋上初始值,ri = a; + combine 合并操作,把两个向量合并 + mov 改变数据类型,数据范围,比如把u8 变成u16,或者u16变成u8 + zip 压缩操作 + uzp 解压操作 + ld1 加载数据,给定的buffer 指针中拷贝数据,注意是ld后面的是数字1,而不是字母l + st1 拷贝数据,将neon数据类型拷贝到指定buffer中 + + +〉**示例函数指令分析** +```c +int16x8_t vqaddq_s16 (int16x8_t, int16x8_t) +int16x4_t vqadd_s16 (int16x4_t, int16x4_t) +``` + +* 第一个字母'v'指明是vector向量指令,也就是NEON指令; +* 第二个字母'q'指明是饱和指令,即后续的加法结果会自动饱和; +* 第三个字段'add'指明是加法指令; +* 第四个字段'q'指明操作寄存器宽度,为'q'时操作QWORD, 为128位;未指明时操作寄存器为DWORD,为64位; +* 第五个字段's16'指明操作的基本单元为有符号16位整数,其最大表示范围为-32768 ~ 32767; +* 第六个字段为空,普通指令,形参和返回值类型约定与C语言一致。 + +其它可能用到的助记符包括: + +* l 长指令,数据扩展,双字运算得到四字结果 +* w 宽指令,数据对齐,双字和四字运算得到四字结果 +* n 窄指令, 数据压缩,四字运算得到双字结果 + +> 示例2 +```c +uint8x8_t vld1_u8 (const uint8_t *) +``` +* 第一个字母'v'指明是vector向量指令,也就是NEON指令; +* 第二个字段'ld'表示加载指令 load +* 第三个字段'1'(注意是1,不是l)表示顺次加载。如果需要处理图像的RGB分量,可能会用到vld3间隔3个单元加载。 + + +NEON指令按照作用可以分为:加载数据、存储数据、加减乘除运算、逻辑AND/OR/XOR运算、比较大小运算 + +> **初始化寄存器** +```c +// 寄存器的每个lane(通道)都赋值为一个值N +Result_t vcreate_type(Scalar_t N) // type需要换成具体类型 s8, u8, f32, I16, S16 +Result_t vdup_type(Scalar_t N) // vcreate_s8 vdup_s8 vmov_s8 +Result_t vmov_type(Scalar_t N) +``` +> **加载load 内存数据进寄存器** +```c +// 间隔为x,加载数据进NEON寄存器, 间隔:交叉存取,是ARM NEON特有的指令 +Result_t vld[x]_type(Scalar_t* N) // +Result_t vld[x]q_type(Scalar_t* N) // vld1q_s32 间隔1 即连续内存访问, + +// **通过将 Q 附加到指令助记符,可以指定正常指令的操作数和结果必须全部为四字。** + +float32x4x3_t = vld3q_f32(float32_t* ptr) +// 此处间隔为3,即交叉读取12个float32进3个NEON寄存器中。 +// 3个寄存器的值分别为: +// {ptr[0],ptr[3],ptr[6],ptr[9]}, // 128为Q寄存器 +// {ptr[1],ptr[4],ptr[7],ptr[10]}, +// {ptr[2],ptr[5],ptr[8],ptr[11]}。 +``` + +* 1. VLD1是最简单的形式,从内存加载1~4个寄存器的数据,没有deinterleave,即线性加载; + +* 2. VLD2加载2或者4个寄存器的数据,解交织奇偶元素到各自的寄存器,这样很容易的把交织的立体声音频数据分解为左右声道的数据; + +* 3. VLD3加载3个寄存器的数据,很方便的把RGB的数据分为R、G、B通道; + +* 4. VLD4加载4个寄存器的数据,解交织,用于分解ARGB图像数据; + + +> **存储set 寄存器数据到内存 间隔为x,存储NEON寄存器的数据到内存中** +```cpp +void vst[x]_type(Scalar_t* N) +void vst[x]q_type(Scalar_t* N) +``` + +> **算数运算指令** + +[普通指令] 普通加法运算 res = M+N +```c +Result_t vadd_type(Vector_t M,Vector_t N) +Result_t vaddq_type(Vector_t M,Vector_t N) + +``` +[长指令 long] 变长加法运算 res = M+N + +为了防止溢出,一种做法是使用如下指令,加法结果存储到长度x2的寄存器中, + +如: +```c + +Result_t vaddl_type(Vector_t M,Vector_t N) + +vuint16x8_t res = vaddl_u8(uint8x8_t M,uint8x8_t N) +``` + +[宽指令] 加法运算 res = M+N,第一个参数M宽度大于第二个参数N。 +```c +Result_t vaddw_type(Vector_t M,Vector_t N) +``` + +[普通指令] 减法运算 res = M-N +```c +Result_t vsub_type(Vector_t M,Vector_t N) +``` + +[普通指令] 乘法运算 res = M*N +```c +Result_t vmul_type(Vector_t M,Vector_t N) +Result_t vmulq_type(Vector_t M,Vector_t N) +``` + +[普通指令] 乘&加法运算 res = M + N*P +```c +Result_t vmla_type(Vector_t M,Vector_t N,Vector_t P) +Result_t vmlaq_type(Vector_t M,Vector_t N,Vector_t P) +``` + +乘&减法运算 res = M-N*P +```c +Result_t vmls_type(Vector_t M,Vector_t N,Vector_t P) +Result_t vmlsq_type(Vector_t M,Vector_t N,Vector_t P) +``` + +> **数据处理指令** + +[普通指令] 计算绝对值 res=abs(M) +```c +Result_t vabs_type(Vector_t M) +``` +[普通指令] 计算负值 res=-M negative +```c +Result_t vneg_type(Vector_t M) +``` +[普通指令] 计算最大值 res=max(M,N) maxmum +```c +Result_t vmax_type(Vector_t M,Vector_t N) +``` +[普通指令] 计算最小值 res=min(M,N) +```c +Result_t vmin_type(Vector_t M,Vector_t N) +``` + +> **比较指令** + +[普通指令] 比较是否相等 res=mask(M == N) compare equal +```c +Result_t vceg_type(Vector_t M,Vector_t N) +``` +[普通指令] 比较是否大于或等于 res=mask(M >= N) compare greate and equal +```c +Result_t vcge_type(Vector_t M,Vector_t N) +``` +[普通指令] 比较是否大于 res=mask(M > N) +```c +Result_t vcgt_type(Vector_t M,Vector_t N) +``` +[普通指令] 比较是否小于或等于 res=mask(M <= N) compare little and equal +```c +Result_t vcle_type(Vector_t M,Vector_t N) +``` +[普通指令] 比较是否小于 res=mask(M < N) compare little +```c +Result_t vclt_type(Vector_t M,Vector_t N) +``` +#### 向量加法: + +> **正常向量加法 vadd -> Vr[i]:=Va[i]+Vb[i]** +Vr、Va、Vb 具有相等的向量线大小。 +```c +//64位== +int8x8_t vadd_s8(int8x8_t a, int8x8_t b); // VADD.I8 d0,d0,d0 +int16x4_t vadd_s16(int16x4_t a, int16x4_t b); // VADD.I16 d0,d0,d0 +int32x2_t vadd_s32(int32x2_t a, int32x2_t b); // VADD.I32 d0,d0,d0 +int64x1_t vadd_s64(int64x1_t a, int64x1_t b); // VADD.I64 d0,d0,d0 +float32x2_t vadd_f32(float32x2_t a, float32x2_t b); // VADD.F32 d0,d0,d0 +uint8x8_t vadd_u8(uint8x8_t a, uint8x8_t b); // VADD.I8 d0,d0,d0 +uint16x4_t vadd_u16(uint16x4_t a, uint16x4_t b); // VADD.I16 d0,d0,d0 +uint32x2_t vadd_u32(uint32x2_t a, uint32x2_t b); // VADD.I32 d0,d0,d0 +uint64x1_t vadd_u64(uint64x1_t a, uint64x1_t b); // VADD.I64 d0,d0,d0 +//128位== +int8x16_t vaddq_s8(int8x16_t a, int8x16_t b); // VADD.I8 q0,q0,q0 +int16x8_t vaddq_s16(int16x8_t a, int16x8_t b); // VADD.I16 q0,q0,q0 +int32x4_t vaddq_s32(int32x4_t a, int32x4_t b); // VADD.I32 q0,q0,q0 +int64x2_t vaddq_s64(int64x2_t a, int64x2_t b); // VADD.I64 q0,q0,q0 +float32x4_t vaddq_f32(float32x4_t a, float32x4_t b); // VADD.F32 q0,q0,q0 +uint8x16_t vaddq_u8(uint8x16_t a, uint8x16_t b); // VADD.I8 q0,q0,q0 +uint16x8_t vaddq_u16(uint16x8_t a, uint16x8_t b); // VADD.I16 q0,q0,q0 +uint32x4_t vaddq_u32(uint32x4_t a, uint32x4_t b); // VADD.I32 q0,q0,q0 +uint64x2_t vaddq_u64(uint64x2_t a, uint64x2_t b); // VADD.I64 q0,q0,q0 +``` + +> **向量长型加法:vaddl -> Vr[i]:=Va[i]+Vb[i]** + +Va、Vb 具有相等的向量线大小,结果为向量线宽度变成两倍的 128 位向量。 +```c +int16x8_t vaddl_s8(int8x8_t a, int8x8_t b); // VADDL.S8 q0,d0,d0 +int32x4_t vaddl_s16(int16x4_t a, int16x4_t b); // VADDL.S16 q0,d0,d0 +int64x2_t vaddl_s32(int32x2_t a, int32x2_t b); // VADDL.S32 q0,d0,d0 +uint16x8_t vaddl_u8(uint8x8_t a, uint8x8_t b); // VADDL.U8 q0,d0,d0 +uint32x4_t vaddl_u16(uint16x4_t a, uint16x4_t b); // VADDL.U16 q0,d0,d0 +uint64x2_t vaddl_u32(uint32x2_t a, uint32x2_t b); // VADDL.U32 q0,d0,d0 + +``` +> **向量宽型加法:vaddw -> Vr[i]:=Va[i]+Vb[i] 64位与128位运算得到128位** +```c +int16x8_t vaddw_s8(int16x8_t a, int8x8_t b); // VADDW.S8 q0,q0,d0 +int32x4_t vaddw_s16(int32x4_t a, int16x4_t b); // VADDW.S16 q0,q0,d0 +int64x2_t vaddw_s32(int64x2_t a, int32x2_t b); // VADDW.S32 q0,q0,d0 +uint16x8_t vaddw_u8(uint16x8_t a, uint8x8_t b); // VADDW.U8 q0,q0,d0 +uint32x4_t vaddw_u16(uint32x4_t a, uint16x4_t b); // VADDW.U16 q0,q0,d0 +uint64x2_t vaddw_u32(uint64x2_t a, uint32x2_t b); // VADDW.U32 q0,q0,d0 +``` +> **向量半加:vhadd -> Vr[i]:=(Va[i]+Vb[i])>>1 求和后除以2** +```c +//64位 +int8x8_t vhadd_s8(int8x8_t a, int8x8_t b); // VHADD.S8 d0,d0,d0 +int16x4_t vhadd_s16(int16x4_t a, int16x4_t b); // VHADD.S16 d0,d0,d0 +int32x2_t vhadd_s32(int32x2_t a, int32x2_t b); // VHADD.S32 d0,d0,d0 +uint8x8_t vhadd_u8(uint8x8_t a, uint8x8_t b); // VHADD.U8 d0,d0,d0 +uint16x4_t vhadd_u16(uint16x4_t a, uint16x4_t b); // VHADD.U16 d0,d0,d0 +uint32x2_t vhadd_u32(uint32x2_t a, uint32x2_t b); // VHADD.U32 d0,d0,d0 +// 128位 +int8x16_t vhaddq_s8(int8x16_t a, int8x16_t b); // VHADD.S8 q0,q0,q0 +int16x8_t vhaddq_s16(int16x8_t a, int16x8_t b); // VHADD.S16 q0,q0,q0 +int32x4_t vhaddq_s32(int32x4_t a, int32x4_t b); // VHADD.S32 q0,q0,q0 +uint8x16_t vhaddq_u8(uint8x16_t a, uint8x16_t b); // VHADD.U8 q0,q0,q0 +uint16x8_t vhaddq_u16(uint16x8_t a, uint16x8_t b); // VHADD.U16 q0,q0,q0 +uint32x4_t vhaddq_u32(uint32x4_t a, uint32x4_t b); // VHADD.U32 q0,q0,q0 +``` + +> **向量舍入半加:vrhadd -> Vr[i]:=(Va[i]+Vb[i]+1)>>1 求和再加1后除以2** + +```c +//64位 +int8x8_t vrhadd_s8(int8x8_t a, int8x8_t b); // VRHADD.S8 d0,d0,d0 +int16x4_t vrhadd_s16(int16x4_t a, int16x4_t b); // VRHADD.S16 d0,d0,d0 +int32x2_t vrhadd_s32(int32x2_t a, int32x2_t b); // VRHADD.S32 d0,d0,d0 +uint8x8_t vrhadd_u8(uint8x8_t a, uint8x8_t b); // VRHADD.U8 d0,d0,d0 +uint16x4_t vrhadd_u16(uint16x4_t a, uint16x4_t b); // VRHADD.U16 d0,d0,d0 +uint32x2_t vrhadd_u32(uint32x2_t a, uint32x2_t b); // VRHADD.U32 d0,d0,d0 +//128位 +int8x16_t vrhaddq_s8(int8x16_t a, int8x16_t b); // VRHADD.S8 q0,q0,q0 +int16x8_t vrhaddq_s16(int16x8_t a, int16x8_t b); // VRHADD.S16 q0,q0,q0 +int32x4_t vrhaddq_s32(int32x4_t a, int32x4_t b); // VRHADD.S32 q0,q0,q0 +uint8x16_t vrhaddq_u8(uint8x16_t a, uint8x16_t b); // VRHADD.U8 q0,q0,q0 +uint16x8_t vrhaddq_u16(uint16x8_t a, uint16x8_t b); // VRHADD.U16 q0,q0,q0 +uint32x4_t vrhaddq_u32(uint32x4_t a, uint32x4_t b); // VRHADD.U32 q0,q0,q0 +``` +> **向量饱和加法:vqadd -> Vr[i]:=sat(Va[i]+Vb[i])** + +```c +//64位 +int8x8_t vqadd_s8(int8x8_t a, int8x8_t b); // VQADD.S8 d0,d0,d0 +int16x4_t vqadd_s16(int16x4_t a, int16x4_t b); // VQADD.S16 d0,d0,d0 +int32x2_t vqadd_s32(int32x2_t a, int32x2_t b); // VQADD.S32 d0,d0,d0 +int64x1_t vqadd_s64(int64x1_t a, int64x1_t b); // VQADD.S64 d0,d0,d0 +uint8x8_t vqadd_u8(uint8x8_t a, uint8x8_t b); // VQADD.U8 d0,d0,d0 +uint16x4_t vqadd_u16(uint16x4_t a, uint16x4_t b); // VQADD.U16 d0,d0,d0 +uint32x2_t vqadd_u32(uint32x2_t a, uint32x2_t b); // VQADD.U32 d0,d0,d0 +uint64x1_t vqadd_u64(uint64x1_t a, uint64x1_t b); // VQADD.U64 d0,d0,d0 +//128位 前面的q表示饱和运算,后面的q表示q寄存器,128位寄存器操作数 +int8x16_t vqaddq_s8(int8x16_t a, int8x16_t b); // VQADD.S8 q0,q0,q0 +int16x8_t vqaddq_s16(int16x8_t a, int16x8_t b); // VQADD.S16 q0,q0,q0 +int32x4_t vqaddq_s32(int32x4_t a, int32x4_t b); // VQADD.S32 q0,q0,q0 +int64x2_t vqaddq_s64(int64x2_t a, int64x2_t b); // VQADD.S64 q0,q0,q0 +uint8x16_t vqaddq_u8(uint8x16_t a, uint8x16_t b); // VQADD.U8 q0,q0,q0 +uint16x8_t vqaddq_u16(uint16x8_t a, uint16x8_t b); // VQADD.U16 q0,q0,q0 +uint32x4_t vqaddq_u32(uint32x4_t a, uint32x4_t b); // VQADD.U32 q0,q0,q0 +uint64x2_t vqaddq_u64(uint64x2_t a, uint64x2_t b); // VQADD.U64 q0,q0,q0 +``` +> **高位半部分向量加法:- > Vr[i]:=Va[i]+Vb[i]** +```c +int8x8_t vaddhn_s16(int16x8_t a, int16x8_t b); // VADDHN.I16 d0,q0,q0 +int16x4_t vaddhn_s32(int32x4_t a, int32x4_t b); // VADDHN.I32 d0,q0,q0 +int32x2_t vaddhn_s64(int64x2_t a, int64x2_t b); // VADDHN.I64 d0,q0,q0 +uint8x8_t vaddhn_u16(uint16x8_t a, uint16x8_t b); // VADDHN.I16 d0,q0,q0 +uint16x4_t vaddhn_u32(uint32x4_t a, uint32x4_t b); // VADDHN.I32 d0,q0,q0 +uint32x2_t vaddhn_u64(uint64x2_t a, uint64x2_t b); // VADDHN.I64 d0,q0,q0 +``` +> **高位半部分向量舍入加法** +```c +int8x8_t vraddhn_s16(int16x8_t a, int16x8_t b); // VRADDHN.I16 d0,q0,q0 +int16x4_t vraddhn_s32(int32x4_t a, int32x4_t b); // VRADDHN.I32 d0,q0,q0 +int32x2_t vraddhn_s64(int64x2_t a, int64x2_t b); // VRADDHN.I64 d0,q0,q0 +uint8x8_t vraddhn_u16(uint16x8_t a, uint16x8_t b); // VRADDHN.I16 d0,q0,q0 +uint16x4_t vraddhn_u32(uint32x4_t a, uint32x4_t b); // VRADDHN.I32 d0,q0,q0 +uint32x2_t vraddhn_u64(uint64x2_t a, uint64x2_t b); // VRADDHN.I64 d0,q0,q0 +``` + +#### 向量减法 + +>**正常向量减法 vsub -> Vr[i]:=Va[i]-Vb[i]** +```c +//64bits +int8x8_t vsub_s8(int8x8_t a, int8x8_t b); // VSUB.I8 d0,d0,d0 +int16x4_t vsub_s16(int16x4_t a, int16x4_t b); // VSUB.I16 d0,d0,d0 +int32x2_t vsub_s32(int32x2_t a, int32x2_t b); // VSUB.I32 d0,d0,d0 +int64x1_t vsub_s64(int64x1_t a, int64x1_t b); // VSUB.I64 d0,d0,d0 +float32x2_t vsub_f32(float32x2_t a, float32x2_t b); // VSUB.F32 d0,d0,d0 +uint8x8_t vsub_u8(uint8x8_t a, uint8x8_t b); // VSUB.I8 d0,d0,d0 +uint16x4_t vsub_u16(uint16x4_t a, uint16x4_t b); // VSUB.I16 d0,d0,d0 +uint32x2_t vsub_u32(uint32x2_t a, uint32x2_t b); // VSUB.I32 d0,d0,d0 +uint64x1_t vsub_u64(uint64x1_t a, uint64x1_t b); // VSUB.I64 d0,d0,d0 +//128bits +int8x16_t vsubq_s8(int8x16_t a, int8x16_t b); // VSUB.I8 q0,q0,q0 +int16x8_t vsubq_s16(int16x8_t a, int16x8_t b); // VSUB.I16 q0,q0,q0 +int32x4_t vsubq_s32(int32x4_t a, int32x4_t b); // VSUB.I32 q0,q0,q0 +int64x2_t vsubq_s64(int64x2_t a, int64x2_t b); // VSUB.I64 q0,q0,q0 +float32x4_t vsubq_f32(float32x4_t a, float32x4_t b); // VSUB.F32 q0,q0,q0 +uint8x16_t vsubq_u8(uint8x16_t a, uint8x16_t b); // VSUB.I8 q0,q0,q0 +uint16x8_t vsubq_u16(uint16x8_t a, uint16x8_t b); // VSUB.I16 q0,q0,q0 +uint32x4_t vsubq_u32(uint32x4_t a, uint32x4_t b); // VSUB.I32 q0,q0,q0 +uint64x2_t vsubq_u64(uint64x2_t a, uint64x2_t b); // VSUB.I64 q0,q0,q0 +``` + + +>**向量长型减法:vsubl -> Vr[i]:=Va[i]-Vb[i]** +```c +int16x8_t vsubl_s8(int8x8_t a, int8x8_t b); // VSUBL.S8 q0,d0,d0 +int32x4_t vsubl_s16(int16x4_t a, int16x4_t b); // VSUBL.S16 q0,d0,d0 +int64x2_t vsubl_s32(int32x2_t a, int32x2_t b); // VSUBL.S32 q0,d0,d0 +uint16x8_t vsubl_u8(uint8x8_t a, uint8x8_t b); // VSUBL.U8 q0,d0,d0 +uint32x4_t vsubl_u16(uint16x4_t a, uint16x4_t b); // VSUBL.U16 q0,d0,d0 +uint64x2_t vsubl_u32(uint32x2_t a, uint32x2_t b); // VSUBL.U32 q0,d0,d0 +``` + +>**向量宽型减法:vsubw -> Vr[i]:=Va[i]+Vb[i]** +```c +int16x8_t vsubw_s8(int16x8_t a, int8x8_t b); // VSUBW.S8 q0,q0,d0 +int32x4_t vsubw_s16(int32x4_t a, int16x4_t b); // VSUBW.S16 q0,q0,d0 +int64x2_t vsubw_s32(int64x2_t a, int32x2_t b); // VSUBW.S32 q0,q0,d0 +uint16x8_t vsubw_u8(uint16x8_t a, uint8x8_t b); // VSUBW.U8 q0,q0,d0 +uint32x4_t vsubw_u16(uint32x4_t a, uint16x4_t b); // VSUBW.U16 q0,q0,d0 +uint64x2_t vsubw_u32(uint64x2_t a, uint32x2_t b); // VSUBW.U32 q0,q0,d0 +``` + +>**向量饱和减法 vqsub-> Vr[i]:=sat(Va[i]-Vb[i])** + +```c +//64bits +int8x8_t vqsub_s8(int8x8_t a, int8x8_t b); // VQSUB.S8 d0,d0,d0 +int16x4_t vqsub_s16(int16x4_t a, int16x4_t b); // VQSUB.S16 d0,d0,d0 +int32x2_t vqsub_s32(int32x2_t a, int32x2_t b); // VQSUB.S32 d0,d0,d0 +int64x1_t vqsub_s64(int64x1_t a, int64x1_t b); // VQSUB.S64 d0,d0,d0 +uint8x8_t vqsub_u8(uint8x8_t a, uint8x8_t b); // VQSUB.U8 d0,d0,d0 +uint16x4_t vqsub_u16(uint16x4_t a, uint16x4_t b); // VQSUB.U16 d0,d0,d0 +uint32x2_t vqsub_u32(uint32x2_t a, uint32x2_t b); // VQSUB.U32 d0,d0,d0 +uint64x1_t vqsub_u64(uint64x1_t a, uint64x1_t b); // VQSUB.U64 d0,d0,d0 +//128bits +int8x16_t vqsubq_s8(int8x16_t a, int8x16_t b); // VQSUB.S8 q0,q0,q0 +int16x8_t vqsubq_s16(int16x8_t a, int16x8_t b); // VQSUB.S16 q0,q0,q0 +int32x4_t vqsubq_s32(int32x4_t a, int32x4_t b); // VQSUB.S32 q0,q0,q0 +int64x2_t vqsubq_s64(int64x2_t a, int64x2_t b); // VQSUB.S64 q0,q0,q0 +uint8x16_t vqsubq_u8(uint8x16_t a, uint8x16_t b); // VQSUB.U8 q0,q0,q0 +uint16x8_t vqsubq_u16(uint16x8_t a, uint16x8_t b); // VQSUB.U16 q0,q0,q0 +uint32x4_t vqsubq_u32(uint32x4_t a, uint32x4_t b); // VQSUB.U32 q0,q0,q0 +uint64x2_t vqsubq_u64(uint64x2_t a, uint64x2_t b); // VQSUB.U64 q0,q0,q0 +``` + +>**向量半减Vr[i]:=(Va[i]-Vb[i])>>1** +```c +int8x8_t vhsub_s8(int8x8_t a, int8x8_t b); // VHSUB.S8 d0,d0,d0 +int16x4_t vhsub_s16(int16x4_t a, int16x4_t b); // VHSUB.S16 d0,d0,d0 +int32x2_t vhsub_s32(int32x2_t a, int32x2_t b); // VHSUB.S32 d0,d0,d0 +uint8x8_t vhsub_u8(uint8x8_t a, uint8x8_t b); // VHSUB.U8 d0,d0,d0 +uint16x4_t vhsub_u16(uint16x4_t a, uint16x4_t b); // VHSUB.U16 d0,d0,d0 +uint32x2_t vhsub_u32(uint32x2_t a, uint32x2_t b); // VHSUB.U32 d0,d0,d0 +int8x16_t vhsubq_s8(int8x16_t a, int8x16_t b); // VHSUB.S8 q0,q0,q0 +int16x8_t vhsubq_s16(int16x8_t a, int16x8_t b); // VHSUB.S16 q0,q0,q0 +int32x4_t vhsubq_s32(int32x4_t a, int32x4_t b); // VHSUB.S32 q0,q0,q0 +uint8x16_t vhsubq_u8(uint8x16_t a, uint8x16_t b); // VHSUB.U8 q0,q0,q0 +uint16x8_t vhsubq_u16(uint16x8_t a, uint16x8_t b); // VHSUB.U16 q0,q0,q0 +uint32x4_t vhsubq_u32(uint32x4_t a, uint32x4_t b); // VHSUB.U32 q0,q0,q0 +``` + +#### 乘法 + +>**向量乘法:vmul -> Vr[i] := Va[i] * Vb[i]** +```c +//64bits=== +int8x8_t vmul_s8(int8x8_t a, int8x8_t b); // VMUL.I8 d0,d0,d0 +int16x4_t vmul_s16(int16x4_t a, int16x4_t b); // VMUL.I16 d0,d0,d0 +int32x2_t vmul_s32(int32x2_t a, int32x2_t b); // VMUL.I32 d0,d0,d0 +float32x2_t vmul_f32(float32x2_t a, float32x2_t b); // VMUL.F32 d0,d0,d0 +uint8x8_t vmul_u8(uint8x8_t a, uint8x8_t b); // VMUL.I8 d0,d0,d0 +uint16x4_t vmul_u16(uint16x4_t a, uint16x4_t b); // VMUL.I16 d0,d0,d0 +uint32x2_t vmul_u32(uint32x2_t a, uint32x2_t b); // VMUL.I32 d0,d0,d0 +poly8x8_t vmul_p8(poly8x8_t a, poly8x8_t b); // VMUL.P8 d0,d0,d0 +//128bits== +int8x16_t vmulq_s8(int8x16_t a, int8x16_t b); // VMUL.I8 q0,q0,q0 +int16x8_t vmulq_s16(int16x8_t a, int16x8_t b); // VMUL.I16 q0,q0,q0 +int32x4_t vmulq_s32(int32x4_t a, int32x4_t b); // VMUL.I32 q0,q0,q0 +float32x4_t vmulq_f32(float32x4_t a, float32x4_t b); // VMUL.F32 q0,q0,q0 +uint8x16_t vmulq_u8(uint8x16_t a, uint8x16_t b); // VMUL.I8 q0,q0,q0 +uint16x8_t vmulq_u16(uint16x8_t a, uint16x8_t b); // VMUL.I16 q0,q0,q0 +uint32x4_t vmulq_u32(uint32x4_t a, uint32x4_t b); // VMUL.I32 q0,q0,q0 +poly8x16_t vmulq_p8(poly8x16_t a, poly8x16_t b); // VMUL.P8 q0,q0,q0 + +``` +>**向量长型乘法:vmull -> Vr[i] := Va[i] * Vb[i]** +```c +int16x8_t vmull_s8(int8x8_t a, int8x8_t b); // VMULL.S8 q0,d0,d0 +int32x4_t vmull_s16(int16x4_t a, int16x4_t b); // VMULL.S16 q0,d0,d0 +int64x2_t vmull_s32(int32x2_t a, int32x2_t b); // VMULL.S32 q0,d0,d0 +uint16x8_t vmull_u8(uint8x8_t a, uint8x8_t b); // VMULL.U8 q0,d0,d0 +``` + +>**向量乘加:vmla -> Vr[i] := Va[i] + Vb[i] * Vc[i]** +```c +//64bits=== +int8x8_t vmla_s8(int8x8_t a, int8x8_t b, int8x8_t c); // VMLA.I8 d0,d0,d0 +int16x4_t vmla_s16(int16x4_t a, int16x4_t b, int16x4_t c); // VMLA.I16 d0,d0,d0 +int32x2_t vmla_s32(int32x2_t a, int32x2_t b, int32x2_t c); // VMLA.I32 d0,d0,d0 +float32x2_t vmla_f32(float32x2_t a, float32x2_t b, float32x2_t c); // VMLA.F32 d0,d0,d0 +uint8x8_t vmla_u8(uint8x8_t a, uint8x8_t b, uint8x8_t c); // VMLA.I8 d0,d0,d0 +uint16x4_t vmla_u16(uint16x4_t a, uint16x4_t b, uint16x4_t c); // VMLA.I16 d0,d0,d0 +uint32x2_t vmla_u32(uint32x2_t a, uint32x2_t b, uint32x2_t c); // VMLA.I32 d0,d0,d0 +//128bits== +int8x16_t vmlaq_s8(int8x16_t a, int8x16_t b, int8x16_t c); // VMLA.I8 q0,q0,q0 +int16x8_t vmlaq_s16(int16x8_t a, int16x8_t b, int16x8_t c); // VMLA.I16 q0,q0,q0 +int32x4_t vmlaq_s32(int32x4_t a, int32x4_t b, int32x4_t c); // VMLA.I32 q0,q0,q0 +float32x4_t vmlaq_f32(float32x4_t a, float32x4_t b, float32x4_t c); // VMLA.F32 q0,q0,q0 +uint8x16_t vmlaq_u8(uint8x16_t a, uint8x16_t b, uint8x16_t c); // VMLA.I8 q0,q0,q0 +uint16x8_t vmlaq_u16(uint16x8_t a, uint16x8_t b, uint16x8_t c); // VMLA.I16 q0,q0,q0 +uint32x4_t vmlaq_u32(uint32x4_t a, uint32x4_t b, uint32x4_t c); // VMLA.I32 q0,q0,q0 +``` + + +>**向量长型乘加:vmlal -> Vr[i] := Va[i] + Vb[i] * Vc[i]** +```c +int16x8_t vmlal_s8(int16x8_t a, int8x8_t b, int8x8_t c); // VMLAL.S8 q0,d0,d0 +int32x4_t vmlal_s16(int32x4_t a, int16x4_t b, int16x4_t c); // VMLAL.S16 q0,d0,d0 +int64x2_t vmlal_s32(int64x2_t a, int32x2_t b, int32x2_t c); // VMLAL.S32 q0,d0,d0 +uint16x8_t vmlal_u8(uint16x8_t a, uint8x8_t b, uint8x8_t c); // VMLAL.U8 q0,d0,d0 +uint32x4_t vmlal_u16(uint32x4_t a, uint16x4_t b, uint16x4_t c); // VMLAL.U16 q0,d0,d0 +uint64x2_t vmlal_u32(uint64x2_t a, uint32x2_t b, uint32x2_t c); // VMLAL.U32 q0,d0,d0 +``` + +>**向量乘减:vmls -> Vr[i] := Va[i] - Vb[i] * Vc[i]** +```c +//64bits== +int8x8_t vmls_s8(int8x8_t a, int8x8_t b, int8x8_t c); // VMLS.I8 d0,d0,d0 +int16x4_t vmls_s16(int16x4_t a, int16x4_t b, int16x4_t c); // VMLS.I16 d0,d0,d0 +int32x2_t vmls_s32(int32x2_t a, int32x2_t b, int32x2_t c); // VMLS.I32 d0,d0,d0 +float32x2_t vmls_f32(float32x2_t a, float32x2_t b, float32x2_t c); // VMLS.F32 d0,d0,d0 +uint8x8_t vmls_u8(uint8x8_t a, uint8x8_t b, uint8x8_t c); // VMLS.I8 d0,d0,d0 +uint16x4_t vmls_u16(uint16x4_t a, uint16x4_t b, uint16x4_t c); // VMLS.I16 d0,d0,d0 +uint32x2_t vmls_u32(uint32x2_t a, uint32x2_t b, uint32x2_t c); // VMLS.I32 d0,d0,d0 +//128bits== +int8x16_t vmlsq_s8(int8x16_t a, int8x16_t b, int8x16_t c); // VMLS.I8 q0,q0,q0 +int16x8_t vmlsq_s16(int16x8_t a, int16x8_t b, int16x8_t c); // VMLS.I16 q0,q0,q0 +int32x4_t vmlsq_s32(int32x4_t a, int32x4_t b, int32x4_t c); // VMLS.I32 q0,q0,q0 +float32x4_t vmlsq_f32(float32x4_t a, float32x4_t b, float32x4_t c); // VMLS.F32 q0,q0,q0 +uint8x16_t vmlsq_u8(uint8x16_t a, uint8x16_t b, uint8x16_t c); // VMLS.I8 q0,q0,q0 +uint16x8_t vmlsq_u16(uint16x8_t a, uint16x8_t b, uint16x8_t c); // VMLS.I16 q0,q0,q0 +uint32x4_t vmlsq_u32(uint32x4_t a, uint32x4_t b, uint32x4_t c); // VMLS.I32 q0,q0,q0 +``` + +>**向量长型乘减 vmlsl -> Vr[i] := Va[i] - Vb[i] * Vc[i]** +```c +int16x8_t vmlsl_s8(int16x8_t a, int8x8_t b, int8x8_t c); // VMLSL.S8 q0,d0,d0 +int32x4_t vmlsl_s16(int32x4_t a, int16x4_t b, int16x4_t c); // VMLSL.S16 q0,d0,d0 +int64x2_t vmlsl_s32(int64x2_t a, int32x2_t b, int32x2_t c); // VMLSL.S32 q0,d0,d0 +uint16x8_t vmlsl_u8(uint16x8_t a, uint8x8_t b, uint8x8_t c); // VMLSL.U8 q0,d0,d0 +uint32x4_t vmlsl_u16(uint32x4_t a, uint16x4_t b, uint16x4_t c); // VMLSL.U16 q0,d0,d0 +uint64x2_t vmlsl_u32(uint64x2_t a, uint32x2_t b, uint32x2_t c); // VMLSL.U32 q0,d0,d0 +``` + +#### 比较compare +提供一系列比较内在函数。如果对于一条向量线比较结果为 true,则该向量线的结果为将所有位设置为一。如果对于一条向量线比较结果为 false,则将所有位设置为零。返回类型是无符号整数类型。这意味着可以将比较结果用作 vbsl内在函数的第一个参数。 + + +>**向量比较 等于否 vceq_type vceqq_type compare equal** +```c +// 64位 +uint8x8_t vceq_s8(int8x8_t a, int8x8_t b); // VCEQ.I8 d0, d0, d0 +uint16x4_t vceq_s16(int16x4_t a, int16x4_t b); // VCEQ.I16 d0, d0, d0 +uint32x2_t vceq_s32(int32x2_t a, int32x2_t b); // VCEQ.I32 d0, d0, d0 +uint32x2_t vceq_f32(float32x2_t a, float32x2_t b); // VCEQ.F32 d0, d0, d0 +uint8x8_t vceq_u8(uint8x8_t a, uint8x8_t b); // VCEQ.I8 d0, d0, d0 +uint16x4_t vceq_u16(uint16x4_t a, uint16x4_t b); // VCEQ.I16 d0, d0, d0 +uint32x2_t vceq_u32(uint32x2_t a, uint32x2_t b); // VCEQ.I32 d0, d0, d0 +uint8x8_t vceq_p8(poly8x8_t a, poly8x8_t b); // VCEQ.I8 d0, d0, d0 +// 128位 +uint8x16_t vceqq_s8(int8x16_t a, int8x16_t b); // VCEQ.I8 q0, q0, q0 +uint16x8_t vceqq_s16(int16x8_t a, int16x8_t b); // VCEQ.I16 q0, q0, q0 +uint32x4_t vceqq_s32(int32x4_t a, int32x4_t b); // VCEQ.I32 q0, q0, q0 +uint32x4_t vceqq_f32(float32x4_t a, float32x4_t b); // VCEQ.F32 q0, q0, q0 +uint8x16_t vceqq_u8(uint8x16_t a, uint8x16_t b); // VCEQ.I8 q0, q0, q0 +uint16x8_t vceqq_u16(uint16x8_t a, uint16x8_t b); // VCEQ.I16 q0, q0, q0 +uint32x4_t vceqq_u32(uint32x4_t a, uint32x4_t b); // VCEQ.I32 q0, q0, q0 +uint8x16_t vceqq_p8(poly8x16_t a, poly8x16_t b); // VCEQ.I8 q0, q0, q0 +``` + +>**向量比较大于或等于 vcge vcgeq : compare greate or equal** +```c +// 64位 +uint8x8_t vcge_s8(int8x8_t a, int8x8_t b); // VCGE.S8 d0, d0, d0 +uint16x4_t vcge_s16(int16x4_t a, int16x4_t b); // VCGE.S16 d0, d0, d0 +uint32x2_t vcge_s32(int32x2_t a, int32x2_t b); // VCGE.S32 d0, d0, d0 +uint32x2_t vcge_f32(float32x2_t a, float32x2_t b); // VCGE.F32 d0, d0, d0 +uint8x8_t vcge_u8(uint8x8_t a, uint8x8_t b); // VCGE.U8 d0, d0, d0 +uint16x4_t vcge_u16(uint16x4_t a, uint16x4_t b); // VCGE.U16 d0, d0, d0 +uint32x2_t vcge_u32(uint32x2_t a, uint32x2_t b); // VCGE.U32 d0, d0, d0 + +// 128位 +uint8x16_t vcgeq_s8(int8x16_t a, int8x16_t b); // VCGE.S8 q0, q0, q0 +uint16x8_t vcgeq_s16(int16x8_t a, int16x8_t b); // VCGE.S16 q0, q0, q0 +uint32x4_t vcgeq_s32(int32x4_t a, int32x4_t b); // VCGE.S32 q0, q0, q0 +uint32x4_t vcgeq_f32(float32x4_t a, float32x4_t b); // VCGE.F32 q0, q0, q0 +uint8x16_t vcgeq_u8(uint8x16_t a, uint8x16_t b); // VCGE.U8 q0, q0, q0 +uint16x8_t vcgeq_u16(uint16x8_t a, uint16x8_t b); // VCGE.U16 q0, q0, q0 +uint32x4_t vcgeq_u32(uint32x4_t a, uint32x4_t b); // VCGE.U32 q0, q0, q0 + +``` + +>**向量比较小于或等于 vcle vcleq : compare little or equal** +```c +//64bits +uint8x8_t vcle_s8(int8x8_t a, int8x8_t b); // VCGE.S8 d0, d0, d0 +uint16x4_t vcle_s16(int16x4_t a, int16x4_t b); // VCGE.S16 d0, d0, d0 +uint32x2_t vcle_s32(int32x2_t a, int32x2_t b); // VCGE.S32 d0, d0, d0 +uint32x2_t vcle_f32(float32x2_t a, float32x2_t b); // VCGE.F32 d0, d0, d0 +uint8x8_t vcle_u8(uint8x8_t a, uint8x8_t b); // VCGE.U8 d0, d0, d0 +uint16x4_t vcle_u16(uint16x4_t a, uint16x4_t b); // VCGE.U16 d0, d0, d0 +uint32x2_t vcle_u32(uint32x2_t a, uint32x2_t b); // VCGE.U32 d0, d0, d0 +// 128bits +uint8x16_t vcleq_s8(int8x16_t a, int8x16_t b); // VCGE.S8 q0, q0, q0 +uint16x8_t vcleq_s16(int16x8_t a, int16x8_t b); // VCGE.S16 q0, q0, q0 +uint32x4_t vcleq_s32(int32x4_t a, int32x4_t b); // VCGE.S32 q0, q0, q0 +uint32x4_t vcleq_f32(float32x4_t a, float32x4_t b); // VCGE.F32 q0, q0, q0 +uint8x16_t vcleq_u8(uint8x16_t a, uint8x16_t b); // VCGE.U8 q0, q0, q0 +uint16x8_t vcleq_u16(uint16x8_t a, uint16x8_t b); // VCGE.U16 q0, q0, q0 +uint32x4_t vcleq_u32(uint32x4_t a, uint32x4_t b); // VCGE.U32 q0, q0, q0 +``` + +>**向量比较大于 vcgt vcgtq compare great ** +```c +// 64bits +uint8x8_t vcgt_s8(int8x8_t a, int8x8_t b); // VCGT.S8 d0, d0, d0 +uint16x4_t vcgt_s16(int16x4_t a, int16x4_t b); // VCGT.S16 d0, d0, d0 +uint32x2_t vcgt_s32(int32x2_t a, int32x2_t b); // VCGT.S32 d0, d0, d0 +uint32x2_t vcgt_f32(float32x2_t a, float32x2_t b); // VCGT.F32 d0, d0, d0 +uint8x8_t vcgt_u8(uint8x8_t a, uint8x8_t b); // VCGT.U8 d0, d0, d0 +uint16x4_t vcgt_u16(uint16x4_t a, uint16x4_t b); // VCGT.U16 d0, d0, d0 +uint32x2_t vcgt_u32(uint32x2_t a, uint32x2_t b); // VCGT.U32 d0, d0, d0 +// 128bits +uint8x16_t vcgtq_s8(int8x16_t a, int8x16_t b); // VCGT.S8 q0, q0, q0 +uint16x8_t vcgtq_s16(int16x8_t a, int16x8_t b); // VCGT.S16 q0, q0, q0 +uint32x4_t vcgtq_s32(int32x4_t a, int32x4_t b); // VCGT.S32 q0, q0, q0 +uint32x4_t vcgtq_f32(float32x4_t a, float32x4_t b); // VCGT.F32 q0, q0, q0 +uint8x16_t vcgtq_u8(uint8x16_t a, uint8x16_t b); // VCGT.U8 q0, q0, q0 +uint16x8_t vcgtq_u16(uint16x8_t a, uint16x8_t b); // VCGT.U16 q0, q0, q0 +uint32x4_t vcgtq_u32(uint32x4_t a, uint32x4_t b); // VCGT.U32 q0, q0, q0 +``` + +>**向量比较小于 vclt vcltq : compare little ** +```c +//64bits== +uint8x8_t vclt_s8(int8x8_t a, int8x8_t b); // VCGT.S8 d0, d0, d0 +uint16x4_t vclt_s16(int16x4_t a, int16x4_t b); // VCGT.S16 d0, d0, d0 +uint32x2_t vclt_s32(int32x2_t a, int32x2_t b); // VCGT.S32 d0, d0, d0 +uint32x2_t vclt_f32(float32x2_t a, float32x2_t b); // VCGT.F32 d0, d0, d0 +uint8x8_t vclt_u8(uint8x8_t a, uint8x8_t b); // VCGT.U8 d0, d0, d0 +uint16x4_t vclt_u16(uint16x4_t a, uint16x4_t b); // VCGT.U16 d0, d0, d0 +uint32x2_t vclt_u32(uint32x2_t a, uint32x2_t b); // VCGT.U32 d0, d0, d0 +// 128bits=== +uint8x16_t vcltq_s8(int8x16_t a, int8x16_t b); // VCGT.S8 q0, q0, q0 +uint16x8_t vcltq_s16(int16x8_t a, int16x8_t b); // VCGT.S16 q0, q0, q0 +uint32x4_t vcltq_s32(int32x4_t a, int32x4_t b); // VCGT.S32 q0, q0, q0 +uint32x4_t vcltq_f32(float32x4_t a, float32x4_t b); // VCGT.F32 q0, q0, q0 +uint8x16_t vcltq_u8(uint8x16_t a, uint8x16_t b); // VCGT.U8 q0, q0, q0 +uint16x8_t vcltq_u16(uint16x8_t a, uint16x8_t b); // VCGT.U16 q0, q0, q0 +uint32x4_t vcltq_u32(uint32x4_t a, uint32x4_t b); // VCGT.U32 q0, q0, q0 +``` + +>**向量绝对值比较大于或等于 vcage vcageq: compare abs great equal** +```c + +uint32x2_t vcage_f32(float32x2_t a, float32x2_t b); // VACGE.F32 d0, d0, d0 +uint32x4_t vcageq_f32(float32x4_t a, float32x4_t b); // VACGE.F32 q0, q0, q0 +``` + +>**向量绝对值比较小于或等于 vcale vcaleq: compare abs little equal ** +```c +uint32x2_t vcale_f32(float32x2_t a, float32x2_t b); // VACGE.F32 d0, d0, d0 +uint32x4_t vcaleq_f32(float32x4_t a, float32x4_t b); // VACGE.F32 q0, q0, q0 +``` + +>**向量绝对值比较大于 vcagt vcagtq: compare abs great** +```c +uint32x2_t vcagt_f32(float32x2_t a, float32x2_t b); // VACGT.F32 d0, d0, d0 +uint32x4_t vcagtq_f32(float32x4_t a, float32x4_t b); // VACGT.F32 q0, q0, q0 +``` + +>**向量绝对值比较小于 vcalt vcaltq:compare abs little** +```c +uint32x2_t vcalt_f32(float32x2_t a, float32x2_t b); // VACGT.F32 d0, d0, d0 +uint32x4_t vcaltq_f32(float32x4_t a, float32x4_t b); // VACGT.F32 q0, q0, q0 +``` + +>**向量测试位 test** +```c +uint8x8_t vtst_s8(int8x8_t a, int8x8_t b); // VTST.8 d0, d0, d0 +uint16x4_t vtst_s16(int16x4_t a, int16x4_t b); // VTST.16 d0, d0, d0 +uint32x2_t vtst_s32(int32x2_t a, int32x2_t b); // VTST.32 d0, d0, d0 +uint8x8_t vtst_u8(uint8x8_t a, uint8x8_t b); // VTST.8 d0, d0, d0 +uint16x4_t vtst_u16(uint16x4_t a, uint16x4_t b); // VTST.16 d0, d0, d0 +uint32x2_t vtst_u32(uint32x2_t a, uint32x2_t b); // VTST.32 d0, d0, d0 +uint8x8_t vtst_p8(poly8x8_t a, poly8x8_t b); // VTST.8 d0, d0, d0 + +uint8x16_t vtstq_s8(int8x16_t a, int8x16_t b); // VTST.8 q0, q0, q0 +uint16x8_t vtstq_s16(int16x8_t a, int16x8_t b); // VTST.16 q0, q0, q0 +uint32x4_t vtstq_s32(int32x4_t a, int32x4_t b); // VTST.32 q0, q0, q0 +uint8x16_t vtstq_u8(uint8x16_t a, uint8x16_t b); // VTST.8 q0, q0, q0 +uint16x8_t vtstq_u16(uint16x8_t a, uint16x8_t b); // VTST.16 q0, q0, q0 +uint32x4_t vtstq_u32(uint32x4_t a, uint32x4_t b); // VTST.32 q0, q0, q0 +uint8x16_t vtstq_p8(poly8x16_t a, poly8x16_t b); // VTST.8 q0, q0, q0 + +``` +#### 差值绝对值 +>**参数间的差值绝对值:Vr[i] = | Va[i] - Vb[i] | vabd: abs difference** +```c +int8x8_t vabd_s8(int8x8_t a, int8x8_t b); // VABD.S8 d0,d0,d0 +int16x4_t vabd_s16(int16x4_t a, int16x4_t b); // VABD.S16 d0,d0,d0 +int32x2_t vabd_s32(int32x2_t a, int32x2_t b); // VABD.S32 d0,d0,d0 +uint8x8_t vabd_u8(uint8x8_t a, uint8x8_t b); // VABD.U8 d0,d0,d0 +uint16x4_t vabd_u16(uint16x4_t a, uint16x4_t b); // VABD.U16 d0,d0,d0 +uint32x2_t vabd_u32(uint32x2_t a, uint32x2_t b); // VABD.U32 d0,d0,d0 +float32x2_t vabd_f32(float32x2_t a, float32x2_t b); // VABD.F32 d0,d0,d0 +// 128bits +int8x16_t vabdq_s8(int8x16_t a, int8x16_t b); // VABD.S8 q0,q0,q0 +int16x8_t vabdq_s16(int16x8_t a, int16x8_t b); // VABD.S16 q0,q0,q0 +int32x4_t vabdq_s32(int32x4_t a, int32x4_t b); // VABD.S32 q0,q0,q0 +uint8x16_t vabdq_u8(uint8x16_t a, uint8x16_t b); // VABD.U8 q0,q0,q0 +uint16x8_t vabdq_u16(uint16x8_t a, uint16x8_t b); // VABD.U16 q0,q0,q0 +uint32x4_t vabdq_u32(uint32x4_t a, uint32x4_t b); // VABD.U32 q0,q0,q0 +float32x4_t vabdq_f32(float32x4_t a, float32x4_t b); // VABD.F32 q0,q0,q0 +``` + +>**差值绝对值 - 长型 ** +```c +int16x8_t vabdl_s8(int8x8_t a, int8x8_t b); // VABDL.S8 q0,d0,d0 +int32x4_t vabdl_s16(int16x4_t a, int16x4_t b); // VABDL.S16 q0,d0,d0 +int64x2_t vabdl_s32(int32x2_t a, int32x2_t b); // VABDL.S32 q0,d0,d0 +uint16x8_t vabdl_u8(uint8x8_t a, uint8x8_t b); // VABDL.U8 q0,d0,d0 +uint32x4_t vabdl_u16(uint16x4_t a, uint16x4_t b); // VABDL.U16 q0,d0,d0 +uint64x2_t vabdl_u32(uint32x2_t a, uint32x2_t b); // VABDL.U32 q0,d0,d0 +``` +#### 加载存储指令 +>**加载并存储单个向量 加载并存储某类型的单个向量。vld1q_type** +```c + +``` +### 实例0:数组元素求和 +```c +// c版本======================= +#include +using namespace std; + +float sum_array(float *arr, int len) +{ + if(NULL == arr || len < 1) + { + cout<<"input error\n"; + return 0; + } + float sum(0.0); + for(int i=0; i +#include //需包含的头文件 +using namespace std; + +float sum_array(float *arr, int len) +{ + if(NULL == arr || len < 1) + { + cout<<"input error\n"; + return 0; + } + + int dim4 = len >> 2; // 数组长度除4整数 + int left4 = len & 3; // 数组长度除4余数,不够4的剩下的 + + float32x4_t sum_vec = vdupq_n_f32(0.0);//定义用于暂存累加结果的寄存器且初始化为0 + for (; dim4>0; dim4--, arr+=4) //每次同时访问4个数组元素 + { + float32x4_t data_vec = vld1q_f32(arr); //依次取4个元素存入寄存器vec + sum_vec = vaddq_f32(sum_vec, data_vec);//ri = ai + bi 计算两组寄存器对应元素之和并存放到相应结果 + } + float sum = vgetq_lane_f32(sum_vec, 0)+vgetq_lane_f32(sum_vec, 1)+vgetq_lane_f32(sum_vec, 2)+vgetq_lane_f32(sum_vec, 3);//将累加结果寄存器中的所有元素相加得到最终累加值 + for (; left4>0; left4--, arr++) + sum += (*arr) ; //对于剩下的少于4的数字,依次计算累加即可 + return sum; +} +``` + +上述算法的时间复杂度时O(N/4) +从上面的例子看出,使用NEON函数很简单,只需要将依次处理,变为批处理(如上面的每次处理4个)。 + +上面用到的函数有: +float32x4_t vdupq_n_f32 (float32_t value) +将value复制4分存到返回的寄存器中 + +float32x4_t vld1q_f32 (float32_t const * ptr) +从数组中依次Load4个元素存到寄存器中 + +相应的 有void vst1q_f32 (float32_t * ptr, float32x4_t val) +将寄存器中的值写入数组中 + +float32x4_t vaddq_f32 (float32x4_t a, float32x4_t b) +返回两个寄存器对应元素之和 r = a+b + +相应的 有float32x4_t vsubq_f32 (float32x4_t a, float32x4_t b) +返回两个寄存器对应元素之差 r = a-b + +float32_t vgetq_lane_f32 (float32x4_t v, const int lane) +返回寄存器某一lane的值 + +其他常用的函数还有: + +float32x4_t vmulq_f32 (float32x4_t a, float32x4_t b) +返回两个寄存器对应元素之积 r = a*b + +float32x4_t vmlaq_f32 (float32x4_t a, float32x4_t b, float32x4_t c) +乘加 r = a +b*c + +float32x4_t vmlsq_f32 (float32x4_t a, float32x4_t b, float32x4_t c) +乘减 r = a - b*c + +float32x4_t vextq_f32 (float32x4_t a, float32x4_t b, const int n) +拼接两个寄存器并返回从第n位开始的大小为4的寄存器 0<=n<=3 +例如 + + a: 1 2 3 4 + b: 5 6 7 8 + vextq_f32(a,b,1) -> r: 2 3 4 5 + vextq_f32(a,b,2) -> r: 3 4 5 6 + vextq_f32(a,b,3) -> r: 4 5 6 7 + +```c +float32x4_t sum = vdupq_n_f32(0); // sum四个通道全部赋值为0,sum={0,0,0,0} +float _a[] = {1,2,3,4}, _b[] = {5,6,7,8} ; +float32x4_t a = vld1q_f32(_a), b = vld1q_f32(_b) ;// 载入两个数组元素到 两个寄存器 + +//a的元素乘以b的第几个通道元素,然后后面的累加 +float32x4_t sum1 = vfmaq_laneq_f32(sum, a, b, 0); // sum1={5,10,15,20} +float32x4_t sum2 = vfmaq_laneq_f32(sum1, a, b, 1); +// sum2={5,10,15,20}+{6,12,18,24} = {11,22,33,44} + +float32x4_t sum3 = vfmaq_laneq_f32(sum2, a, b, 2); +// sum3={11,22,33,44}+{7,14,21,28} = {18,36,54,72} +``` + +[官方文档 其他常用函数](https://developer.arm.com/architectures/instruction-sets/simd-isas/neon/intrinsics) + +### 示例1:向量加法** +```c +// 假设 count 是4的倍数 +#include + +// C version +void add_int_c(int* dst, int* src1, int* src2, int count) +{ + int i; + for (i = 0; i < count; i++) + { + dst[i] = src1[i] + src2[i]; + } +} + +// NEON version +void add_float_neon1(int* dst, + int* src1, + int* src2, // 传入三个数据单元的指针(地址) + int count) // 数据量 假设为4的倍数 +{ + int i; + for (i = 0; i < count; i += 4) // 寄存器操作每次 进行4个数据的运输(单指令多数据SIMD) + { + int32x4_t in1, in2, out; + + // 1. 从内存 载入 数据 到寄存器 + in1 = vld1q_s32(src1);// intrinsics传入的为内存数据指针 + // v 表示neon函数 + // ld表示加载load + // q表示使用128位寄存器 + // s32,有符号32位整数,单个数据32,共有4个数据并行超声 + src1 += 4;// 数据 指针 递增+4 + + in2 = vld1q_s32(src2); + src2 += 4; + + // 2. 在寄存器中进行数据运算 加法add + out = vaddq_s32(in1, in2); + + // 3. 将寄存器中的结果 保存到 内存地址中 + vst1q_s32(dst, out); + dst += 4;// + } + // 实际情况,需要做最后不够4个的数的运输,使用普通c函数部分进行 + // 可参考下面的代码进行改进 +} + + +``` + +代码中的 vld1q_s32 会被编译器转换成 vld1.32 {d0, d1}, [r0] 指令, + +同理 vaddq_s32 被转换成 vadd.i32 q0, q0, q0, + + vst1q_s32 被转换成 vst1.32 {d0,d1}, [r0]。 + + + +### 示例2:向量乘法 + +```neon +//NRON优化的vector相乘 +static void neon_vector_mul( + const std::vector& vec_a, // 向量a 常量引用 + const std::vector& vec_b, // 向量b 常量引用 + std::vector& vec_result) // 结果向量 引用 +{ + assert(vec_a.size() == vec_b.size()); + assert(vec_a.size() == vec_result.size()); + int i = 0;// 向量索引 从0开始 + + //neon process + for (; i < (int)vec_result.size() - 3 ; i+=4)// 每一步会并行执行四个数(单指令多数据simd) 注意每次增加4 + {// 不够 4的部分留在后面用 普通 c代码运算 + // 从内存载入数据到寄存器 + const auto data_a = vld1q_f32(&vec_a[i]);// 函数传入的是 地址(指针) + const auto data_b = vld1q_f32(&vec_b[i]); + + float* dst_ptr = &vec_result[i];// 结果向量的地址(内存中) + + // 在寄存器中进行运算,乘法 mulp 运算 + const auto data_res = vmulq_f32(data_a, data_b); + + // 将处于寄存器中的结果 保存传输到 内存中国 + vst1q_f32(dst_ptr, data_res); + } + + // normal process 普通C代码 数据相乘= 剩余不够4个数的部分===可能为 1,2,3个数 + for (; i < (int)vec_result.size(); i++) + { + vec_result[i] = vec_a[i] * vec_b[i]; + } +} + +``` + +> 处理剩余的元素 +[参考](https://blog.csdn.net/hw5226349/article/details/45111237) + +* 1. Larger Arrays 扩展成更大的数组 + +如果改变你要处理的数组大小,比如增加数组大小到向量大小的整数倍,这样就能在最后一次数据处理时也按照向量大小处理而不会把临近的数据损坏。如上面的例子里,把数组大小增加到24个元素,这样就能用NEON用3次迭代完成所有的数据处理而不会损坏周边数据。 + +填补数组到向量的整数个大小: +![](https://github.com/Ewenwan/MVision/blob/master/CNN/HighPerformanceComputing/img/Large-Arrays.jpg) + +一些情况下,可能没法初始化填充的数据,无论填充什么都会影响计算的结果; + +* 2. Overlapping重叠计算 + +如果进行数据处理的操作合适的话,可以考虑把剩余部分的元素通过重叠计算的方式处理,这就会把某些重叠部分的元素计算两次。如下面的例子里,第一次迭代计算元素0到7,第一次计算5到12,第三次计算13到20。从而第一次计算和第二次计算重叠的元素5到7就被计算了两次。 + +重叠向量,在橙色区域的数据计算两次: +![](https://github.com/Ewenwan/MVision/blob/master/CNN/HighPerformanceComputing/img/Overlapping.jpg)) + +重叠处理只适用于需要处理的数组长度不会随着每次迭代而改变的情况,但不适用于每次迭代结果改变的情况,如累加计算,这样重叠部分的数据会被计算两次; + + +* 3. 单个元素的计算过程Single Elements + +NEON提供了能处理向量里的单一元素的加载和存储指令,用这些指令,你能加载包含一个元素的部分向量,处理它然后把结果保存到内存。如下面的例子,前两次的迭代处理跟前面类似,处理元素0到7以及8到15,剩下的5个元素可以在第三次迭代处理,加载处理并存储单一的元素。 + +处理单一的元素实例: + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/HighPerformanceComputing/img/Single-Elements.jpg)) + +这种方法比前面的两种方法速度要慢,每个元素的处理都需要单独进行; + +这种的剩余元素处理方法需要两个迭代循环,第一个处理向量的循环,还有处理剩余元素的循环,这会增加代码大小; + +NEON的单一元素加载只改变目标元素的值,而保留其他的元素不变,如果你向量计算的指令会在一个向量间反复计算,如VPADD,这些寄存器需要在第一个元素加载时初始化。 + + +* 4. 或者剩余的单个元素直接使用C语言进行计算 + + +### 示例3:从内存变量 加载数据 到 寄存器向量 +```c +#include +#include +unsigned short int A[] = {1,2,3,4}; + // 含有四个无符号短整型整数的数组 array with 4 elements +int main(void) +{ + uint16x4_t v; // 4通道16位的向量declare a vector of four 16-bit lanes + v = vld1_u16(A); // 从数组加载到向量load the array from memory into a vector + v = vadd_u16(v,v);// 每个元素加上自身,扩大一倍double each element in the vector + vst1_u16(A, v); // 存储结果回数组A store the vector back to memory + return 0; +} +``` + + +### 示例4:直接从数据创建vcreate_u8()寄存器变量 +```c +#include +int main (void) +{ + uint8x8_t v; // 定义一个8通道个8位数据的向量 + unsigned char A[8]; // 分配内存存储一个含有8个无符号字符数据的数组 + v = vcreate_u8(0x0102030405060708); // 创建一个8X8位向量,存储 1,2,3,4,5,6,7,8 + vst1_u8(A, v); // 将向量数据 存储到内存 + return 0; +} + +``` + +### 示例5:加载多个向量数据 +```c +#include +int main (void) +{ + uint8x8x3_t v; // 定义一个包含3个向量的向量数组,每个向量为8通道8位无符号整形 + unsigned char A[24]; // 定义一个包含24个无符号字节数据的数组,表示24个像素 + v = vld3_u8(A); // 从A处加载数据(多向量间隔加载) + // v.val[0] 是第一个向量={A[0],A[3],A[6],A[9],A[12],A[15],A[18],A[21]},RGB红色通道 + // v.val[1] 是第二个向量={A[1],A[4],A[7],A[10],A[13],A[16],A[19],A[22]},RGB绿色通道 + // v.val[2] 是第三个向量={A[2],A[5],A[8],A[11],A[14],A[17],A[20],A[23]},RGB蓝色通道 + v.val[0] = vadd_u8(v.val[0],v.val[0]);// 红色通道数值加倍 + vst3_u8(A, v); // 在把使用向量处理后的数据,存回内存数组A中 + return 0; +} + +``` +vld3_u8: + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/HighPerformanceComputing/img/rgb-3.PNG) + +vswp_u8: 交换R和B通道 + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/HighPerformanceComputing/img/rgb-bgr.jpg) + + +vld1_u8: + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/HighPerformanceComputing/img/rgb.PNG) + +加载和保存: + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/HighPerformanceComputing/img/rgb-store.PNG) + +### 示例6:数组矩阵相乘 + + 列主导4*4矩阵相乘: + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/HighPerformanceComputing/img/matrixMul.PNG) + +细节-结果矩阵的产生: + +![](https://github.com/Ewenwan/MVision/blob/master/CNN/HighPerformanceComputing/img/matrixMul_COL.PNG) + +结果矩阵的第一列: + +A矩阵第一列和B矩阵第一列的第一个元素相乘 + +A矩阵第二列和B矩阵第一列的第二个元素相乘 + +A矩阵第三列和B矩阵第一列的第三个元素相乘 + +A矩阵第四列和B矩阵第一列的第四个元素相乘 + +```c +void altneonmult(const float *matrixA, const float *matrixB, float *matrixR) +// matrixA \ matrixB \ matrixR均为 4*4 浮点数矩阵,列优先存储?? +// 计算过程为 matrixR = matrixA * matrixB +{ + float32x4_t a, b0, b1, b2, b3, r;// 4通道32位浮点数 行row 列column + a0 = vld1q_f32(matrixA); /* A矩阵第一列 从内存地址加载数据,连续加载,4个32位共128位数据*/ + a1 = vld1q_f32(matrixA + 4); /* A矩阵第二列*/ + a2 = vld1q_f32(matrixA + 8); /* A矩阵第三列*/ + a3 = vld1q_f32(matrixA + 12); /* A矩阵第四列 */ + +// 结果矩阵的第一列 + b = vld1q_f32(matrixB); /* B矩阵第一列 */ + r = vmulq_lane_f32(a0, vget_low_f32(b), 0); // A矩阵第一列 乘 B矩阵第一列的第一个元素 + r = vmlaq_lane_f32(r, a1, vget_low_f32(b), 1); // 乘加 + r = vmlaq_lane_f32(r, a2, vget_high_f32(b), 0); + r = vmlaq_lane_f32(r, a3, vget_high_f32(b), 1); + vst1q_f32(matrixR, r); /* store col 0 of result */ +// 结果矩阵的第二列 + b = vld1q_f32(matrixB + 4); /* B矩阵第二列 */ + r = vmulq_lane_f32(a0, vget_low_f32(b), 0); + r = vmlaq_lane_f32(r, a1, vget_low_f32(b), 1); + r = vmlaq_lane_f32(r, a2, vget_high_f32(b), 0); + r = vmlaq_lane_f32(r, a3, vget_high_f32(b), 1); + vst1q_f32(matrixR + 4, r); /* store col 1 of result */ +// 结果矩阵的第三列 + b = vld1q_f32(matrixB + 8); /* B矩阵第三列 */ + r = vmulq_lane_f32(a0, vget_low_f32(b), 0); + r = vmlaq_lane_f32(r, a1, vget_low_f32(b), 1); + r = vmlaq_lane_f32(r, a2, vget_high_f32(b), 0); + r = vmlaq_lane_f32(r, a3, vget_high_f32(b), 1); + vst1q_f32(matrixR + 8, r); /* store col 2 of result */ +// 结果矩阵的第四列 + b = vld1q_f32(matrixB + 12); /* B矩阵第四列 */ + r = vmulq_lane_f32(a0, vget_low_f32(b), 0); + r = vmlaq_lane_f32(r, a1, vget_low_f32(b), 1); + r = vmlaq_lane_f32(r, a2, vget_high_f32(b), 0); + r = vmlaq_lane_f32(r, a3, vget_high_f32(b), 1); + vst1q_f32(matrixR + 12, r); /* store col 3 of result */ +} + +// 先提取 再计算 最后存取 +void neonmult(const float *matrixA, const float *matrixB, float *matrixR) +{ +// 0. 定义变量 + float32x4_t a0, a1, a2, a3, b0, b1, b2, b3, r0, r1, r2, r3; + +// 1. 先提取每个矩阵的每一列 + a0 = vld1q_f32(matrixA); /* col 0 of matrixA */ + a1 = vld1q_f32(matrixA + 4); /* col 1 of matrixA */ + a2 = vld1q_f32(matrixA + 8); /* col 2 of matrixA */ + a3 = vld1q_f32(matrixA + 12); /* col 3 of matrixA */ + + b0 = vld1q_f32(matrixB); /* col 0 of matrixB */ + b1 = vld1q_f32(matrixB + 4); /* col 1 of matrixB */ + b2 = vld1q_f32(matrixB + 8); /* col 2 of matrixB */ + b3 = vld1q_f32(matrixB + 12); /* col 3 of matrixB */ + +// 2. 计算结果矩阵的每一列 + /* compute all the cols in the order specified by compiler */ + // 第一列 + r0 = vmulq_lane_f32(a0, vget_low_f32(b0), 0); // 乘 + r0 = vmlaq_lane_f32(r0, a1, vget_low_f32(b0), 1); // 乘加 + r0 = vmlaq_lane_f32(r0, a2, vget_high_f32(b0), 0);// 乘加 + r0 = vmlaq_lane_f32(r0, a3, vget_high_f32(b0), 1);// 乘加 + //第二列 + r1 = vmulq_lane_f32(a0, vget_low_f32(b1), 0); + r1 = vmlaq_lane_f32(r1, a1, vget_low_f32(b1), 1); + r1 = vmlaq_lane_f32(r1, a2, vget_high_f32(b1), 0); + r1 = vmlaq_lane_f32(r1, a3, vget_high_f32(b1), 1); + //第三列 + r2 = vmulq_lane_f32(a0, vget_low_f32(b2), 0); + r2 = vmlaq_lane_f32(r2, a1, vget_low_f32(b2), 1); + r2 = vmlaq_lane_f32(r2, a2, vget_high_f32(b2), 0); + r2 = vmlaq_lane_f32(r2, a3, vget_high_f32(b2), 1); + //第四列 + r3 = vmulq_lane_f32(a0, vget_low_f32(b3), 0); + r3 = vmlaq_lane_f32(r3, a1, vget_low_f32(b3), 1); + r3 = vmlaq_lane_f32(r3, a2, vget_high_f32(b3), 0); + r3 = vmlaq_lane_f32(r3, a3, vget_high_f32(b3), 1); + +// 3. 存储设置结果矩阵 + vst1q_f32(matrixR, r0); // 第一列 + vst1q_f32(matrixR + 4, r1);//第二列 + vst1q_f32(matrixR + 8, r2);//第三列 + vst1q_f32(matrixR + 12, r3);//第四列 +} +``` +### 示例7: 向量叉乘 Cross product + +a = [ai, aj, ak] + +b = [bi, bj, bk] + +> ** r = a 叉乘 b = [aj*bk-ak*bj, ak*bi-ai*bk, ai*bj-aj*bi]** + +```c +// Single cross product===== 单叉积? +void cross_product_s(float32_t *r, float32_t* a, float32_t* b) +{ + // 向量存储 ai bi在低地址,ak bk在高地址 + // 寄存器内存 register for example: + // [element3, element2, element1, element0] element0低地址 element3高地址 + float32x2_t vec_a_1 = vld1_f32(a + 1); //D register = [ak, aj] aj低地址 + float32x2_t vec_a_2 = vld1_f32(a); //D register = [aj, ai] ai低地址 + + float32x2_t vec_b_1 = vld1_f32(b + 1); //D register = [bk, bj] bj低地址 + float32x2_t vec_b_2 = vld1_f32(b); //D register = [bj, bi] bi低地址 + + // 寄存器合并 combine + float32x4_t vec_a = vcombine_f32(vec_a_1, vec_a_2); //Q register = [aj, ai, ak, aj] + float32x4_t vec_b = vcombine_f32(vec_b_1, vec_b_2); //Q register = [bj, bi, bk, bj] + // 寄存器移通道 低位通道数据到最高位通道,其他数据依次往低位通道移动 + float32x4_t vec_a_rot = vextq_f32(vec_a, vec_a, 1); //Q register = [ aj, aj, ai, ak ] + float32x4_t vec_b_rot = vextq_f32(vec_b, vec_b, 1); //Q register = [ bj, bj, bi, bk ] + + // vec_a = [ aj, ai, ak, aj ] + // vec_b_rot = [ bj, bj, bi, bk ] + // vec_a_rot = [ aj, aj, ai, ak ] + // vec_b = [ bj, bi, bk, bj ] + + float32x4_t prod = vmulq_f32(vec_a, vec_b_rot); // 乘 + // prod = [ ajbj, aibj, akbi, ajbk ] + + // vec_a_rot*vec_b = [aj*bj, aj*bi, ai*bk, ak*bj] + prod = vmlsq_f32(prod, vec_a_rot, vec_b);// 乘 再 减 prod - vec_a_rot * vec_b + // prod = [ ajbj-ajbj, aibj-ajbi, akbi-aibk, ajbk-akbj ] + + vst1_f32(r, vget_low_f32(prod)); // 先存储低位两个通道 [XXX, akbi-aibk, ajbk-akbj] + vst1_lane_f32(r + 2, vget_high_f32(prod), 0); // 再存储第三个通道 [aibj-ajbi, akbi-aibk, ajbk-akbj] +} + + +// Four cross products +void cross_product_q(float32_t* r, float32_t* a, float32_t* b) +{ + float32x4x3_t vec_a = vld3q_f32(a); // [,,,ai] 0 + // [,,,aj] 1 + // [,,,ak] 2 + + float32x4x3_t vec_b = vld3q_f32(b); // [,,,bi] 0 + // [,,,bj] 1 + // [,,,bk] 2 + float32x4x3_t result; + + result.val[0] = vmulq_f32(vec_a.val[1], vec_b.val[2]); // 乘 aj*bk + result.val[0] = vmlsq_f32(result.val[0], vec_a.val[2], vec_b.val[1]); // 乘减 aj*bk - ak*bj + + result.val[1] = vmulq_f32(vec_a.val[2], vec_b.val[0]); // 乘 ak*bi + result.val[1] = vmlsq_f32(result.val[1], vec_a.val[0], vec_b.val[2]); // 乘减 ak*bi - ai*bk + + result.val[2] = vmulq_f32(vec_a.val[0], vec_b.val[1]); // 乘 ai*bj + result.val[2] = vmlsq_f32(result.val[2], vec_a.val[1], vec_b.val[0]); // 乘减 ai*bj - aj*bi + + vst3q_f32(r, result); +} +``` + +### 示例7: 向量的点积 Dot product +A = (a1,a2,a3,...,an) + +B = (b1,b2,b3,...,bn) + +A * B = a1b1 + a2b2 + a3b3 + ... + anbn + +向量的每一维相乘然后相加,相乘之间具有良好的并行性,所以可以通过ARM NEON intrinsic指令进行加速。下面是代码实现: + +```c +// 浮点数 +float dot(float* A,float* B,int K) +{ + float sum=0; + float32x4_t sum_vec=vdupq_n_f32(0); // 和向量,从立即数创建数据 + float32x4_t left_vec,right_vec; // 向量A 和 向量 B + for(int k=0; k(input_top_ptr + input.offset())); +const float32x4_t middle_data = vld1q_f32(reinterpret_cast(input_middle_ptr + input.offset())); +const float32x4_t bottom_data = vld1q_f32(reinterpret_cast(input_bottom_ptr + input.offset())); + +float32x2_t res = {}; +if(pooling_type == PoolingType::AVG) +{// 均值池化============= + // Calculate scale + float scale = calculate_avg_scale(id, pool_size, upper_bound_w, upper_bound_h, pool_pad_x, pool_pad_y, pool_stride_x, pool_stride_y); + const float32x2_t scale_v = vdup_n_f32(scale);// 寄存器 初始化为 scale 2个32位 + + // Perform pooling + const float32x4_t sum_data = vaddq_f32(vaddq_f32(top_data, bottom_data), middle_data); + res = vpadd_f32(vget_high_f32(vsetq_lane_f32(0.f, sum_data, 3)), vget_low_f32(sum_data)); + res = vmul_f32(vpadd_f32(res, res), scale_v);// 得到4个最大的float +} +else +{// 最大值池化 + const float32x4_t max_data = vmaxq_f32(vmaxq_f32(top_data, bottom_data), middle_data); + res = vpmax_f32(vget_high_f32(vsetq_lane_f32(-std::numeric_limits::max(), max_data, 3)), vget_low_f32(max_data)); + res = vpmax_f32(res, res); +} + +*(reinterpret_cast(output.ptr())) = vget_lane_f32(res, 0); + +``` +## 4. NEON assembly + +采用汇编语言进行NEON(**NEON 汇编(assembly)**)的最底层优化,可以使优化性能最大化,但汇编语言比较灵活,手写汇编程序对开发人员来说具有较大挑战,如果使用不恰当,反而会影响优化性能。 + +NEON可以有两种写法: +* 1. Assembly文件: 纯汇编文件,后缀为”.S”或”.s”。注意对寄存器数据的保存。 +* 2. inline assembly内联汇编 + +在C/C++程序中编写汇编代码主要有两种形式:汇编函数或内联汇编。汇编函数中,需要声明代码段、操作堆栈等,过于复杂。而编写内联汇编,在C代码中需要以“asm”关键字标识,并在asm()编写汇编语句。这种方法只需要在待优化部分局部采用汇编语言实现,相对简单。 + + +### 数据加载保存移动 + +> **扩展 寄存器 加载和存储 指令** + +语法: +```asm +VLDR{cond}{.size} Fd, [Rn{, #offset}] # load加载,从内存中加载一个扩展寄存器。 +VSTR{cond}{.size} Fd, [Rn{, #offset}] # set保存,将一个扩展寄存器的内容保存到内存中。 +VLDR{cond}{.size} Fd, label +VSTR{cond}{.size} Fd, label +``` +cond: 是一个可选的条件代码,EQ等于\NE不等于\HI无符号大于\LS无符号小于等于\GE有符号大于等于\LT有符号小于\GT有符号大于\LE有符号小于等于 + +size:是一个可选的数据大小说明符。 如果 Fd 是单精度 VFP 寄存器,则必须为 32,传送一个字;否则必须为 64,传送两个字。 + +Fd:是要加载或保存的扩展寄存器。 对于 NEON 指令,它必须为 Dd。 对于 VFP 指令,它可以为 Dd 或 Sd。 + +Rn:是存放要传送的基址的 ARM 寄存器。 + +offset:是一个可选的数值表达式。 在汇编时,该表达式的值必须为一个数字常数。 该值必须是 4 的倍数,并在 -1020 到 +1020 的范围内。 该值被加到基址上以构成用于传送的地址。 + +label:是一个程序相对的表达式。必须位于当前指令的 ±1KB 范围之内。 + +> **扩展寄存器加载多个、存储多个、从堆栈弹出、推入堆栈** + +语法: +```asm +VLDMmode{cond} Rn,{!} Registers # 加载多个 +VSTMmode{cond} Rn,{!} Registers # 存储多个 +VPOP{cond} Registers # 从堆栈弹出 VPOP Registers 等效于 VLDM sp!,Registers +VPUSH{cond} Registers # 推入堆栈 VPUSH Registers 等效于 VSTMDB sp!,Registers +``` +mode 必须是下列值之一: + + IA 表示在每次传送后递增地址。IA 是缺省值,可以省略。 increase + DB 表示在每次传送前递减地址。 decrease + EA 表示空的升序堆栈操作。 对于加载操作,该值与 DB 相同;对于保存操作,该值与 IA 相同。 + FD 表示满的降序堆栈操作。 对于加载操作,该值与 IA 相同;对于保存操作,该值与 DB 相同。 + +! 是可选的。! 指定必须将更新后的基址写回到 Rn 中。 如果未指定!,则 mode 必须为 IA。 + +Registers 是一个用大括号 { 和 } 括起的连续扩展寄存器的列表。 该列表可用逗号分隔,也可以采用范围格式。 列表中必须至少有一个寄存器。可指定 S、D 或 Q 寄存器,但一定不能混用这些寄存器。 D 寄存器的数目不得超过 16 个,Q 寄存器的数目不得超过 8 个。 如果指定 Q 寄存器,则在反汇编时它们将显示为 D 寄存器。 + +> **VMOV(在两个 ARM 寄存器和一个扩展寄存器之间传送内容)** + +在两个 ARM 寄存器与一个 64 位扩展寄存器或两个连续的 32 位 VFP 寄存器之间传送内容。 + +语法: +```asm +VMOV{cond} Dm, Rd, Rn # 将 Rd 的内容传送到 Dm 的低半部分,并将 Rn 的内容传送到 Dm 的高半部分 +VMOV{cond} Rd, Rn, Dm # 将 Dm 的低半部分的内容传送到 Rd,并将 Dm 的高半部分的内容传送到 Rn +VMOV{cond} {Sm, Sm1}, Rd, Rn # 将 Sm 的内容传送到 Rd,并将 Sm1 的内容传送到 +VMOV{cond} Rd, Rn, {Sm, Sm1} # 将 Rd 的内容传送到 Sm,并将 Rn 的内容传送到 Sm1 +``` + + Dm 是一个 64 位扩展寄存器。 + Sm 是一个 VFP 32 位寄存器。 + Sm1 是 Sm 之后的下一个 VFP 32 位寄存器。 + Rd、Rn 是 ARM 寄存器。 不要使用 r15。 +> **VMOV(在一个 ARM 寄存器R 和一个 NEON 标量之间)** + +在一个 ARM 寄存器和一个 NEON 标量之间传送内容。 + +语法 +VMOV{cond}{.size} Dn[x], Rd # 将 Rd 的最低有效字节、半字或字的内容传送到 Sn。 +VMOV{cond}{.datatype} Rd, Dn[x] # 将 Dn[x] 的内容传送到 Rd 的最低有效字节、半字或字。 + +size 是数据大小。 可以为 8、16 或 32。 如果省略,则 size 为 32。 + +datatype 是数据类型。 可以为 U8、S8、U16、S16 或 32。 如果省略,则 datatype为 32。 + +Dn[x] 是 NEON 标量,16 位标量限定为寄存器 D0-D7,其中 x 位于范围 0-3 内,32 位标量限定为寄存器 D0-D15,其中 x 为 0 或 1。 + +Rd 是 ARM 寄存器。Rd 不得为 R15。 + +#### NEON 逻辑运算和比较运算 +> **VAND、VBIC、VEOR、VORN 和 VORR(寄存器)** + +VAND(按位与)、VBIC(位清除)、VEOR(按位异或)、VORN(按位或非)和 VORR(按位或)指令在两个寄存器之间执行按位逻辑运算,并将结果存放到目标寄存器中。 + +语法: +```asm +Vop{cond}.{datatype} {Qd}, Qn, Qm +Vop{cond}.{datatype} {Dd}, Dn, Dm +``` + +op 必须是下列值之一: +AND 逻辑“与”\ORR 逻辑“或”\EOR 逻辑异或\BIC 逻辑“与”求补\ORN 逻辑“或”求补。 + +Qd、Qn、Qm 为四字运算指定目标寄存器、第一个操作数寄存器和第二个操作数寄存器。 + +Dd、Dn、Dm 为双字运算指定目标寄存器、第一个操作数寄存器和第二个操作数寄存器。 + +> **VBIC 和 VORR(立即数)** + +VBIC(位清除(立即数))获取目标向量的每个元素,对其与一个立即数执行按位与求补运算,并将结果返回到目标向量。 + +VORR(按位或(立即数))获取目标向量的每个元素,对其与一个立即数执行按位或运算,并将结果返回到目标向量。 + + +语法: +```asm +Vop{cond}.datatype Qd, #imm +Vop{cond}.datatype Dd, #imm +``` +op 必须为 BIC 或 ORR。 + +datatype 必须为 I16 或 I32。 + +Qd 或 Dd 是用于存放源和结果的 NEON 寄存器。 + +imm 是立即数。 + +立即数 + +如果 datatype 为 I16,则立即数必须采用下列格式之一: +• 0x00XY +• 0xXY00。 + +如果 datatype 为 I32,则立即数必须采用下列格式之一: +• 0x000000XY +• 0x0000XY00 +• 0x00XY0000 +• 0xXY000000。 + +〉**VBIF、VBIT 和 VBSL** + +VBIT(为 True 时按位插入):如果第二个操作数的对应位为 1,则该指令将第一个操作数中的每一位插入目标中;否则将目标位保持不变。 + +VBIF(为 False 时按位插入):如果第二个操作数的对应位为 0,则该指令将第一个操作数中的每一位插入目标中;否则将目标位保持不变。 + +VBSL(按位选择):如果目标的对应位为 1,则该指令从第一个操作数中选择目标的每一位;如果目标的对应位为 0,则从第二个操作数中选择目标的每一位。 + +语法: +```asm +Vop{cond}{.datatype} {Qd}, Qn, Qm +Vop{cond}{.datatype} {Dd}, Dn, Dm + +``` + +> **VMOV、VMVN(寄存器)** + +VMOV向量移动(寄存器)将源寄存器中的值复制到目标寄存器中。 + +VMVN向量求反移动(寄存器)对源寄存器中每一位的值执行求反运算,并将结果存放到目标寄存器中。 + + +语法: +```asm +VMOV{cond}{.datatype} Qd, Qm +VMOV{cond}{.datatype} Dd, Qm +VMVN{cond}{.datatype} Qd, Qm +VMVN{cond}{.datatype} Dd, Qm +``` + +### NEON 乘法指令 + +VMUL(向量乘法))将两个向量中的相应元素相乘,并将结果存放到目标向量中。 +VMLA(向量乘加)将两个向量中的相应元素相乘,并将结果累加到目标向量的元素中。 +VMLS(向量乘减)将两个向量中的相应元素相乘,从目标向量的相应元素中减去相乘的结果,并将最终结果放入目标向量中。 +语法: +```asm +Vop{cond}.datatype {Qd}, Qn, Qm +Vop{cond}.datatype {Dd}, Dn, Dm +VopL{cond}.datatype Qd, Dn, Dm +``` + + + +### 内联汇编 inline assembly +[ARM GCC Inline Assembler Cookbook](http://www.ethernut.de/en/documents/arm-inline-asm.html) + +[博客参考](https://blog.csdn.net/dahailantian1/article/details/78584920) + +优点:在C代码中嵌入汇编,调用简单,无需手动存储寄存器; +缺点:有较为复杂的格式需要事先学习,不好移植到其他语言环境。 + +[汇编语言笔记](https://github.com/Ewenwan/ShiYanLou/blob/master/OS/%E6%B1%87%E7%BC%96%E8%AF%AD%E8%A8%80.md) + +[内联汇编参考](https://github.com/Ewenwan/ShiYanLou/tree/master/OS/Linux#c内联汇编) + +比如上述intrinsics代码产生的汇编代码为: +```c +// ARMv7‐A/AArch32 +void add_float_neon2(int* dst, int* src1, int* src2, int count) +{ + asm volatile ( + "1: \n" // 用于构成循环的标记号 + "vld1.32 {q0}, [%[src1]]! \n" // 从src地址处载入4个32位的浮点数 地址递增 + "vld1.32 {q1}, [%[src2]]! \n" + "vadd.f32 q0, q0, q1 \n" // q0 = q0 +q1 + "subs %[count], %[count], #4 \n"// 循环计数count = count-4 + "vst1.32 {q0}, [%[dst]]! \n" // 将运算结果存储到目标地址,目标地址递增 + "bgt 1b \n" // 如果count>0,跳转到标记号1处继续执行 + : [dst] "+r" (dst) // 可写 + : [src1] "r" (src1), [src2] "r" (src2), [count] "r" (count) + : "memory", "q0", "q1" + ); +} + +``` + + +## 建议的NEON调优步骤 + +* 1. 理清所需的寄存器、指令。 建议根据要实现的任务,画出数据变换流程,和每步所需的具体指令,尽可能找到最优的实现流程。这一步非常关键,如果思路出错或是不够优化,则会影响使用NEON的效果,并且对程序修改带来麻烦,一定要找到最优的实现算法哦~ + +* 2. 先实现intrinsics(可选)。 初学者先实现intrinsics是有好处的,字面理解性更强,且有助于理解NEON指令。建议随时打印关键步骤的数据,以检查程序的正误。 + +* 3. 写成汇编进一步优化。 将intrinsics生成的汇编代码进行优化调整。一般来说,有以下几点值得注意【干货】: + +* 只要intrinsics运算指令足够精简,运算类的汇编指令就不用大修; +* 大部分的问题会出在存取、移动指令的滥用、混乱使用上; +* 优化时要尽量减少指令间的相关性,包括结构相关、数据相关控制相关,保证流水线执行效率更高; +* 大概估算所有程序指令取指、执行、写回的总理论时间,以此估算本程序可以优化的空间; +* 熟练对每条指令准备发射、写回时间有一定的认识,有助于对指令的优化排序; +* 一定要多测试不同指令的处理时间!!原因是你所想跟实际有出入,且不同的编译器优化的效果可能也有些不同; +* 一定要有一定的计算机体系结构基础,对存储结构、流水线有一定的体会!! + +〉 **总结一下NEON优化就是:** + +* 第一优化算法实现流程; +* 第二优化程序存取; +* 第三优化程序执行; +* 第四哪儿能优化,就优化哪儿 + +〉 **需要注意的地方** + +   1. load数据的时候,第一次load会把数据放在cache里面,只要不超过cache的大小,下一次load同样数据的时候,则会比第一次load要快很多,会直接从cache中load数据,这样在汇编程序设计的时候是非常需要考虑的问题。 + +   如:求取一个图像的均值,8*8的窗口,先行求和,然后列求和出来均值,这时候会有两个函数,数据会加载两遍,如果按照这样去优化的话则优化不了多少。如果换成上面这种思路,先做行16行,然后再做列,这样数据都在cache里面,做列的时候load数据会很快。 + +   在做neon乘法指令的时候会有大约2个clock的阻塞时间,如果你要立即使用乘法的结果,则就会阻塞在这里,在写neon指令的时候需要特别注意。乘法的结果不能立即使用,可以将一些其他的操作插入到乘法后面而不会有时间的消耗。 + +如:vmul.u16 q1, d3, d4  + +         vadd.u32 q1, q2, q3 + +此时直接使用乘法的结果q1则会阻塞,执行vadd需要再等待2个clock的时间 + +使用饱和指令的时候,如乘法饱和的时候,在做乘法后会再去做一次饱和,所以时间要比直接做乘法要慢。 + +如:  vmul.u16 q1, d3, d4 + +          vqmul.u32 q1, q2, q3 + +后一个的时间要比第一个的时间要久。 + +在对16位数据进行load或者store操作的时候,需要注意的是字节移位。比如是16位数据,则load 8个16位数据,如果指定寄存器进行偏移,此时需要特别注意。 + +例如:vld1.64 {d0}, [r0], r1 + + +## 内联汇编使用心得 +[ARM GCC Inline Assembler Cookbook](http://www.ethernut.de/en/documents/arm-inline-asm.html) + +inline assembly下面的三个冒号一定要注意 +output/input registers的写法一定要写对,clobber list也一定要写完全,否则会造成令你头疼的问题 (TT) + +这个问题在给出的cookbook中也有介绍,但是并不全面,有些问题只有自己碰到了再去解决。 笔者就曾经被虐了很久,从生成的汇编发现编译器将寄存器乱用,导致指针操作完全混乱,毫无头绪… + + +一般情况下建议的写法举例: +```asm +asm volatile ( + ... /* assembly code 汇编代码 */ + // 所有的汇编代码必须用双引号括起来。 + // 如果有多行汇编代码的话,每一条语句都要用双引号括起来,并且在代码后面要加上换行符(“\n”或者“\n\t”)。 + + // "[modifier修改符 可选]constraint限定符" (C expression C语言表达式) + // 修改符和限定符要用双引号括起来,而C表达式要用括号括起来。 + : "+r"(arg0) // %0 + "+r"(arg1) // %1 // 输入寄存器 Output Registers + : "r"(arg2) // %2 // 输入寄存器 Input Registers + : "cc", "memory", r0, r1 // 寄存器变化 +); +``` + +> **限定符** + + 限定符 在ARM指令集下 在Thumb指令集下 + f 浮点寄存器f0...f7 N/A + h N/A 寄存器r8...r15 + G 浮点常量立即数 N/A + H 和G作用相同 N/A + I 数据处理指令中用到的立即数 范围为0...255的常量 + J 范围为-4095...4095的索引常量 范围为-255...-1的常量 + K 和I作用相同 和I作用相同 + L 和I作用相同 范围为-7...7的常量 + l 和r作用相同 寄存器r0...r7 + M 范围为0.32或者是2的幂次方的常量 范围为0...1020的4的倍数的常量 + m 内存地址memory 内存地址 + N N/A 范围为0...31的常量 + O N/A 范围为 -508...508 的4的倍数的常量 + r 通用寄存器r0...r15 N/A + w 向量浮点寄存器s0...s31 N/A + X 任何类型的操作数 任何类型的操作数 + + 数字 0,1,2,3,... 指代前面定义的操作数 + +是常用的也就是r,f和m等几个。 + +> **修改符** + +修改符是加在限定符之前的,并且是可选的,如果没有修改符的话,则表明这个操作数是只读的。 + +这个对输入操作数没有问题,但是对输出操作数来说,肯定是需要被修改的,那怎么办呢? + +答案就是使用修改符,修改这个操作数的属性。目前,GCC中定义了三个修改符,分别是: + + 修改符 含义 + = 只写 操作数,通常用于输出操作数中 + + 可读 且 可写 操作数,必须要列在输出操作数中 + & 寄存器只能用于输出(不能作为输入寄存器) + +所以,作为输出操作数,只需要在限定符前加上“=”就可以了。 + +如果想让一个C变量既作为输入操作数,也作为输出操作数的话,可以使用“+”限定符,并且这个操作数只需要在输出操作数列表中列出就行了。例如: + +```asm +__asm__( + "mov %0, %0, ror #1" + : "+r" (y) + ); +``` +是将变量y中的值右移1位。因为输入和输出操作数是一个,所以该操作数要既可读也可写,因此添加了“+”修改符。 + +其实,在限定符中,也可以使用数字,其作用是指代前面定义的操作数,0代表第一个,1代表第二个,以此类推。 + + +```asm +__asm__( + "mov %0, %0, ror #1" + : "=r" (y) + : "0" (y) + ); +``` +// 这个例子的效果和前面的例子是相同的。本例不同的是,先定义了一个可写的输出变量,同时在输入变量列表中,明确用数字0指出了前面定义的第一个操作数同时也要用来作为输入操作数。 + + +使用“&”修改符,明确告诉编译器,代表输出操作数的寄存器一定不能使用输入操作数已经使用过的寄存器。下面举个例子: + +如果汇编代码中有输入寄存器还没有使用完毕,就对输出操作数进行修改的情况,则特别需要用“&”修改符,保证不复用。 + +```asm +__asm__ __volatile__( + "ldr %0, [%1]\n\t" + "str %2, [%1, #4]" + : "=&r" (rdv) + : "r" (&table), "r" (wdv) + : "memory"); + +``` +本例中,将操作一个table数组,读出它的第一个数存放到rdv中,然后修改第二个数为wdv中存放的值。乍看一下没什么问题,但是如果编译器用同一个寄存器来表示输入操作数&table(%1)和输出操作数rdv(%0)怎么办呢?执行完第一条语句之后,table数组的地址就被修改掉了。所以,可以在输出操作数中加上一个“&”修改符,强制保证输出操作数不能和输入操作数复用同一个寄存器,这个问题就解决了 + +> **修改寄存器列表** + +在汇编指令中,有可能会用到一些指定的寄存器,但是在执行你定义的汇编程序时,那个指定的寄存器有可能另有别的用途,存放了非常重要的数据。等你的程序执行完成后,那个寄存器的值已经被你修改过了,肯定会造成执行错误。因此,在执行你的程序之前必须要做必要的备份和恢复的动作。但是,编译器并不会分析你的汇编代码,找出这种被你修改过,需要恢复的寄存器,因此你必须显式的告诉编译器,被你修改过的寄存器有哪些。这就是修改寄存器列表所起到的作用。 + +对于嵌入内联ARM汇编来说,此列表中的值有下面三种类型: + + 类型 作用 + r0...r15 告诉编译器汇编代码中 修改了通用寄存器r0...r15 + cc 告诉编译器汇编代码 会 导致 CPU状态位 的 改变 memory 告诉编译器汇编代码 会 读取或修 改内存中某个地址 存放的值 + +对于“memory”来说,它并不是表示寄存器被读取或修改了,而是表示内存中的值被修改了。出于优化的目的,在执行你的汇编代码之前,编译器将某些变量的值还保存在寄存器中,并没有被写到实际的内存中。但是,如果你的汇编代码会读取内存中的值,则很有可能新的值还在寄存器中,而内存中存放的还是老的值,这样就会造成错误。添加了“memory”之后,编译器会在执行你的代码之前,保证将保存在寄存器中,没有更新到内存中的值全部都写入到内存中。 + +此列表中的每一项都要用双引号("")括起来,每项之间要用逗号(“,”)分割。 + + + +### 浮点向量加法 NEON instruction 内联函数 Inline assembly内联汇编 NEON assembly 纯汇编 对比 +[Neon 寄存器 指令集 ARMv7/v8 对比](https://blog.csdn.net/zsc09_leaf/article/details/45825015) + +// c 与内联函数对比 +```c +#include + +void add_float_c(float* dst, float* src1, float* src2, int count) +{ + int i; + for (i = 0; i < count; i++) + dst[i] = src1[i] + src2[i]; +} + +void add_float_neon1(float* dst, float* src1, float* src2, int count) +{ + int i = 0; + for (; i < count - 3; i += 4) + { + float32x4_t in1, in2, out; + in1 = vld1q_f32(src1); + src1 += 4; + in2 = vld1q_f32(src2); + src2 += 4; + // v8 + #if __aarch64__ + out = vaddvq_f32(in1, in2); + #else + out = vaddq_f32(in1, in2); + #endif + vst1q_f32(dst, out); + dst += 4; + } + // 剩余 1~3个数 使用普通c + for(;i < count; i++) + { + dst[i] = src1[i] + src2[i] + } +} + + + +``` + +// 内联函数 V7 V8 对比 +```c +// ARMv7-A/AArch32 +void add_float_neon3(float* dst, float* src1, float* src2, int count) +{ + int nn = count >> 4; + int remain = count - (nn << 2); +/* + asm volatile ( + "1: \n" // 用于循环跳转,标记号 + "vld1.32 {q0}, [%4]! \n" + "vld1.32 {q1}, [%5]! \n" + "vadd.f32 q0, q0, q1 \n" + "subs %1, #1 \n" + "vst1.32 {q0}, [%0]! \n" + "bgt 1b \n" + : "+r"(dst), // %0 输出参数列表 + "+r"(nn) // %1 + : "0"(dst) + "1"(nn) + "r"(src1), // %4 输入参数列表 + "r"(src2) // %5 + : "memory", "q0", "q1" + ); +*/ + asm volatile ( + "1: \n" // 用于循环跳转,标记号 + "vld1.32 {q0}, [%[src1]]! \n" + "vld1.32 {q1}, [%[src2]]! \n" + "vadd.f32 q0, q0, q1 \n" + "subs %[nn], %[nn], #4 \n" + "vst1.32 {q0}, [%[dst]]! \n" + "bgt 1b \n" + : [dst] "+r" (dst) + : [src1] "r" (src1), [src2] "r" (src2), [nn] "r" (nn) + : "memory", "q0", "q1" + ); + // 剩余数处理 + for( ; remain > 0; remain--) + { + *dst = *src1 + *src2; + } +} + + +// AArch64 +void add_float_neon3(float* dst, float* src1, float* src2, int count) +{ + asm volatile ( + "1: \n" // 用于循环跳转,标记号 + "ld1 {v0.4s}, [%[src1]], #16 \n" + "ld1 {v1.4s}, [%[src2]], #16 \n" + "fadd v0.4s, v0.4s, v1.4s \n" + "subs %[count], %[count], #4 \n" + "st1 {v0.4s}, [%[dst]], #16 \n" + "bgt 1b \n" + : [dst] "+r" (dst) //输出参数 + : [src1] "r" (src1), [src2] "r" (src2), [count] "r" (count) + : "memory", "v0", "v1" + ); + +} +``` + +> 纯汇编 V7 V8 对比 + +// 函数声明头文件 +```c +//header +void add_float_neon2(float* dst, float* src1, float* src2, int count); +``` + +// v7 + +```asm + .text // .text表示代码正文部分 + .syntax unified + + .align 4 // .align根据不同的汇编器会有不同的行为,像这里的.align4可能表示4字节对齐,也可能表示16字节对齐。 + .global add_float_neon2 // 函数名 可以用.global或.globl来标注全局函数。在Apple的Assembler中仅支持.globl。函数名前要加下划线。 + .type add_float_neon2, %function // 函数名 + .thumb // .arm表示后面的函数中的指令都是arm指令。 + // 而.thumb表示后面函数中的指令都是thumb或thumb-2指令。 + // 其中,如果一个函数是用thumb写的,那么必须用 .thumb_func 修饰,否则连接器在连接符号时会有问题。 +.thumb_func + +add_float_neon2: +.L_loop: + vld1.32 {q0}, [r1]! // 函数第一个参数为 r0 第二个为 r1 第三个位r2 第四个为 r3 + vld1.32 {q1}, [r2]! + vadd.f32 q0, q0, q1 + subs r3, r3, #4 + vst1.32 {q0}, [r0]! + bgt .L_loop + + bx lr + + +``` + +// v8 + +```asm + .text + + .align 4 + .global add_float_neon2 # 函数名 + .type add_float_neon2, %function # 函数名 + +add_float_neon2: + +.L_loop: + ld1 {v0.4s}, [x1], #16 # 函数第一个参数为 x0 第二个为 x1 第三个为 x2 第四个为 x3 + ld1 {v1.4s}, [x2], #16 + fadd v0.4s, v0.4s, v1.4s + subs x3, x3, #4 + st1 {v0.4s}, [x0], #16 + bgt .L_loop + + ret + +``` + + + + +## ARM NEON CNN卷积网络优化 深度学习优化 实例 +[参考NCNN](https://github.com/Ewenwan/MVision/blob/master/CNN/HighPerformanceComputing/example/ncnn_%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90.md) + +### 1.绝对值 AbsVal arm_neon_v7 neon_v8 优化 +```c +// arm 内联汇编 +// asm( +// 代码列表 +// : 输出运算符列表 "r" 表示同用寄存器 "m" 表示内存地址 "I" 立即数 +// : 输入运算符列表 "=r" 修饰符 = 表示只写,无修饰符表示只读,+修饰符表示可读可写,&修饰符表示只作为输出 +// : 被更改资源列表 +// ); +// __asm__ __volatile__(); + +// 关键字“__asm__”,其实也可以写成“asm”。但是“asm”并不是所有版本的GCC编译器都支持的, +// 而且有可能和程序中别的地方定义的变量或函数名冲突,所以用“__asm__”的话,兼容性会好一点。 + +// __volatile__或volatile 是可选的,假如用了它,则是向GCC 声明不答应对该内联汇编优化, +// 否则当 使用了优化选项(-O)进行编译时,GCC 将会根据自己的判定决定是否将这个内联汇编表达式中的指令优化掉。 + +// 作用是禁止编译器对后面编写的汇编指令再进行优化。一般情况下,自己写的汇编代码肯定是自己进行设计优化过了的, +// 如果编译器再进行优化的话,很有可能效果还不如不优化,而且也有可能会出现奇怪的错误,所以通常都会带上这个关键字。 +// 同样,“__volatile__”也可以写成“volatile”,但可能兼容性会没那么好。 + +#if __ARM_NEON +#include +#endif // __ARM_NEON + +// 换行符和制表符的使用可以使得指令列表看起来变得美观。 +int AbsVal_arm::forward_inplace(Mat& bottom_top_blob) const +{ + int w = bottom_top_blob.w;// 输入特征图宽度 + int h = bottom_top_blob.h;// 输入特征图高度 + int channels = bottom_top_blob.c;// 输入特征图通道数 + int size = w * h;// 一个通道的元素数量 + + #pragma omp parallel for // omp并行 + // #pragma omp parallel for num_threads(opt.num_threads) + for (int q=0; q> 2;// 128位的寄存器,一次可以操作 4个float32位,剩余不够4个的,最后面直接c语言执行 + // 右移两位相当于除以4 + int remain = size - (nn << 2);// 4*32 =128字节对其后 剩余的 float32个数, 剩余不够4个的数量 + +#else + int remain = size; // 若不支持优化,则全部使用不同C语言版本进行计算 +#endif // __ARM_NEON + +/* +从内存中载入: +v7: + 带了前缀v的就是v7 32bit指令的标志; + ld1表示是顺序读取,还可以取ld2就是跳一个读取,ld3、ld4就是跳3、4个位置读取,这在RGB分解的时候贼方便; + 后缀是f32表示单精度浮点,还可以是s32、s16表示有符号的32、16位整型值。 + 这里Q寄存器是用q表示,q5对应d10、d11可以分开单独访问(注:v8就没这么方便了。) + 大括号里面最多只有两个Q寄存器。 + + "vld1.f32 {q10}, [%3]! \n" + "vld1.s16 {q0, q1}, [%2]! \n" + + +v8: + ARMV8(64位cpu) NEON寄存器 用 v来表示 v1.8b v2.8h v3.4s v4.2d + 后缀为8b/16b/4h/8h/2s/4s/2d) + 大括号内最多支持4个V寄存器; + + "ld1 {v0.4s, v1.4s, v2.4s, v3.4s}, [%2], #64 \n" // 4s表示float32 后面的64 是 64个字节 16个字节为128位 读取4*128位数据 + "ld1 {v0.8h, v1.8h}, [%2], #32 \n" + "ld1 {v0.4h, v1.4h}, [%2], #32 \n" // 4h 表示int16 读取32*8 = 2*128位数据 2个v寄存器 + + +所有的汇编代码必须用双引号括起来。如果有多行汇编代码的话,每一条语句都要用双引号括起来,并且在代码后面要加上换行符(“\n”或者“\n\t”)。 + +这样做是因为GCC会将汇编代码部分作为字符串形式直接传给汇编器,加上换行符后,汇编器就能准确知道哪些字符串表示的是一条汇编语句。同时,为了增加可读性,每条汇编语句都可以换行。 + +*/ + +// 优化过程 +#if __ARM_NEON +// arm_v8================================ +#if __aarch64__ // ARMv8-A 是首款64 位架构的ARM 处理器,是移动手机端使用的CPU + if (nn > 0)// 这里的循环次数已经是 除以4之后的了 + { + asm volatile( + "0: \n" // 0: 作为标志,局部标签 + "prfm pldl1keep, [%1, #128] \n" // %1处为ptr标识为1标识,即数据地址,预取 128个字节 4*32 = 128 + "ld1 {v0.4s}, [%1] \n" // 载入 ptr 指针对应的值,连续4个float 12位 + "fabs v0.4s, v0.4s \n" // ptr 指针对应的值 连续4个,使用fabs函数 进行绝对值操作 4s表示浮点数 + "subs %w0, %w0, #1 \n" // %0 引用 参数 nn 操作次数每次 -1 #1表示1 + // w表示啥? + "st1 {v0.4s}, [%1], #16 \n" // %1 引用 参数 ptr 指针 向前移动 4*4=16字节 = 16*8 =128位 + // store 1, {v0.4s} 计算绝对值后 再存入 [%1]? + "bne 0b \n" // 如果非0,则向后跳转到 0标志处执行 + + // BNE指令会去查看状态寄存器,当Z!=0的时候就跳转到指定位置. + // BEQ功能与BNE刚好相反,Z==0的时候才跳转到指定位置. + + // 每个操作数的寄存器行为 “=”,表示此操作数类型是只写,即输出寄存器。 + // "[modifier修改符可选]constraint限定符" (C expression C语言表达式) + : "=r"(nn), // %0 操作次数 nn 循环变量 + "=r"(ptr) // %1 引用参数 ptr 数据内存地址指针 + + // 数据 标签标识 nn 标识为0 ptr标识为1 + // 使用百分号(“%”)后面接一个数字,0表示定义的第一个操作数,1表示定义的第二个操作数,依次类推。 + : "0"(nn), + "1"(ptr) + // 寄存器变化表 list of clobbered registers + : "cc", "memory", "v0" // v0寄存器,内存memory, cc CPU状态位 可能会变化 + ); + } +#else + +// arm_v7=========================== + if (nn > 0) + { + asm volatile( + "0: \n" // 0: 作为标志,局部标签 + "vld1.f32 {d0-d1}, [%1] \n" // %1处为ptr标识为1标识,即数据地址 + // IA 表示在每次传送后递增地址。IA 是缺省值,可以省略。?? + "vabs.f32 q0, q0 \n" // q0寄存器 = [d1 d0],128位寄存器,取出四个 float 单精度浮点数 进行绝对值计算 后 写入 + "subs %0, #1 \n" // %0为 循环变量nn标识,标识循环次数-1 #1表示1 + "vst1.f32 {d0-d1}, [%1]! \n" // 存储 store1 经过绝对值运算后的寄存器的值 存入原内存中 + // !感叹号作用? 指针 [%1] 前移16字节?? + // ! 指定必须将更新后的基址([%1]递增16)写回到 [%1] 中 + + "bne 0b \n" // 如果非0,则向后跳转到 0标志处执行 + // 每个操作数的寄存器行为 “=”,表示此操作数类型是只写,即输出寄存器。 + : "=r"(nn), // %0 + "=r"(ptr) // %1 + // 数据 标签标识 nn 标识为0 ptr标识为1 + : "0"(nn), + "1"(ptr) + // 寄存器变化表 list of clobbered registers + : "cc", "memory", "q0"// q0寄存器,内存memory, cc CPU状态位 可能会变化 + ); + } +#endif // __aarch64__ +#endif // __ARM_NEON + + // 剩余不够4个的直接c语言执行===== + for (; remain>0; remain--)// 循环次数-1 + { + *ptr = *ptr > 0 ? *ptr : - *ptr; + ptr++;// 指针+1 + } + } + + return 0; +} + +``` + +### 2. BN层 通道数据归一化 BatchNorm + +```c +// load_model() 函数预处理=============== + + // 去均值 归一化 合在一起============= + // 各个通道均值 mean_data = sum(xi)/m + // 各个通道方差 var_data = sum((xi - mean_data)^2)/m + // xi‘ = ( xi - mean_data )/(sqrt(var_data + eps)) // 去均值,除以方差,归一化 + + // yi = slope_data * xi' + bias_data // 缩放 + 平移===== + + // 写成一起===================== + // yi = slope_data / (sqrt(var_data + eps)) * xi + bias_data - slope_data*mean_data/(sqrt(var_data + eps)) + // b = slope_data / (sqrt(var_data + eps)) = slope_data /sqrt_var; + // a = bias_data - slope_data*mean_data/(sqrt(var_data + eps)) = bias_data - slope_data*mean_data/sqrt_var; + + // yi = b * xi + a + +// 在layer/batchnorm.cpp 的 BatchNorm::load_model 函数中处理 + +int BatchNorm::load_model(const ModelBin& mb) + +{ + slope_data = mb.load(channels, 1); // 缩放系数 + if (slope_data.empty()) + return -100; + + mean_data = mb.load(channels, 1); // 均值 + if (mean_data.empty()) + return -100; + + var_data = mb.load(channels, 1); // 方差 + if (var_data.empty()) + return -100; + + bias_data = mb.load(channels, 1); // 标准差 + if (bias_data.empty()) + return -100; + + a_data.create(channels); // 去均值减方差 缩放和平移合在一起 >>> 新偏移量 + if (a_data.empty()) + return -100; + + b_data.create(channels); // 新 缩放系数 + if (b_data.empty()) + return -100; + + for (int i=0; i> 2; // 128位寄存器一个可以操作 4个 32位浮点数,所以总数除以4得到 寄存器操作次数 + // 右移动2位,相当于除以4,例如 10,右移两位相当于乘除4,得到2 + int remain = size - (nn << 2);// 10-2*4=2 剩余2个 不够4,使用普通c语言版本 +#else + int remain = size; // 如果不支持neon,则全部使用 普通c语言计算呢 +#endif // __ARM_NEON + +#if __ARM_NEON +#if __aarch64__ + if (nn > 0) + { + asm volatile( + "dup v1.4s, %w4 \n" // 每通道的 变化系数a,b都一样只需载入一次,传入的为立即数使用dup + "dup v2.4s, %w5 \n" // v1存储a,v2存储b,v0存储特征数据,v3存储变化的数据地址以及a + "0: \n" // 构成循环的标记号 + "prfm pldl1keep, [%1, #128] \n" // 从%1 ptr 处预读取 128字节 4*32 4个浮点数 + "ld1 {v0.4s}, [%1] \n" // 载入 ptr 指针对应的值到 v0,连续4个float + "orr v3.16b, v1.16b, v1.16b \n" // v1 --> v3, v3 =a + "fmla v3.4s, v0.4s, v2.4s \n" // 特征数据v0*缩放v2 + 偏置v3 最后赋值给 v3 += v0×b + "subs %w0, %w0, #1 \n" // %0 为nn 执行次数 -1 #1 为1 + "st1 {v3.4s}, [%1], #16 \n" // 结果v3 store存储到 原数据地址处,原数据地址递增16字节 + "bne 0b \n" // subs结果不为零的话跳转回去,继续循环 + : "=r"(nn), // %0 + "=r"(ptr) // %1 + : "0"(nn), // 2 ???===== + "1"(ptr), // 3 ???===== + "r"(a), // %4 存入寄存器 只读, 不变, 参数 偏置a + "r"(b) // %5 存入寄存器 只读, 不变,参数 缩放归一化系数 + : "cc", "memory", "v0", "v1", "v2", "v3" + // cc CPU状态位,内存memory,v,v1,v2,v3寄存器 可能会变化 + ); + } +#else + if (nn > 0) + { + asm volatile( + "vdup.f32 q1, %4 \n"// 每通道的 变化系数a,b都一样只需载入一次,传入的为立即数使用dup + "vdup.f32 q2, %5 \n"// q1存储变量 a,q2存储变量b,q0存储特征值 + // q3存储中间变量,先存储a和b以及q0执行乘加后,存储最终的结果 + // 最后把 在q3中的结果 存储回原 特征数据地址处 + + "0: \n"// 构成循环的标记号 + "pld [%1, #128] \n"// 从%1 ptr 处预读取 128字节 4*32 4个浮点数 + "vld1.f32 {d0-d1}, [%1 :128] \n"// 从%1 ptr 处载入 4个浮点数到q0,传入的为指针,使用ld + "vorr.32 q3, q1, q1 \n"// q3 = q1 或 q1 = 变量a + "vmla.f32 q3, q0, q2 \n"// q3 += q0(特征值)*q2(变量b), 乘加运算 + "subs %0, #1 \n"// 循环次数 nn -1 + "vst1.f32 {d6-d7}, [%1 :128]! \n"// q3->{d6-d7} 结果值 顺序store到 原特征值地址处[%1] + // !感叹号,强制[%1]向后跳转128位 + "bne 0b \n"// 不为零跳回去,继续循环 + + : "=r"(nn), // %0 循环次数(按寄存器一次并行运算4个浮点数数) nn + "=r"(ptr) // %1 特征值数据地址 + : "0"(nn), // 2 ???=== + "1"(ptr), // 3 ???=== + "r"(a), // %4 + "r"(b) // %5 + : "cc", "memory", "q0", "q1", "q2", "q3" + // cc CPU状态位,内存memory,q0,q1,q2,q3寄存器 可能会变化 + ); + } +#endif // __aarch64__ +#endif // __ARM_NEON + for (; remain>0; remain--) + { + *ptr = b * *ptr + a;// 剩余不够 4个的 直接c语言执行 + + ptr++;// 数据地址增加 1 + } + } + return 0; +} + + +``` + +### 3.添加偏置类 bias + +```c +// 进行运算: y = x + bias ---> x + +int Bias_arm::forward_inplace(Mat& bottom_top_blob, const Option& opt) const +{ + int w = bottom_top_blob.w;// 特征图宽度 + int h = bottom_top_blob.h;// 特征图高度 + int channels = bottom_top_blob.c;// 通道数量(特征 图 厚度,汉堡包层数) + int size = w * h;// 单通道特征尺寸 + + const float* bias_ptr = bias_data; // 偏置数据 指针 在 bias.h 中定义的 public公开数据 + + #pragma omp parallel for num_threads(opt.num_threads)// omp并行执行 + + for (int q=0; q> 2; // 128位寄存器一个可以操作 4个 32位浮点数,所以总数除以4得到 寄存器操作次数 + // 右移动2位,相当于除以4,例如 10,右移两位相当于乘除4,得到2 + int remain = size - (nn << 2);// 剩余不够4个的数量 1~3 +#else + int remain = size; +#endif // __ARM_NEON + +#if __ARM_NEON +/* +// 这里 直接使用了 neon Instrinsic 内在函数,不过优化程度不如 汇编代码 + + float32x4_t _bias = vdupq_n_f32(bias);// 偏置数据 dup载入到 寄存器 4个32位的浮点数 + // 传入的为 立即数 + for (; nn>0; nn--) + { + float32x4_t _p = vld1q_f32(ptr);// 载入 特征值 传入的为 数据的地址 + float32x4_t _outp = vaddq_f32(_p, _bias);// 加上偏置_bias + vst1q_f32(ptr, _outp); // 从寄存器数据 设置内存数据 store1存储结果数据到ptr + + ptr += 4;// 特征指针 移动四个单位 + } +*/ +// 可以试写 neon内联汇编代码,区分v8 、v7=============== + +#if __aarch64__ + if (nn > 0) + { + asm volatile( + "dup v1.4s, %w4 \n" // 每通道的 变化系数a,b都一样只需载入一次,传入的为立即数使用dup + "0: \n" // 构成循环的标记号 + "prfm pldl1keep, [%1, #128] \n" // 从%1 ptr 处预读取 128字节 4*32 4个浮点数 + "ld1 {v0.4s}, [%1] \n" // 载入 ptr 指针对应的值到 v0,连续4个float + "fadd v0.4s, v0.4s, v1.4s \n" // v0 = v0 + v1 + "subs %w0, %w0, #1 \n" // %0 为nn 执行次数 -1 #1 为1 + "st1 {v0.4s}, [%1], #16 \n" // 结果v0 store存储到 原数据地址处,原数据地址递增16字节 + "bne 0b \n" // subs结果不为零的话跳转回去,继续循环 + : "=r"(nn), // %0 + "=r"(ptr) // %1 + : "0"(nn), // 2 ???===== + "1"(ptr), // 3 ???===== + "r"(bias) // %4 存入寄存器 只读, 不变, 参数 偏置a + : "cc", "memory", "v0", "v1" + // cc CPU状态位,内存memory,v,v1,v2,v3寄存器 可能会变化 + ); + } +#else + if (nn > 0) + { + asm volatile( + "vdup.f32 q1, %4 \n"// 每通道的 变化系数a,b都一样只需载入一次,传入的为立即数使用dup + "0: \n"// 构成循环的标记号 + "pld [%1, #128] \n"// 从%1 ptr 处预读取 128字节 4*32 4个浮点数 + "vld1.f32 {d0-d1}, [%1 :128] \n"// 从%1 ptr 处载入 4个浮点数到q0,传入的为指针,使用ld + "vadd.f32 q0, q0, q1 \n"// q0 = q0(特征值) + q1(变量bias) + "subs %0, #1 \n"// 循环次数 nn -1 + "vst1.f32 {d0-d1}, [%1 :128]! \n"// q0->{d0-d1} 结果值 顺序store到 原特征值地址处[%1] !感叹号,强制[%1]向后跳转128位 + "bne 0b \n"// 不为零跳回去,继续循环 + + : "=r"(nn), // %0 循环次数(按寄存器一次并行运算4个浮点数数) nn + "=r"(ptr) // %1 特征值数据地址 + : "0"(nn), // 2 ???=== + "1"(ptr), // 3 ???=== + "r"(bias) // %4 + : "cc", "memory", "q0", "q1" + // cc CPU状态位,内存memory,q0,q1,q2,q3寄存器 可能会变化 + ); + } +#endif // __aarch64__ + + +#endif // __ARM_NEON + + for (; remain>0; remain--) + { + *ptr = *ptr + bias; // 普通c 版本 加上偏置 + + ptr++; + } + } + + return 0; +} + + +``` + +### 4.修剪 clip 上下阈值处理 + + +```c +int Clip_arm::forward_inplace(Mat &bottom_top_blob, const Option &opt) const +{ + int w = bottom_top_blob.w; + int h = bottom_top_blob.h; + int channels = bottom_top_blob.c; + int size = w * h; + int elempack = bottom_top_blob.elempack; + +#if __ARM_NEON + if (elempack == 4) // 如果数据数量是4的整数倍 直接使用instric指令计算 也不用考虑剩余数的处理 + { + #pragma omp parallel for num_threads(opt.num_threads) + for (int q=0; q> 2; // 除以4 的余数 + int remain = size & 3; // 剩余 +#else + int remain = size; +#endif + +#if __ARM_NEON + float32x4_t _max = vdupq_n_f32(max); // 最小值 + float32x4_t _min = vdupq_n_f32(min); // 最大值 +#if __aarch64__ + for (; nn>0; nn--) + { + float32x4_t _ptr = vld1q_f32(ptr); + _ptr = vmaxq_f32(_ptr, _min); + _ptr = vminq_f32(_ptr, _max); + vst1q_f32(ptr, _ptr); + ptr += 4; + } +#else + if (nn > 0) + { + asm volatile( + "0: \n" + "pld [%1, #128] \n" // 预取 128位(字节?) + "vld1.f32 {d0-d1}, [%1: 128] \n" // q0 寄存器存储 普通人指针处 的值 + "vmax.f32 q0, q0, %q4 \n" // 下限处理 + "vmin.f32 q0, q0, %q5 \n" // 上限处理 + "subs %0, #1 \n" + "vst1.f32 {d0-d1}, [%1: 128]! \n" + "bne 0b \n" + + : "=r"(nn), // %0 + "=r"(ptr) // %1 + : "0"(nn), + "1"(ptr), + "w"(_min), // %q4 + "w"(_max) // %q5 + : "cc", "memory", "q0" + ); + } +#endif // __aarch64__ +#endif // __ARM_NEON + + for (; remain>0; remain--) + { + if (*ptr < min) + *ptr = min; + if (*ptr > max) + *ptr = max; + ptr++; + } + } + + return 0; +} + +``` + + + + + + + diff --git a/CNN/HighPerformanceComputing/FeatherCNN/readme.md b/CNN/HighPerformanceComputing/FeatherCNN/readme.md index 55b752c5..1257ea9c 100644 --- a/CNN/HighPerformanceComputing/FeatherCNN/readme.md +++ b/CNN/HighPerformanceComputing/FeatherCNN/readme.md @@ -1 +1,14 @@ # 腾讯 FeatherCNN 神经网络高性能计算 + +FeatherCNN是由腾讯AI平台部研发的一个高性能轻量级CNN推理库 + +FeatherCNN 由腾讯 AI 平台部研发,基于 ARM 架构开发的高效神经网络前向计算库 + +FeatherCNN 由腾讯 AI 平台部研发,基于 ARM 架构开发的高效神经网络前向计算库,核心算法已申请专利。该计算库支持 caffe 模型,具有无依赖,速度快,轻量级三大特性。 + +该库具有以下特性: + + 1.无依赖:该计算库无第三方组件,静态库或者源码可轻松部署于 ARM 服务器,和嵌入式终端,安卓,苹果手机等移动智能设备。 + 2.速度快:该计算库是当前性能最好的开源前向计算库之一,在 64 核 ARM 众核芯片上比 Caffe 和 Caffe2 快 6 倍和 12 倍,在 iPhone7 上比 Tensorflow lite 快 2.5 倍。 + 3.轻量级:该计算库编译后的后端 Linux 静态库仅 115KB , 前端 Linux 静态库 575KB , 可执行文件仅 246KB 。 + 4.FeatherCNN 采用 TensorGEMM 加速的 Winograd 变种算法,以 ARM 指令集极致提升 CPU 效率,为移动端提供强大的 AI 计算能力。使用该计算库可接近甚至达到专业神经网络芯片或 GPU 的性能,并保护用户已有硬件投资。 diff --git a/CNN/HighPerformanceComputing/Tengine/readme.md b/CNN/HighPerformanceComputing/Tengine/readme.md index 700c24cd..8d491e19 100644 --- a/CNN/HighPerformanceComputing/Tengine/readme.md +++ b/CNN/HighPerformanceComputing/Tengine/readme.md @@ -1 +1,171 @@ # Tengine 高性能神经网络推理引擎 + +[源码](https://github.com/Ewenwan/Tengine) + +[Tengine 推断引擎:树莓派也能玩转深度学习](https://shumeipai.nxez.com/2018/12/07/tengine-inference-engine-raspberry-pi-deep-learning.html) + +[Tengine Winograd快速卷积算法 ](https://github.com/Ewenwan/Winograd_tutorial_python) + +[基于ARM-v8的Tengine GEMM 矩阵乘法 汇编优化 教程 ](https://github.com/Ewenwan/Tengine_gemm_tutorial) + +[Tengine 白皮书](https://cdn-file.aijishu.com/494/739/494739128-5d51139b186ca.pdf?_upt=c49f6b9e1588562426) + +# 编译 + +> 安装相关工具 + + sudo apt-get instal git cmake + + git 是一个版本控制系统,稍后将用来从 github 网站上下载Tengine的源码 + cmake 是一个编译工具,用来产生make过程中所需要的Makefile文件 + +> 安装支持库 + +sudo apt-get install libprotobuf-dev protobuf-compiler libboost-all-dev libgoogle-glog-dev libopencv-dev libopenblas-dev + + protobuf 是一种轻便高效的数据存储格式,这是caffe各种配置文件所使用的数据格式 + boost 是一个c++的扩展程序库,稍后Tengine的编译依赖于该库 + google-glog 是一个google提供的日志系统的程序库 + opencv 是一个开源的计算机视觉库 + openblas 是一个开源的基础线性代数子程序库 + +> 特点 + +重点加速卷积等最为耗时的算子 convolution/FC/Pooling 支持多种卷积计算模式 GEMM/Direct/Winogrid + +手工汇编调优,CPU微架构极致优化,Dataflow多线程加速,适配ARM A7/A17/A35/A53/A72/A73/A55/A76 + +支持F32/F16/Int8动态量化混合精度计算模式 + + +## 框架 + +老接口: + +1. 初始化 init_tengine(); + +2. 载入模型,创建图 create_graph(nullptr, "tengine", tm_file) 普通设备 + + create_graph(nullptr, "tiny", tm_mem) // mcu stm32 + create_graph(nullptr, "zhouyi", tm_file) // 周易 AIPU + create_graph(nullptr, "nnie", tm_file, config) // 海思 nnie 3519 3516 + create_graph(nullptr, "rk3399pro", tm_mem) // rk3399pro AIPU + +3. 设置图属性 和 输入数据 + + get_graph_input_tensor(graph, 0, 0); + set_graph_attr(graph, "low_mem_mode", &val, sizeof(val)); + +4. 预推理 + + prerun_graph(graph) + +5. 正式运行 + + run_graph(graph, 1) + +6. 清理 + + release_graph_tensor(input_tensor); + release_graph_tensor(output_tensor); + postrun_graph(graph); + destroy_graph(graph); + + release_tengine(); + +新接口(类似ncnn的): + + + +## **gemm 矩阵乘法(全连接层、卷积核和输入展开后的矩阵乘法、卷积winogrid变换后的矩阵乘法)** + +矩阵乘法的加速运算 A[M K] * B[K N] ====== C[M N] + +纯c实现: +```C + +void gemm_pure_c(float* A, float* B, float* C,int m,int n,int k) +{ + for(int i=0;i 元素乘法 gemm算法 ----> 输出转换 + 权重矩阵转换 + + +1. define transform matrix + ```python + # kernel转换 + G_F23 = np.array([ + [ 1.0, 0.0, 0.0 ], + [ 0.5, 0.5, 0.5 ], + [ 0.5, -0.5, 0.5 ], + [ 0.0, 0.0, 1.0 ]]) + # 输入转换矩阵 + Bt_F23 = np.array([ + [ 1.0, 0.0, -1.0, 0.0 ], + [ 0.0, 1.0, 1.0, 0.0 ], + [ 0.0, -1.0, 1.0, 0.0 ], + [ 0.0, 1.0, 0.0, -1.0 ]]) + # 输出转换矩阵 + At_F23 = np.array([ + [ 1.0, 1.0, 1.0, 0.0 ], + [ 0.0, 1.0, -1.0, -1.0 ]]) + ``` +2. compute transformation for input, kernel, output + ```python + # 输入矩阵转换 g' = G*g*G转置 + def trans_kernel(g): + return np.dot(np.dot(G_F23,g),G_F23.T) + # 权重kernel转换 d' = B转置*d*B转 + def trans_input(d): + return np.dot(np.dot(Bt_F23,d),Bt_F23.T) + # o' = g' * d' + # 输出转换 o = A转置*o'*A转 + def trans_output(r): + return np.dot(np.dot(At_F23,r),At_F23.T) + ``` +3. do conv_winof23, conv_direct + ```python + def wino_f23(kernel,input): + tran_inp = trans_input(input) + tran_ker = trans_kernel(kernel) + mid = tran_inp * tran_ker + out = trans_output(mid) + return out + + def conv_direct(kernel,input): + out=np.zeros((2,2)) + for h in range(2): + for w in range(2): + out[h,w]=np.sum(input[h:h+3,w:w+3]*kernel) + return out + ``` + + + + + diff --git a/CNN/HighPerformanceComputing/doc/ARM-Cortex-A-Series-Version-4.pdf b/CNN/HighPerformanceComputing/doc/ARM-Cortex-A-Series-Version-4.pdf new file mode 100644 index 00000000..121477cb Binary files /dev/null and b/CNN/HighPerformanceComputing/doc/ARM-Cortex-A-Series-Version-4.pdf differ diff --git a/CNN/HighPerformanceComputing/doc/ARMCompilerVersion5.04-armasmUser-Guide.pdf b/CNN/HighPerformanceComputing/doc/ARMCompilerVersion5.04-armasmUser-Guide.pdf new file mode 100644 index 00000000..98b5b1e5 Binary files /dev/null and b/CNN/HighPerformanceComputing/doc/ARMCompilerVersion5.04-armasmUser-Guide.pdf differ diff --git "a/CNN/HighPerformanceComputing/doc/ARMV7 NEON\346\261\207\347\274\226\346\214\207\344\273\244\350\257\246\350\247\243\344\270\255\346\226\207\347\211\210RealView\347\274\226\350\257\221\345\267\245\345\205\2673.1 \347\211\210.pdf" "b/CNN/HighPerformanceComputing/doc/ARMV7 NEON\346\261\207\347\274\226\346\214\207\344\273\244\350\257\246\350\247\243\344\270\255\346\226\207\347\211\210RealView\347\274\226\350\257\221\345\267\245\345\205\2673.1 \347\211\210.pdf" new file mode 100644 index 00000000..55c6cdfe Binary files /dev/null and "b/CNN/HighPerformanceComputing/doc/ARMV7 NEON\346\261\207\347\274\226\346\214\207\344\273\244\350\257\246\350\247\243\344\270\255\346\226\207\347\211\210RealView\347\274\226\350\257\221\345\267\245\345\205\2673.1 \347\211\210.pdf" differ diff --git "a/CNN/HighPerformanceComputing/doc/ARMV7 NEON\346\261\207\347\274\226\346\214\207\344\273\244\350\257\246\350\247\243\344\270\255\346\226\207\347\211\210RealView\347\274\226\350\257\221\345\267\245\345\205\2674.0 \347\211\210.pdf" "b/CNN/HighPerformanceComputing/doc/ARMV7 NEON\346\261\207\347\274\226\346\214\207\344\273\244\350\257\246\350\247\243\344\270\255\346\226\207\347\211\210RealView\347\274\226\350\257\221\345\267\245\345\205\2674.0 \347\211\210.pdf" new file mode 100644 index 00000000..edde6220 Binary files /dev/null and "b/CNN/HighPerformanceComputing/doc/ARMV7 NEON\346\261\207\347\274\226\346\214\207\344\273\244\350\257\246\350\247\243\344\270\255\346\226\207\347\211\210RealView\347\274\226\350\257\221\345\267\245\345\205\2674.0 \347\211\210.pdf" differ diff --git "a/CNN/HighPerformanceComputing/doc/ARM\345\265\214\345\205\245\345\274\217\347\263\273\347\273\237\347\232\204DNN\346\200\247\350\203\275\344\274\230\345\214\226.pdf" "b/CNN/HighPerformanceComputing/doc/ARM\345\265\214\345\205\245\345\274\217\347\263\273\347\273\237\347\232\204DNN\346\200\247\350\203\275\344\274\230\345\214\226.pdf" new file mode 100644 index 00000000..ddfa5c0d Binary files /dev/null and "b/CNN/HighPerformanceComputing/doc/ARM\345\265\214\345\205\245\345\274\217\347\263\273\347\273\237\347\232\204DNN\346\200\247\350\203\275\344\274\230\345\214\226.pdf" differ diff --git a/CNN/HighPerformanceComputing/doc/AUGEM automatically generate high performance dense linear algebra kernels on x86 CPUs.pdf b/CNN/HighPerformanceComputing/doc/AUGEM automatically generate high performance dense linear algebra kernels on x86 CPUs.pdf new file mode 100644 index 00000000..1a4c7227 Binary files /dev/null and b/CNN/HighPerformanceComputing/doc/AUGEM automatically generate high performance dense linear algebra kernels on x86 CPUs.pdf differ diff --git "a/CNN/HighPerformanceComputing/doc/NEON\347\256\200\344\273\213\345\217\212\345\237\272\346\234\254\346\236\266\346\236\204.pdf" "b/CNN/HighPerformanceComputing/doc/NEON\347\256\200\344\273\213\345\217\212\345\237\272\346\234\254\346\236\266\346\236\204.pdf" new file mode 100644 index 00000000..f60995a5 Binary files /dev/null and "b/CNN/HighPerformanceComputing/doc/NEON\347\256\200\344\273\213\345\217\212\345\237\272\346\234\254\346\236\266\346\236\204.pdf" differ diff --git "a/CNN/HighPerformanceComputing/doc/NEON\347\274\226\347\250\213-\344\274\230\345\214\226\345\277\203\345\276\227\345\217\212\345\206\205\350\201\224\346\261\207\347\274\226\344\275\277\347\224\250\345\277\203\345\276\227.pdf" "b/CNN/HighPerformanceComputing/doc/NEON\347\274\226\347\250\213-\344\274\230\345\214\226\345\277\203\345\276\227\345\217\212\345\206\205\350\201\224\346\261\207\347\274\226\344\275\277\347\224\250\345\277\203\345\276\227.pdf" new file mode 100644 index 00000000..1dfa8ab0 Binary files /dev/null and "b/CNN/HighPerformanceComputing/doc/NEON\347\274\226\347\250\213-\344\274\230\345\214\226\345\277\203\345\276\227\345\217\212\345\206\205\350\201\224\346\261\207\347\274\226\344\275\277\347\224\250\345\277\203\345\276\227.pdf" differ diff --git "a/CNN/HighPerformanceComputing/doc/arm-cortex_a_\347\263\273\345\210\227\347\274\226\347\250\213\346\211\213\345\206\214.pdf" "b/CNN/HighPerformanceComputing/doc/arm-cortex_a_\347\263\273\345\210\227\347\274\226\347\250\213\346\211\213\345\206\214.pdf" new file mode 100644 index 00000000..121477cb Binary files /dev/null and "b/CNN/HighPerformanceComputing/doc/arm-cortex_a_\347\263\273\345\210\227\347\274\226\347\250\213\346\211\213\345\206\214.pdf" differ diff --git a/CNN/HighPerformanceComputing/doc/arm_neon.h b/CNN/HighPerformanceComputing/doc/arm_neon.h new file mode 100644 index 00000000..7e138de1 --- /dev/null +++ b/CNN/HighPerformanceComputing/doc/arm_neon.h @@ -0,0 +1,34020 @@ +/* ARM NEON intrinsics include file. + + Copyright (C) 2011-2019 Free Software Foundation, Inc. + Contributed by ARM Ltd. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _AARCH64_NEON_H_ +#define _AARCH64_NEON_H_ + +#pragma GCC push_options +#pragma GCC target ("+nothing+simd") + +#include + +#define __AARCH64_UINT64_C(__C) ((uint64_t) __C) +#define __AARCH64_INT64_C(__C) ((int64_t) __C) + +typedef __Int8x8_t int8x8_t; +typedef __Int16x4_t int16x4_t; +typedef __Int32x2_t int32x2_t; +typedef __Int64x1_t int64x1_t; +typedef __Float16x4_t float16x4_t; +typedef __Float32x2_t float32x2_t; +typedef __Poly8x8_t poly8x8_t; +typedef __Poly16x4_t poly16x4_t; +typedef __Uint8x8_t uint8x8_t; +typedef __Uint16x4_t uint16x4_t; +typedef __Uint32x2_t uint32x2_t; +typedef __Float64x1_t float64x1_t; +typedef __Uint64x1_t uint64x1_t; +typedef __Int8x16_t int8x16_t; +typedef __Int16x8_t int16x8_t; +typedef __Int32x4_t int32x4_t; +typedef __Int64x2_t int64x2_t; +typedef __Float16x8_t float16x8_t; +typedef __Float32x4_t float32x4_t; +typedef __Float64x2_t float64x2_t; +typedef __Poly8x16_t poly8x16_t; +typedef __Poly16x8_t poly16x8_t; +typedef __Poly64x2_t poly64x2_t; +typedef __Poly64x1_t poly64x1_t; +typedef __Uint8x16_t uint8x16_t; +typedef __Uint16x8_t uint16x8_t; +typedef __Uint32x4_t uint32x4_t; +typedef __Uint64x2_t uint64x2_t; + +typedef __Poly8_t poly8_t; +typedef __Poly16_t poly16_t; +typedef __Poly64_t poly64_t; +typedef __Poly128_t poly128_t; + +typedef __fp16 float16_t; +typedef float float32_t; +typedef double float64_t; + +typedef struct int8x8x2_t +{ + int8x8_t val[2]; +} int8x8x2_t; + +typedef struct int8x16x2_t +{ + int8x16_t val[2]; +} int8x16x2_t; + +typedef struct int16x4x2_t +{ + int16x4_t val[2]; +} int16x4x2_t; + +typedef struct int16x8x2_t +{ + int16x8_t val[2]; +} int16x8x2_t; + +typedef struct int32x2x2_t +{ + int32x2_t val[2]; +} int32x2x2_t; + +typedef struct int32x4x2_t +{ + int32x4_t val[2]; +} int32x4x2_t; + +typedef struct int64x1x2_t +{ + int64x1_t val[2]; +} int64x1x2_t; + +typedef struct int64x2x2_t +{ + int64x2_t val[2]; +} int64x2x2_t; + +typedef struct uint8x8x2_t +{ + uint8x8_t val[2]; +} uint8x8x2_t; + +typedef struct uint8x16x2_t +{ + uint8x16_t val[2]; +} uint8x16x2_t; + +typedef struct uint16x4x2_t +{ + uint16x4_t val[2]; +} uint16x4x2_t; + +typedef struct uint16x8x2_t +{ + uint16x8_t val[2]; +} uint16x8x2_t; + +typedef struct uint32x2x2_t +{ + uint32x2_t val[2]; +} uint32x2x2_t; + +typedef struct uint32x4x2_t +{ + uint32x4_t val[2]; +} uint32x4x2_t; + +typedef struct uint64x1x2_t +{ + uint64x1_t val[2]; +} uint64x1x2_t; + +typedef struct uint64x2x2_t +{ + uint64x2_t val[2]; +} uint64x2x2_t; + +typedef struct float16x4x2_t +{ + float16x4_t val[2]; +} float16x4x2_t; + +typedef struct float16x8x2_t +{ + float16x8_t val[2]; +} float16x8x2_t; + +typedef struct float32x2x2_t +{ + float32x2_t val[2]; +} float32x2x2_t; + +typedef struct float32x4x2_t +{ + float32x4_t val[2]; +} float32x4x2_t; + +typedef struct float64x2x2_t +{ + float64x2_t val[2]; +} float64x2x2_t; + +typedef struct float64x1x2_t +{ + float64x1_t val[2]; +} float64x1x2_t; + +typedef struct poly8x8x2_t +{ + poly8x8_t val[2]; +} poly8x8x2_t; + +typedef struct poly8x16x2_t +{ + poly8x16_t val[2]; +} poly8x16x2_t; + +typedef struct poly16x4x2_t +{ + poly16x4_t val[2]; +} poly16x4x2_t; + +typedef struct poly16x8x2_t +{ + poly16x8_t val[2]; +} poly16x8x2_t; + +typedef struct poly64x1x2_t +{ + poly64x1_t val[2]; +} poly64x1x2_t; + +typedef struct poly64x1x3_t +{ + poly64x1_t val[3]; +} poly64x1x3_t; + +typedef struct poly64x1x4_t +{ + poly64x1_t val[4]; +} poly64x1x4_t; + +typedef struct poly64x2x2_t +{ + poly64x2_t val[2]; +} poly64x2x2_t; + +typedef struct poly64x2x3_t +{ + poly64x2_t val[3]; +} poly64x2x3_t; + +typedef struct poly64x2x4_t +{ + poly64x2_t val[4]; +} poly64x2x4_t; + +typedef struct int8x8x3_t +{ + int8x8_t val[3]; +} int8x8x3_t; + +typedef struct int8x16x3_t +{ + int8x16_t val[3]; +} int8x16x3_t; + +typedef struct int16x4x3_t +{ + int16x4_t val[3]; +} int16x4x3_t; + +typedef struct int16x8x3_t +{ + int16x8_t val[3]; +} int16x8x3_t; + +typedef struct int32x2x3_t +{ + int32x2_t val[3]; +} int32x2x3_t; + +typedef struct int32x4x3_t +{ + int32x4_t val[3]; +} int32x4x3_t; + +typedef struct int64x1x3_t +{ + int64x1_t val[3]; +} int64x1x3_t; + +typedef struct int64x2x3_t +{ + int64x2_t val[3]; +} int64x2x3_t; + +typedef struct uint8x8x3_t +{ + uint8x8_t val[3]; +} uint8x8x3_t; + +typedef struct uint8x16x3_t +{ + uint8x16_t val[3]; +} uint8x16x3_t; + +typedef struct uint16x4x3_t +{ + uint16x4_t val[3]; +} uint16x4x3_t; + +typedef struct uint16x8x3_t +{ + uint16x8_t val[3]; +} uint16x8x3_t; + +typedef struct uint32x2x3_t +{ + uint32x2_t val[3]; +} uint32x2x3_t; + +typedef struct uint32x4x3_t +{ + uint32x4_t val[3]; +} uint32x4x3_t; + +typedef struct uint64x1x3_t +{ + uint64x1_t val[3]; +} uint64x1x3_t; + +typedef struct uint64x2x3_t +{ + uint64x2_t val[3]; +} uint64x2x3_t; + +typedef struct float16x4x3_t +{ + float16x4_t val[3]; +} float16x4x3_t; + +typedef struct float16x8x3_t +{ + float16x8_t val[3]; +} float16x8x3_t; + +typedef struct float32x2x3_t +{ + float32x2_t val[3]; +} float32x2x3_t; + +typedef struct float32x4x3_t +{ + float32x4_t val[3]; +} float32x4x3_t; + +typedef struct float64x2x3_t +{ + float64x2_t val[3]; +} float64x2x3_t; + +typedef struct float64x1x3_t +{ + float64x1_t val[3]; +} float64x1x3_t; + +typedef struct poly8x8x3_t +{ + poly8x8_t val[3]; +} poly8x8x3_t; + +typedef struct poly8x16x3_t +{ + poly8x16_t val[3]; +} poly8x16x3_t; + +typedef struct poly16x4x3_t +{ + poly16x4_t val[3]; +} poly16x4x3_t; + +typedef struct poly16x8x3_t +{ + poly16x8_t val[3]; +} poly16x8x3_t; + +typedef struct int8x8x4_t +{ + int8x8_t val[4]; +} int8x8x4_t; + +typedef struct int8x16x4_t +{ + int8x16_t val[4]; +} int8x16x4_t; + +typedef struct int16x4x4_t +{ + int16x4_t val[4]; +} int16x4x4_t; + +typedef struct int16x8x4_t +{ + int16x8_t val[4]; +} int16x8x4_t; + +typedef struct int32x2x4_t +{ + int32x2_t val[4]; +} int32x2x4_t; + +typedef struct int32x4x4_t +{ + int32x4_t val[4]; +} int32x4x4_t; + +typedef struct int64x1x4_t +{ + int64x1_t val[4]; +} int64x1x4_t; + +typedef struct int64x2x4_t +{ + int64x2_t val[4]; +} int64x2x4_t; + +typedef struct uint8x8x4_t +{ + uint8x8_t val[4]; +} uint8x8x4_t; + +typedef struct uint8x16x4_t +{ + uint8x16_t val[4]; +} uint8x16x4_t; + +typedef struct uint16x4x4_t +{ + uint16x4_t val[4]; +} uint16x4x4_t; + +typedef struct uint16x8x4_t +{ + uint16x8_t val[4]; +} uint16x8x4_t; + +typedef struct uint32x2x4_t +{ + uint32x2_t val[4]; +} uint32x2x4_t; + +typedef struct uint32x4x4_t +{ + uint32x4_t val[4]; +} uint32x4x4_t; + +typedef struct uint64x1x4_t +{ + uint64x1_t val[4]; +} uint64x1x4_t; + +typedef struct uint64x2x4_t +{ + uint64x2_t val[4]; +} uint64x2x4_t; + +typedef struct float16x4x4_t +{ + float16x4_t val[4]; +} float16x4x4_t; + +typedef struct float16x8x4_t +{ + float16x8_t val[4]; +} float16x8x4_t; + +typedef struct float32x2x4_t +{ + float32x2_t val[4]; +} float32x2x4_t; + +typedef struct float32x4x4_t +{ + float32x4_t val[4]; +} float32x4x4_t; + +typedef struct float64x2x4_t +{ + float64x2_t val[4]; +} float64x2x4_t; + +typedef struct float64x1x4_t +{ + float64x1_t val[4]; +} float64x1x4_t; + +typedef struct poly8x8x4_t +{ + poly8x8_t val[4]; +} poly8x8x4_t; + +typedef struct poly8x16x4_t +{ + poly8x16_t val[4]; +} poly8x16x4_t; + +typedef struct poly16x4x4_t +{ + poly16x4_t val[4]; +} poly16x4x4_t; + +typedef struct poly16x8x4_t +{ + poly16x8_t val[4]; +} poly16x8x4_t; + +/* __aarch64_vdup_lane internal macros. */ +#define __aarch64_vdup_lane_any(__size, __q, __a, __b) \ + vdup##__q##_n_##__size (__aarch64_vget_lane_any (__a, __b)) + +#define __aarch64_vdup_lane_f16(__a, __b) \ + __aarch64_vdup_lane_any (f16, , __a, __b) +#define __aarch64_vdup_lane_f32(__a, __b) \ + __aarch64_vdup_lane_any (f32, , __a, __b) +#define __aarch64_vdup_lane_f64(__a, __b) \ + __aarch64_vdup_lane_any (f64, , __a, __b) +#define __aarch64_vdup_lane_p8(__a, __b) \ + __aarch64_vdup_lane_any (p8, , __a, __b) +#define __aarch64_vdup_lane_p16(__a, __b) \ + __aarch64_vdup_lane_any (p16, , __a, __b) +#define __aarch64_vdup_lane_p64(__a, __b) \ + __aarch64_vdup_lane_any (p64, , __a, __b) +#define __aarch64_vdup_lane_s8(__a, __b) \ + __aarch64_vdup_lane_any (s8, , __a, __b) +#define __aarch64_vdup_lane_s16(__a, __b) \ + __aarch64_vdup_lane_any (s16, , __a, __b) +#define __aarch64_vdup_lane_s32(__a, __b) \ + __aarch64_vdup_lane_any (s32, , __a, __b) +#define __aarch64_vdup_lane_s64(__a, __b) \ + __aarch64_vdup_lane_any (s64, , __a, __b) +#define __aarch64_vdup_lane_u8(__a, __b) \ + __aarch64_vdup_lane_any (u8, , __a, __b) +#define __aarch64_vdup_lane_u16(__a, __b) \ + __aarch64_vdup_lane_any (u16, , __a, __b) +#define __aarch64_vdup_lane_u32(__a, __b) \ + __aarch64_vdup_lane_any (u32, , __a, __b) +#define __aarch64_vdup_lane_u64(__a, __b) \ + __aarch64_vdup_lane_any (u64, , __a, __b) + +/* __aarch64_vdup_laneq internal macros. */ +#define __aarch64_vdup_laneq_f16(__a, __b) \ + __aarch64_vdup_lane_any (f16, , __a, __b) +#define __aarch64_vdup_laneq_f32(__a, __b) \ + __aarch64_vdup_lane_any (f32, , __a, __b) +#define __aarch64_vdup_laneq_f64(__a, __b) \ + __aarch64_vdup_lane_any (f64, , __a, __b) +#define __aarch64_vdup_laneq_p8(__a, __b) \ + __aarch64_vdup_lane_any (p8, , __a, __b) +#define __aarch64_vdup_laneq_p16(__a, __b) \ + __aarch64_vdup_lane_any (p16, , __a, __b) +#define __aarch64_vdup_laneq_p64(__a, __b) \ + __aarch64_vdup_lane_any (p64, , __a, __b) +#define __aarch64_vdup_laneq_s8(__a, __b) \ + __aarch64_vdup_lane_any (s8, , __a, __b) +#define __aarch64_vdup_laneq_s16(__a, __b) \ + __aarch64_vdup_lane_any (s16, , __a, __b) +#define __aarch64_vdup_laneq_s32(__a, __b) \ + __aarch64_vdup_lane_any (s32, , __a, __b) +#define __aarch64_vdup_laneq_s64(__a, __b) \ + __aarch64_vdup_lane_any (s64, , __a, __b) +#define __aarch64_vdup_laneq_u8(__a, __b) \ + __aarch64_vdup_lane_any (u8, , __a, __b) +#define __aarch64_vdup_laneq_u16(__a, __b) \ + __aarch64_vdup_lane_any (u16, , __a, __b) +#define __aarch64_vdup_laneq_u32(__a, __b) \ + __aarch64_vdup_lane_any (u32, , __a, __b) +#define __aarch64_vdup_laneq_u64(__a, __b) \ + __aarch64_vdup_lane_any (u64, , __a, __b) + +/* __aarch64_vdupq_lane internal macros. */ +#define __aarch64_vdupq_lane_f16(__a, __b) \ + __aarch64_vdup_lane_any (f16, q, __a, __b) +#define __aarch64_vdupq_lane_f32(__a, __b) \ + __aarch64_vdup_lane_any (f32, q, __a, __b) +#define __aarch64_vdupq_lane_f64(__a, __b) \ + __aarch64_vdup_lane_any (f64, q, __a, __b) +#define __aarch64_vdupq_lane_p8(__a, __b) \ + __aarch64_vdup_lane_any (p8, q, __a, __b) +#define __aarch64_vdupq_lane_p16(__a, __b) \ + __aarch64_vdup_lane_any (p16, q, __a, __b) +#define __aarch64_vdupq_lane_p64(__a, __b) \ + __aarch64_vdup_lane_any (p64, q, __a, __b) +#define __aarch64_vdupq_lane_s8(__a, __b) \ + __aarch64_vdup_lane_any (s8, q, __a, __b) +#define __aarch64_vdupq_lane_s16(__a, __b) \ + __aarch64_vdup_lane_any (s16, q, __a, __b) +#define __aarch64_vdupq_lane_s32(__a, __b) \ + __aarch64_vdup_lane_any (s32, q, __a, __b) +#define __aarch64_vdupq_lane_s64(__a, __b) \ + __aarch64_vdup_lane_any (s64, q, __a, __b) +#define __aarch64_vdupq_lane_u8(__a, __b) \ + __aarch64_vdup_lane_any (u8, q, __a, __b) +#define __aarch64_vdupq_lane_u16(__a, __b) \ + __aarch64_vdup_lane_any (u16, q, __a, __b) +#define __aarch64_vdupq_lane_u32(__a, __b) \ + __aarch64_vdup_lane_any (u32, q, __a, __b) +#define __aarch64_vdupq_lane_u64(__a, __b) \ + __aarch64_vdup_lane_any (u64, q, __a, __b) + +/* __aarch64_vdupq_laneq internal macros. */ +#define __aarch64_vdupq_laneq_f16(__a, __b) \ + __aarch64_vdup_lane_any (f16, q, __a, __b) +#define __aarch64_vdupq_laneq_f32(__a, __b) \ + __aarch64_vdup_lane_any (f32, q, __a, __b) +#define __aarch64_vdupq_laneq_f64(__a, __b) \ + __aarch64_vdup_lane_any (f64, q, __a, __b) +#define __aarch64_vdupq_laneq_p8(__a, __b) \ + __aarch64_vdup_lane_any (p8, q, __a, __b) +#define __aarch64_vdupq_laneq_p16(__a, __b) \ + __aarch64_vdup_lane_any (p16, q, __a, __b) +#define __aarch64_vdupq_laneq_p64(__a, __b) \ + __aarch64_vdup_lane_any (p64, q, __a, __b) +#define __aarch64_vdupq_laneq_s8(__a, __b) \ + __aarch64_vdup_lane_any (s8, q, __a, __b) +#define __aarch64_vdupq_laneq_s16(__a, __b) \ + __aarch64_vdup_lane_any (s16, q, __a, __b) +#define __aarch64_vdupq_laneq_s32(__a, __b) \ + __aarch64_vdup_lane_any (s32, q, __a, __b) +#define __aarch64_vdupq_laneq_s64(__a, __b) \ + __aarch64_vdup_lane_any (s64, q, __a, __b) +#define __aarch64_vdupq_laneq_u8(__a, __b) \ + __aarch64_vdup_lane_any (u8, q, __a, __b) +#define __aarch64_vdupq_laneq_u16(__a, __b) \ + __aarch64_vdup_lane_any (u16, q, __a, __b) +#define __aarch64_vdupq_laneq_u32(__a, __b) \ + __aarch64_vdup_lane_any (u32, q, __a, __b) +#define __aarch64_vdupq_laneq_u64(__a, __b) \ + __aarch64_vdup_lane_any (u64, q, __a, __b) + +/* Internal macro for lane indices. */ + +#define __AARCH64_NUM_LANES(__v) (sizeof (__v) / sizeof (__v[0])) +#define __AARCH64_LANE_CHECK(__vec, __idx) \ + __builtin_aarch64_im_lane_boundsi (sizeof(__vec), sizeof(__vec[0]), __idx) + +/* For big-endian, GCC's vector indices are the opposite way around + to the architectural lane indices used by Neon intrinsics. */ +#ifdef __AARCH64EB__ +#define __aarch64_lane(__vec, __idx) (__AARCH64_NUM_LANES (__vec) - 1 - __idx) +#else +#define __aarch64_lane(__vec, __idx) __idx +#endif + +/* vget_lane internal macro. */ +#define __aarch64_vget_lane_any(__vec, __index) \ + __extension__ \ + ({ \ + __AARCH64_LANE_CHECK (__vec, __index); \ + __vec[__aarch64_lane (__vec, __index)]; \ + }) + +/* vset_lane and vld1_lane internal macro. */ +#define __aarch64_vset_lane_any(__elem, __vec, __index) \ + __extension__ \ + ({ \ + __AARCH64_LANE_CHECK (__vec, __index); \ + __vec[__aarch64_lane (__vec, __index)] = __elem; \ + __vec; \ + }) + +/* vadd */ +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vadd_s8 (int8x8_t __a, int8x8_t __b) +{ + return __a + __b; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vadd_s16 (int16x4_t __a, int16x4_t __b) +{ + return __a + __b; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vadd_s32 (int32x2_t __a, int32x2_t __b) +{ + return __a + __b; +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vadd_f32 (float32x2_t __a, float32x2_t __b) +{ + return __a + __b; +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vadd_f64 (float64x1_t __a, float64x1_t __b) +{ + return __a + __b; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vadd_u8 (uint8x8_t __a, uint8x8_t __b) +{ + return __a + __b; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vadd_u16 (uint16x4_t __a, uint16x4_t __b) +{ + return __a + __b; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vadd_u32 (uint32x2_t __a, uint32x2_t __b) +{ + return __a + __b; +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vadd_s64 (int64x1_t __a, int64x1_t __b) +{ + return __a + __b; +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vadd_u64 (uint64x1_t __a, uint64x1_t __b) +{ + return __a + __b; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddq_s8 (int8x16_t __a, int8x16_t __b) +{ + return __a + __b; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddq_s16 (int16x8_t __a, int16x8_t __b) +{ + return __a + __b; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddq_s32 (int32x4_t __a, int32x4_t __b) +{ + return __a + __b; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddq_s64 (int64x2_t __a, int64x2_t __b) +{ + return __a + __b; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddq_f32 (float32x4_t __a, float32x4_t __b) +{ + return __a + __b; +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddq_f64 (float64x2_t __a, float64x2_t __b) +{ + return __a + __b; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddq_u8 (uint8x16_t __a, uint8x16_t __b) +{ + return __a + __b; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddq_u16 (uint16x8_t __a, uint16x8_t __b) +{ + return __a + __b; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddq_u32 (uint32x4_t __a, uint32x4_t __b) +{ + return __a + __b; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddq_u64 (uint64x2_t __a, uint64x2_t __b) +{ + return __a + __b; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddl_s8 (int8x8_t __a, int8x8_t __b) +{ + return (int16x8_t) __builtin_aarch64_saddlv8qi (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddl_s16 (int16x4_t __a, int16x4_t __b) +{ + return (int32x4_t) __builtin_aarch64_saddlv4hi (__a, __b); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddl_s32 (int32x2_t __a, int32x2_t __b) +{ + return (int64x2_t) __builtin_aarch64_saddlv2si (__a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddl_u8 (uint8x8_t __a, uint8x8_t __b) +{ + return (uint16x8_t) __builtin_aarch64_uaddlv8qi ((int8x8_t) __a, + (int8x8_t) __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddl_u16 (uint16x4_t __a, uint16x4_t __b) +{ + return (uint32x4_t) __builtin_aarch64_uaddlv4hi ((int16x4_t) __a, + (int16x4_t) __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddl_u32 (uint32x2_t __a, uint32x2_t __b) +{ + return (uint64x2_t) __builtin_aarch64_uaddlv2si ((int32x2_t) __a, + (int32x2_t) __b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddl_high_s8 (int8x16_t __a, int8x16_t __b) +{ + return (int16x8_t) __builtin_aarch64_saddl2v16qi (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddl_high_s16 (int16x8_t __a, int16x8_t __b) +{ + return (int32x4_t) __builtin_aarch64_saddl2v8hi (__a, __b); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddl_high_s32 (int32x4_t __a, int32x4_t __b) +{ + return (int64x2_t) __builtin_aarch64_saddl2v4si (__a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddl_high_u8 (uint8x16_t __a, uint8x16_t __b) +{ + return (uint16x8_t) __builtin_aarch64_uaddl2v16qi ((int8x16_t) __a, + (int8x16_t) __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddl_high_u16 (uint16x8_t __a, uint16x8_t __b) +{ + return (uint32x4_t) __builtin_aarch64_uaddl2v8hi ((int16x8_t) __a, + (int16x8_t) __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddl_high_u32 (uint32x4_t __a, uint32x4_t __b) +{ + return (uint64x2_t) __builtin_aarch64_uaddl2v4si ((int32x4_t) __a, + (int32x4_t) __b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddw_s8 (int16x8_t __a, int8x8_t __b) +{ + return (int16x8_t) __builtin_aarch64_saddwv8qi (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddw_s16 (int32x4_t __a, int16x4_t __b) +{ + return (int32x4_t) __builtin_aarch64_saddwv4hi (__a, __b); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddw_s32 (int64x2_t __a, int32x2_t __b) +{ + return (int64x2_t) __builtin_aarch64_saddwv2si (__a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddw_u8 (uint16x8_t __a, uint8x8_t __b) +{ + return (uint16x8_t) __builtin_aarch64_uaddwv8qi ((int16x8_t) __a, + (int8x8_t) __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddw_u16 (uint32x4_t __a, uint16x4_t __b) +{ + return (uint32x4_t) __builtin_aarch64_uaddwv4hi ((int32x4_t) __a, + (int16x4_t) __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddw_u32 (uint64x2_t __a, uint32x2_t __b) +{ + return (uint64x2_t) __builtin_aarch64_uaddwv2si ((int64x2_t) __a, + (int32x2_t) __b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddw_high_s8 (int16x8_t __a, int8x16_t __b) +{ + return (int16x8_t) __builtin_aarch64_saddw2v16qi (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddw_high_s16 (int32x4_t __a, int16x8_t __b) +{ + return (int32x4_t) __builtin_aarch64_saddw2v8hi (__a, __b); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddw_high_s32 (int64x2_t __a, int32x4_t __b) +{ + return (int64x2_t) __builtin_aarch64_saddw2v4si (__a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddw_high_u8 (uint16x8_t __a, uint8x16_t __b) +{ + return (uint16x8_t) __builtin_aarch64_uaddw2v16qi ((int16x8_t) __a, + (int8x16_t) __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddw_high_u16 (uint32x4_t __a, uint16x8_t __b) +{ + return (uint32x4_t) __builtin_aarch64_uaddw2v8hi ((int32x4_t) __a, + (int16x8_t) __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddw_high_u32 (uint64x2_t __a, uint32x4_t __b) +{ + return (uint64x2_t) __builtin_aarch64_uaddw2v4si ((int64x2_t) __a, + (int32x4_t) __b); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vhadd_s8 (int8x8_t __a, int8x8_t __b) +{ + return (int8x8_t) __builtin_aarch64_shaddv8qi (__a, __b); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vhadd_s16 (int16x4_t __a, int16x4_t __b) +{ + return (int16x4_t) __builtin_aarch64_shaddv4hi (__a, __b); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vhadd_s32 (int32x2_t __a, int32x2_t __b) +{ + return (int32x2_t) __builtin_aarch64_shaddv2si (__a, __b); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vhadd_u8 (uint8x8_t __a, uint8x8_t __b) +{ + return (uint8x8_t) __builtin_aarch64_uhaddv8qi ((int8x8_t) __a, + (int8x8_t) __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vhadd_u16 (uint16x4_t __a, uint16x4_t __b) +{ + return (uint16x4_t) __builtin_aarch64_uhaddv4hi ((int16x4_t) __a, + (int16x4_t) __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vhadd_u32 (uint32x2_t __a, uint32x2_t __b) +{ + return (uint32x2_t) __builtin_aarch64_uhaddv2si ((int32x2_t) __a, + (int32x2_t) __b); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vhaddq_s8 (int8x16_t __a, int8x16_t __b) +{ + return (int8x16_t) __builtin_aarch64_shaddv16qi (__a, __b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vhaddq_s16 (int16x8_t __a, int16x8_t __b) +{ + return (int16x8_t) __builtin_aarch64_shaddv8hi (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vhaddq_s32 (int32x4_t __a, int32x4_t __b) +{ + return (int32x4_t) __builtin_aarch64_shaddv4si (__a, __b); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vhaddq_u8 (uint8x16_t __a, uint8x16_t __b) +{ + return (uint8x16_t) __builtin_aarch64_uhaddv16qi ((int8x16_t) __a, + (int8x16_t) __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vhaddq_u16 (uint16x8_t __a, uint16x8_t __b) +{ + return (uint16x8_t) __builtin_aarch64_uhaddv8hi ((int16x8_t) __a, + (int16x8_t) __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vhaddq_u32 (uint32x4_t __a, uint32x4_t __b) +{ + return (uint32x4_t) __builtin_aarch64_uhaddv4si ((int32x4_t) __a, + (int32x4_t) __b); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrhadd_s8 (int8x8_t __a, int8x8_t __b) +{ + return (int8x8_t) __builtin_aarch64_srhaddv8qi (__a, __b); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrhadd_s16 (int16x4_t __a, int16x4_t __b) +{ + return (int16x4_t) __builtin_aarch64_srhaddv4hi (__a, __b); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrhadd_s32 (int32x2_t __a, int32x2_t __b) +{ + return (int32x2_t) __builtin_aarch64_srhaddv2si (__a, __b); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrhadd_u8 (uint8x8_t __a, uint8x8_t __b) +{ + return (uint8x8_t) __builtin_aarch64_urhaddv8qi ((int8x8_t) __a, + (int8x8_t) __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrhadd_u16 (uint16x4_t __a, uint16x4_t __b) +{ + return (uint16x4_t) __builtin_aarch64_urhaddv4hi ((int16x4_t) __a, + (int16x4_t) __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrhadd_u32 (uint32x2_t __a, uint32x2_t __b) +{ + return (uint32x2_t) __builtin_aarch64_urhaddv2si ((int32x2_t) __a, + (int32x2_t) __b); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrhaddq_s8 (int8x16_t __a, int8x16_t __b) +{ + return (int8x16_t) __builtin_aarch64_srhaddv16qi (__a, __b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrhaddq_s16 (int16x8_t __a, int16x8_t __b) +{ + return (int16x8_t) __builtin_aarch64_srhaddv8hi (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrhaddq_s32 (int32x4_t __a, int32x4_t __b) +{ + return (int32x4_t) __builtin_aarch64_srhaddv4si (__a, __b); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrhaddq_u8 (uint8x16_t __a, uint8x16_t __b) +{ + return (uint8x16_t) __builtin_aarch64_urhaddv16qi ((int8x16_t) __a, + (int8x16_t) __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrhaddq_u16 (uint16x8_t __a, uint16x8_t __b) +{ + return (uint16x8_t) __builtin_aarch64_urhaddv8hi ((int16x8_t) __a, + (int16x8_t) __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrhaddq_u32 (uint32x4_t __a, uint32x4_t __b) +{ + return (uint32x4_t) __builtin_aarch64_urhaddv4si ((int32x4_t) __a, + (int32x4_t) __b); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddhn_s16 (int16x8_t __a, int16x8_t __b) +{ + return (int8x8_t) __builtin_aarch64_addhnv8hi (__a, __b); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddhn_s32 (int32x4_t __a, int32x4_t __b) +{ + return (int16x4_t) __builtin_aarch64_addhnv4si (__a, __b); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddhn_s64 (int64x2_t __a, int64x2_t __b) +{ + return (int32x2_t) __builtin_aarch64_addhnv2di (__a, __b); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddhn_u16 (uint16x8_t __a, uint16x8_t __b) +{ + return (uint8x8_t) __builtin_aarch64_addhnv8hi ((int16x8_t) __a, + (int16x8_t) __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddhn_u32 (uint32x4_t __a, uint32x4_t __b) +{ + return (uint16x4_t) __builtin_aarch64_addhnv4si ((int32x4_t) __a, + (int32x4_t) __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddhn_u64 (uint64x2_t __a, uint64x2_t __b) +{ + return (uint32x2_t) __builtin_aarch64_addhnv2di ((int64x2_t) __a, + (int64x2_t) __b); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vraddhn_s16 (int16x8_t __a, int16x8_t __b) +{ + return (int8x8_t) __builtin_aarch64_raddhnv8hi (__a, __b); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vraddhn_s32 (int32x4_t __a, int32x4_t __b) +{ + return (int16x4_t) __builtin_aarch64_raddhnv4si (__a, __b); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vraddhn_s64 (int64x2_t __a, int64x2_t __b) +{ + return (int32x2_t) __builtin_aarch64_raddhnv2di (__a, __b); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vraddhn_u16 (uint16x8_t __a, uint16x8_t __b) +{ + return (uint8x8_t) __builtin_aarch64_raddhnv8hi ((int16x8_t) __a, + (int16x8_t) __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vraddhn_u32 (uint32x4_t __a, uint32x4_t __b) +{ + return (uint16x4_t) __builtin_aarch64_raddhnv4si ((int32x4_t) __a, + (int32x4_t) __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vraddhn_u64 (uint64x2_t __a, uint64x2_t __b) +{ + return (uint32x2_t) __builtin_aarch64_raddhnv2di ((int64x2_t) __a, + (int64x2_t) __b); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddhn_high_s16 (int8x8_t __a, int16x8_t __b, int16x8_t __c) +{ + return (int8x16_t) __builtin_aarch64_addhn2v8hi (__a, __b, __c); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddhn_high_s32 (int16x4_t __a, int32x4_t __b, int32x4_t __c) +{ + return (int16x8_t) __builtin_aarch64_addhn2v4si (__a, __b, __c); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddhn_high_s64 (int32x2_t __a, int64x2_t __b, int64x2_t __c) +{ + return (int32x4_t) __builtin_aarch64_addhn2v2di (__a, __b, __c); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddhn_high_u16 (uint8x8_t __a, uint16x8_t __b, uint16x8_t __c) +{ + return (uint8x16_t) __builtin_aarch64_addhn2v8hi ((int8x8_t) __a, + (int16x8_t) __b, + (int16x8_t) __c); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddhn_high_u32 (uint16x4_t __a, uint32x4_t __b, uint32x4_t __c) +{ + return (uint16x8_t) __builtin_aarch64_addhn2v4si ((int16x4_t) __a, + (int32x4_t) __b, + (int32x4_t) __c); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddhn_high_u64 (uint32x2_t __a, uint64x2_t __b, uint64x2_t __c) +{ + return (uint32x4_t) __builtin_aarch64_addhn2v2di ((int32x2_t) __a, + (int64x2_t) __b, + (int64x2_t) __c); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vraddhn_high_s16 (int8x8_t __a, int16x8_t __b, int16x8_t __c) +{ + return (int8x16_t) __builtin_aarch64_raddhn2v8hi (__a, __b, __c); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vraddhn_high_s32 (int16x4_t __a, int32x4_t __b, int32x4_t __c) +{ + return (int16x8_t) __builtin_aarch64_raddhn2v4si (__a, __b, __c); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vraddhn_high_s64 (int32x2_t __a, int64x2_t __b, int64x2_t __c) +{ + return (int32x4_t) __builtin_aarch64_raddhn2v2di (__a, __b, __c); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vraddhn_high_u16 (uint8x8_t __a, uint16x8_t __b, uint16x8_t __c) +{ + return (uint8x16_t) __builtin_aarch64_raddhn2v8hi ((int8x8_t) __a, + (int16x8_t) __b, + (int16x8_t) __c); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vraddhn_high_u32 (uint16x4_t __a, uint32x4_t __b, uint32x4_t __c) +{ + return (uint16x8_t) __builtin_aarch64_raddhn2v4si ((int16x4_t) __a, + (int32x4_t) __b, + (int32x4_t) __c); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vraddhn_high_u64 (uint32x2_t __a, uint64x2_t __b, uint64x2_t __c) +{ + return (uint32x4_t) __builtin_aarch64_raddhn2v2di ((int32x2_t) __a, + (int64x2_t) __b, + (int64x2_t) __c); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdiv_f32 (float32x2_t __a, float32x2_t __b) +{ + return __a / __b; +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdiv_f64 (float64x1_t __a, float64x1_t __b) +{ + return __a / __b; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdivq_f32 (float32x4_t __a, float32x4_t __b) +{ + return __a / __b; +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdivq_f64 (float64x2_t __a, float64x2_t __b) +{ + return __a / __b; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmul_s8 (int8x8_t __a, int8x8_t __b) +{ + return __a * __b; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmul_s16 (int16x4_t __a, int16x4_t __b) +{ + return __a * __b; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmul_s32 (int32x2_t __a, int32x2_t __b) +{ + return __a * __b; +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmul_f32 (float32x2_t __a, float32x2_t __b) +{ + return __a * __b; +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmul_f64 (float64x1_t __a, float64x1_t __b) +{ + return __a * __b; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmul_u8 (uint8x8_t __a, uint8x8_t __b) +{ + return __a * __b; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmul_u16 (uint16x4_t __a, uint16x4_t __b) +{ + return __a * __b; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmul_u32 (uint32x2_t __a, uint32x2_t __b) +{ + return __a * __b; +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmul_p8 (poly8x8_t __a, poly8x8_t __b) +{ + return (poly8x8_t) __builtin_aarch64_pmulv8qi ((int8x8_t) __a, + (int8x8_t) __b); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulq_s8 (int8x16_t __a, int8x16_t __b) +{ + return __a * __b; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulq_s16 (int16x8_t __a, int16x8_t __b) +{ + return __a * __b; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulq_s32 (int32x4_t __a, int32x4_t __b) +{ + return __a * __b; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulq_f32 (float32x4_t __a, float32x4_t __b) +{ + return __a * __b; +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulq_f64 (float64x2_t __a, float64x2_t __b) +{ + return __a * __b; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulq_u8 (uint8x16_t __a, uint8x16_t __b) +{ + return __a * __b; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulq_u16 (uint16x8_t __a, uint16x8_t __b) +{ + return __a * __b; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulq_u32 (uint32x4_t __a, uint32x4_t __b) +{ + return __a * __b; +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulq_p8 (poly8x16_t __a, poly8x16_t __b) +{ + return (poly8x16_t) __builtin_aarch64_pmulv16qi ((int8x16_t) __a, + (int8x16_t) __b); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vand_s8 (int8x8_t __a, int8x8_t __b) +{ + return __a & __b; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vand_s16 (int16x4_t __a, int16x4_t __b) +{ + return __a & __b; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vand_s32 (int32x2_t __a, int32x2_t __b) +{ + return __a & __b; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vand_u8 (uint8x8_t __a, uint8x8_t __b) +{ + return __a & __b; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vand_u16 (uint16x4_t __a, uint16x4_t __b) +{ + return __a & __b; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vand_u32 (uint32x2_t __a, uint32x2_t __b) +{ + return __a & __b; +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vand_s64 (int64x1_t __a, int64x1_t __b) +{ + return __a & __b; +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vand_u64 (uint64x1_t __a, uint64x1_t __b) +{ + return __a & __b; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vandq_s8 (int8x16_t __a, int8x16_t __b) +{ + return __a & __b; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vandq_s16 (int16x8_t __a, int16x8_t __b) +{ + return __a & __b; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vandq_s32 (int32x4_t __a, int32x4_t __b) +{ + return __a & __b; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vandq_s64 (int64x2_t __a, int64x2_t __b) +{ + return __a & __b; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vandq_u8 (uint8x16_t __a, uint8x16_t __b) +{ + return __a & __b; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vandq_u16 (uint16x8_t __a, uint16x8_t __b) +{ + return __a & __b; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vandq_u32 (uint32x4_t __a, uint32x4_t __b) +{ + return __a & __b; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vandq_u64 (uint64x2_t __a, uint64x2_t __b) +{ + return __a & __b; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vorr_s8 (int8x8_t __a, int8x8_t __b) +{ + return __a | __b; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vorr_s16 (int16x4_t __a, int16x4_t __b) +{ + return __a | __b; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vorr_s32 (int32x2_t __a, int32x2_t __b) +{ + return __a | __b; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vorr_u8 (uint8x8_t __a, uint8x8_t __b) +{ + return __a | __b; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vorr_u16 (uint16x4_t __a, uint16x4_t __b) +{ + return __a | __b; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vorr_u32 (uint32x2_t __a, uint32x2_t __b) +{ + return __a | __b; +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vorr_s64 (int64x1_t __a, int64x1_t __b) +{ + return __a | __b; +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vorr_u64 (uint64x1_t __a, uint64x1_t __b) +{ + return __a | __b; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vorrq_s8 (int8x16_t __a, int8x16_t __b) +{ + return __a | __b; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vorrq_s16 (int16x8_t __a, int16x8_t __b) +{ + return __a | __b; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vorrq_s32 (int32x4_t __a, int32x4_t __b) +{ + return __a | __b; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vorrq_s64 (int64x2_t __a, int64x2_t __b) +{ + return __a | __b; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vorrq_u8 (uint8x16_t __a, uint8x16_t __b) +{ + return __a | __b; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vorrq_u16 (uint16x8_t __a, uint16x8_t __b) +{ + return __a | __b; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vorrq_u32 (uint32x4_t __a, uint32x4_t __b) +{ + return __a | __b; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vorrq_u64 (uint64x2_t __a, uint64x2_t __b) +{ + return __a | __b; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +veor_s8 (int8x8_t __a, int8x8_t __b) +{ + return __a ^ __b; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +veor_s16 (int16x4_t __a, int16x4_t __b) +{ + return __a ^ __b; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +veor_s32 (int32x2_t __a, int32x2_t __b) +{ + return __a ^ __b; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +veor_u8 (uint8x8_t __a, uint8x8_t __b) +{ + return __a ^ __b; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +veor_u16 (uint16x4_t __a, uint16x4_t __b) +{ + return __a ^ __b; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +veor_u32 (uint32x2_t __a, uint32x2_t __b) +{ + return __a ^ __b; +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +veor_s64 (int64x1_t __a, int64x1_t __b) +{ + return __a ^ __b; +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +veor_u64 (uint64x1_t __a, uint64x1_t __b) +{ + return __a ^ __b; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +veorq_s8 (int8x16_t __a, int8x16_t __b) +{ + return __a ^ __b; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +veorq_s16 (int16x8_t __a, int16x8_t __b) +{ + return __a ^ __b; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +veorq_s32 (int32x4_t __a, int32x4_t __b) +{ + return __a ^ __b; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +veorq_s64 (int64x2_t __a, int64x2_t __b) +{ + return __a ^ __b; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +veorq_u8 (uint8x16_t __a, uint8x16_t __b) +{ + return __a ^ __b; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +veorq_u16 (uint16x8_t __a, uint16x8_t __b) +{ + return __a ^ __b; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +veorq_u32 (uint32x4_t __a, uint32x4_t __b) +{ + return __a ^ __b; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +veorq_u64 (uint64x2_t __a, uint64x2_t __b) +{ + return __a ^ __b; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbic_s8 (int8x8_t __a, int8x8_t __b) +{ + return __a & ~__b; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbic_s16 (int16x4_t __a, int16x4_t __b) +{ + return __a & ~__b; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbic_s32 (int32x2_t __a, int32x2_t __b) +{ + return __a & ~__b; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbic_u8 (uint8x8_t __a, uint8x8_t __b) +{ + return __a & ~__b; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbic_u16 (uint16x4_t __a, uint16x4_t __b) +{ + return __a & ~__b; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbic_u32 (uint32x2_t __a, uint32x2_t __b) +{ + return __a & ~__b; +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbic_s64 (int64x1_t __a, int64x1_t __b) +{ + return __a & ~__b; +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbic_u64 (uint64x1_t __a, uint64x1_t __b) +{ + return __a & ~__b; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbicq_s8 (int8x16_t __a, int8x16_t __b) +{ + return __a & ~__b; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbicq_s16 (int16x8_t __a, int16x8_t __b) +{ + return __a & ~__b; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbicq_s32 (int32x4_t __a, int32x4_t __b) +{ + return __a & ~__b; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbicq_s64 (int64x2_t __a, int64x2_t __b) +{ + return __a & ~__b; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbicq_u8 (uint8x16_t __a, uint8x16_t __b) +{ + return __a & ~__b; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbicq_u16 (uint16x8_t __a, uint16x8_t __b) +{ + return __a & ~__b; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbicq_u32 (uint32x4_t __a, uint32x4_t __b) +{ + return __a & ~__b; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbicq_u64 (uint64x2_t __a, uint64x2_t __b) +{ + return __a & ~__b; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vorn_s8 (int8x8_t __a, int8x8_t __b) +{ + return __a | ~__b; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vorn_s16 (int16x4_t __a, int16x4_t __b) +{ + return __a | ~__b; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vorn_s32 (int32x2_t __a, int32x2_t __b) +{ + return __a | ~__b; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vorn_u8 (uint8x8_t __a, uint8x8_t __b) +{ + return __a | ~__b; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vorn_u16 (uint16x4_t __a, uint16x4_t __b) +{ + return __a | ~__b; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vorn_u32 (uint32x2_t __a, uint32x2_t __b) +{ + return __a | ~__b; +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vorn_s64 (int64x1_t __a, int64x1_t __b) +{ + return __a | ~__b; +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vorn_u64 (uint64x1_t __a, uint64x1_t __b) +{ + return __a | ~__b; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vornq_s8 (int8x16_t __a, int8x16_t __b) +{ + return __a | ~__b; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vornq_s16 (int16x8_t __a, int16x8_t __b) +{ + return __a | ~__b; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vornq_s32 (int32x4_t __a, int32x4_t __b) +{ + return __a | ~__b; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vornq_s64 (int64x2_t __a, int64x2_t __b) +{ + return __a | ~__b; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vornq_u8 (uint8x16_t __a, uint8x16_t __b) +{ + return __a | ~__b; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vornq_u16 (uint16x8_t __a, uint16x8_t __b) +{ + return __a | ~__b; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vornq_u32 (uint32x4_t __a, uint32x4_t __b) +{ + return __a | ~__b; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vornq_u64 (uint64x2_t __a, uint64x2_t __b) +{ + return __a | ~__b; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsub_s8 (int8x8_t __a, int8x8_t __b) +{ + return __a - __b; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsub_s16 (int16x4_t __a, int16x4_t __b) +{ + return __a - __b; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsub_s32 (int32x2_t __a, int32x2_t __b) +{ + return __a - __b; +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsub_f32 (float32x2_t __a, float32x2_t __b) +{ + return __a - __b; +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsub_f64 (float64x1_t __a, float64x1_t __b) +{ + return __a - __b; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsub_u8 (uint8x8_t __a, uint8x8_t __b) +{ + return __a - __b; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsub_u16 (uint16x4_t __a, uint16x4_t __b) +{ + return __a - __b; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsub_u32 (uint32x2_t __a, uint32x2_t __b) +{ + return __a - __b; +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsub_s64 (int64x1_t __a, int64x1_t __b) +{ + return __a - __b; +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsub_u64 (uint64x1_t __a, uint64x1_t __b) +{ + return __a - __b; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubq_s8 (int8x16_t __a, int8x16_t __b) +{ + return __a - __b; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubq_s16 (int16x8_t __a, int16x8_t __b) +{ + return __a - __b; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubq_s32 (int32x4_t __a, int32x4_t __b) +{ + return __a - __b; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubq_s64 (int64x2_t __a, int64x2_t __b) +{ + return __a - __b; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubq_f32 (float32x4_t __a, float32x4_t __b) +{ + return __a - __b; +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubq_f64 (float64x2_t __a, float64x2_t __b) +{ + return __a - __b; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubq_u8 (uint8x16_t __a, uint8x16_t __b) +{ + return __a - __b; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubq_u16 (uint16x8_t __a, uint16x8_t __b) +{ + return __a - __b; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubq_u32 (uint32x4_t __a, uint32x4_t __b) +{ + return __a - __b; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubq_u64 (uint64x2_t __a, uint64x2_t __b) +{ + return __a - __b; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubl_s8 (int8x8_t __a, int8x8_t __b) +{ + return (int16x8_t) __builtin_aarch64_ssublv8qi (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubl_s16 (int16x4_t __a, int16x4_t __b) +{ + return (int32x4_t) __builtin_aarch64_ssublv4hi (__a, __b); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubl_s32 (int32x2_t __a, int32x2_t __b) +{ + return (int64x2_t) __builtin_aarch64_ssublv2si (__a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubl_u8 (uint8x8_t __a, uint8x8_t __b) +{ + return (uint16x8_t) __builtin_aarch64_usublv8qi ((int8x8_t) __a, + (int8x8_t) __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubl_u16 (uint16x4_t __a, uint16x4_t __b) +{ + return (uint32x4_t) __builtin_aarch64_usublv4hi ((int16x4_t) __a, + (int16x4_t) __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubl_u32 (uint32x2_t __a, uint32x2_t __b) +{ + return (uint64x2_t) __builtin_aarch64_usublv2si ((int32x2_t) __a, + (int32x2_t) __b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubl_high_s8 (int8x16_t __a, int8x16_t __b) +{ + return (int16x8_t) __builtin_aarch64_ssubl2v16qi (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubl_high_s16 (int16x8_t __a, int16x8_t __b) +{ + return (int32x4_t) __builtin_aarch64_ssubl2v8hi (__a, __b); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubl_high_s32 (int32x4_t __a, int32x4_t __b) +{ + return (int64x2_t) __builtin_aarch64_ssubl2v4si (__a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubl_high_u8 (uint8x16_t __a, uint8x16_t __b) +{ + return (uint16x8_t) __builtin_aarch64_usubl2v16qi ((int8x16_t) __a, + (int8x16_t) __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubl_high_u16 (uint16x8_t __a, uint16x8_t __b) +{ + return (uint32x4_t) __builtin_aarch64_usubl2v8hi ((int16x8_t) __a, + (int16x8_t) __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubl_high_u32 (uint32x4_t __a, uint32x4_t __b) +{ + return (uint64x2_t) __builtin_aarch64_usubl2v4si ((int32x4_t) __a, + (int32x4_t) __b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubw_s8 (int16x8_t __a, int8x8_t __b) +{ + return (int16x8_t) __builtin_aarch64_ssubwv8qi (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubw_s16 (int32x4_t __a, int16x4_t __b) +{ + return (int32x4_t) __builtin_aarch64_ssubwv4hi (__a, __b); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubw_s32 (int64x2_t __a, int32x2_t __b) +{ + return (int64x2_t) __builtin_aarch64_ssubwv2si (__a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubw_u8 (uint16x8_t __a, uint8x8_t __b) +{ + return (uint16x8_t) __builtin_aarch64_usubwv8qi ((int16x8_t) __a, + (int8x8_t) __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubw_u16 (uint32x4_t __a, uint16x4_t __b) +{ + return (uint32x4_t) __builtin_aarch64_usubwv4hi ((int32x4_t) __a, + (int16x4_t) __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubw_u32 (uint64x2_t __a, uint32x2_t __b) +{ + return (uint64x2_t) __builtin_aarch64_usubwv2si ((int64x2_t) __a, + (int32x2_t) __b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubw_high_s8 (int16x8_t __a, int8x16_t __b) +{ + return (int16x8_t) __builtin_aarch64_ssubw2v16qi (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubw_high_s16 (int32x4_t __a, int16x8_t __b) +{ + return (int32x4_t) __builtin_aarch64_ssubw2v8hi (__a, __b); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubw_high_s32 (int64x2_t __a, int32x4_t __b) +{ + return (int64x2_t) __builtin_aarch64_ssubw2v4si (__a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubw_high_u8 (uint16x8_t __a, uint8x16_t __b) +{ + return (uint16x8_t) __builtin_aarch64_usubw2v16qi ((int16x8_t) __a, + (int8x16_t) __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubw_high_u16 (uint32x4_t __a, uint16x8_t __b) +{ + return (uint32x4_t) __builtin_aarch64_usubw2v8hi ((int32x4_t) __a, + (int16x8_t) __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubw_high_u32 (uint64x2_t __a, uint32x4_t __b) +{ + return (uint64x2_t) __builtin_aarch64_usubw2v4si ((int64x2_t) __a, + (int32x4_t) __b); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqadd_s8 (int8x8_t __a, int8x8_t __b) +{ + return (int8x8_t) __builtin_aarch64_sqaddv8qi (__a, __b); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqadd_s16 (int16x4_t __a, int16x4_t __b) +{ + return (int16x4_t) __builtin_aarch64_sqaddv4hi (__a, __b); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqadd_s32 (int32x2_t __a, int32x2_t __b) +{ + return (int32x2_t) __builtin_aarch64_sqaddv2si (__a, __b); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqadd_s64 (int64x1_t __a, int64x1_t __b) +{ + return (int64x1_t) {__builtin_aarch64_sqadddi (__a[0], __b[0])}; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqadd_u8 (uint8x8_t __a, uint8x8_t __b) +{ + return __builtin_aarch64_uqaddv8qi_uuu (__a, __b); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vhsub_s8 (int8x8_t __a, int8x8_t __b) +{ + return (int8x8_t)__builtin_aarch64_shsubv8qi (__a, __b); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vhsub_s16 (int16x4_t __a, int16x4_t __b) +{ + return (int16x4_t) __builtin_aarch64_shsubv4hi (__a, __b); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vhsub_s32 (int32x2_t __a, int32x2_t __b) +{ + return (int32x2_t) __builtin_aarch64_shsubv2si (__a, __b); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vhsub_u8 (uint8x8_t __a, uint8x8_t __b) +{ + return (uint8x8_t) __builtin_aarch64_uhsubv8qi ((int8x8_t) __a, + (int8x8_t) __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vhsub_u16 (uint16x4_t __a, uint16x4_t __b) +{ + return (uint16x4_t) __builtin_aarch64_uhsubv4hi ((int16x4_t) __a, + (int16x4_t) __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vhsub_u32 (uint32x2_t __a, uint32x2_t __b) +{ + return (uint32x2_t) __builtin_aarch64_uhsubv2si ((int32x2_t) __a, + (int32x2_t) __b); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vhsubq_s8 (int8x16_t __a, int8x16_t __b) +{ + return (int8x16_t) __builtin_aarch64_shsubv16qi (__a, __b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vhsubq_s16 (int16x8_t __a, int16x8_t __b) +{ + return (int16x8_t) __builtin_aarch64_shsubv8hi (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vhsubq_s32 (int32x4_t __a, int32x4_t __b) +{ + return (int32x4_t) __builtin_aarch64_shsubv4si (__a, __b); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vhsubq_u8 (uint8x16_t __a, uint8x16_t __b) +{ + return (uint8x16_t) __builtin_aarch64_uhsubv16qi ((int8x16_t) __a, + (int8x16_t) __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vhsubq_u16 (uint16x8_t __a, uint16x8_t __b) +{ + return (uint16x8_t) __builtin_aarch64_uhsubv8hi ((int16x8_t) __a, + (int16x8_t) __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vhsubq_u32 (uint32x4_t __a, uint32x4_t __b) +{ + return (uint32x4_t) __builtin_aarch64_uhsubv4si ((int32x4_t) __a, + (int32x4_t) __b); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubhn_s16 (int16x8_t __a, int16x8_t __b) +{ + return (int8x8_t) __builtin_aarch64_subhnv8hi (__a, __b); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubhn_s32 (int32x4_t __a, int32x4_t __b) +{ + return (int16x4_t) __builtin_aarch64_subhnv4si (__a, __b); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubhn_s64 (int64x2_t __a, int64x2_t __b) +{ + return (int32x2_t) __builtin_aarch64_subhnv2di (__a, __b); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubhn_u16 (uint16x8_t __a, uint16x8_t __b) +{ + return (uint8x8_t) __builtin_aarch64_subhnv8hi ((int16x8_t) __a, + (int16x8_t) __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubhn_u32 (uint32x4_t __a, uint32x4_t __b) +{ + return (uint16x4_t) __builtin_aarch64_subhnv4si ((int32x4_t) __a, + (int32x4_t) __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubhn_u64 (uint64x2_t __a, uint64x2_t __b) +{ + return (uint32x2_t) __builtin_aarch64_subhnv2di ((int64x2_t) __a, + (int64x2_t) __b); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsubhn_s16 (int16x8_t __a, int16x8_t __b) +{ + return (int8x8_t) __builtin_aarch64_rsubhnv8hi (__a, __b); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsubhn_s32 (int32x4_t __a, int32x4_t __b) +{ + return (int16x4_t) __builtin_aarch64_rsubhnv4si (__a, __b); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsubhn_s64 (int64x2_t __a, int64x2_t __b) +{ + return (int32x2_t) __builtin_aarch64_rsubhnv2di (__a, __b); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsubhn_u16 (uint16x8_t __a, uint16x8_t __b) +{ + return (uint8x8_t) __builtin_aarch64_rsubhnv8hi ((int16x8_t) __a, + (int16x8_t) __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsubhn_u32 (uint32x4_t __a, uint32x4_t __b) +{ + return (uint16x4_t) __builtin_aarch64_rsubhnv4si ((int32x4_t) __a, + (int32x4_t) __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsubhn_u64 (uint64x2_t __a, uint64x2_t __b) +{ + return (uint32x2_t) __builtin_aarch64_rsubhnv2di ((int64x2_t) __a, + (int64x2_t) __b); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsubhn_high_s16 (int8x8_t __a, int16x8_t __b, int16x8_t __c) +{ + return (int8x16_t) __builtin_aarch64_rsubhn2v8hi (__a, __b, __c); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsubhn_high_s32 (int16x4_t __a, int32x4_t __b, int32x4_t __c) +{ + return (int16x8_t) __builtin_aarch64_rsubhn2v4si (__a, __b, __c); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsubhn_high_s64 (int32x2_t __a, int64x2_t __b, int64x2_t __c) +{ + return (int32x4_t) __builtin_aarch64_rsubhn2v2di (__a, __b, __c); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsubhn_high_u16 (uint8x8_t __a, uint16x8_t __b, uint16x8_t __c) +{ + return (uint8x16_t) __builtin_aarch64_rsubhn2v8hi ((int8x8_t) __a, + (int16x8_t) __b, + (int16x8_t) __c); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsubhn_high_u32 (uint16x4_t __a, uint32x4_t __b, uint32x4_t __c) +{ + return (uint16x8_t) __builtin_aarch64_rsubhn2v4si ((int16x4_t) __a, + (int32x4_t) __b, + (int32x4_t) __c); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsubhn_high_u64 (uint32x2_t __a, uint64x2_t __b, uint64x2_t __c) +{ + return (uint32x4_t) __builtin_aarch64_rsubhn2v2di ((int32x2_t) __a, + (int64x2_t) __b, + (int64x2_t) __c); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubhn_high_s16 (int8x8_t __a, int16x8_t __b, int16x8_t __c) +{ + return (int8x16_t) __builtin_aarch64_subhn2v8hi (__a, __b, __c); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubhn_high_s32 (int16x4_t __a, int32x4_t __b, int32x4_t __c) +{ + return (int16x8_t) __builtin_aarch64_subhn2v4si (__a, __b, __c);; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubhn_high_s64 (int32x2_t __a, int64x2_t __b, int64x2_t __c) +{ + return (int32x4_t) __builtin_aarch64_subhn2v2di (__a, __b, __c); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubhn_high_u16 (uint8x8_t __a, uint16x8_t __b, uint16x8_t __c) +{ + return (uint8x16_t) __builtin_aarch64_subhn2v8hi ((int8x8_t) __a, + (int16x8_t) __b, + (int16x8_t) __c); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubhn_high_u32 (uint16x4_t __a, uint32x4_t __b, uint32x4_t __c) +{ + return (uint16x8_t) __builtin_aarch64_subhn2v4si ((int16x4_t) __a, + (int32x4_t) __b, + (int32x4_t) __c); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubhn_high_u64 (uint32x2_t __a, uint64x2_t __b, uint64x2_t __c) +{ + return (uint32x4_t) __builtin_aarch64_subhn2v2di ((int32x2_t) __a, + (int64x2_t) __b, + (int64x2_t) __c); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqadd_u16 (uint16x4_t __a, uint16x4_t __b) +{ + return __builtin_aarch64_uqaddv4hi_uuu (__a, __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqadd_u32 (uint32x2_t __a, uint32x2_t __b) +{ + return __builtin_aarch64_uqaddv2si_uuu (__a, __b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqadd_u64 (uint64x1_t __a, uint64x1_t __b) +{ + return (uint64x1_t) {__builtin_aarch64_uqadddi_uuu (__a[0], __b[0])}; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqaddq_s8 (int8x16_t __a, int8x16_t __b) +{ + return (int8x16_t) __builtin_aarch64_sqaddv16qi (__a, __b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqaddq_s16 (int16x8_t __a, int16x8_t __b) +{ + return (int16x8_t) __builtin_aarch64_sqaddv8hi (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqaddq_s32 (int32x4_t __a, int32x4_t __b) +{ + return (int32x4_t) __builtin_aarch64_sqaddv4si (__a, __b); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqaddq_s64 (int64x2_t __a, int64x2_t __b) +{ + return (int64x2_t) __builtin_aarch64_sqaddv2di (__a, __b); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqaddq_u8 (uint8x16_t __a, uint8x16_t __b) +{ + return __builtin_aarch64_uqaddv16qi_uuu (__a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqaddq_u16 (uint16x8_t __a, uint16x8_t __b) +{ + return __builtin_aarch64_uqaddv8hi_uuu (__a, __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqaddq_u32 (uint32x4_t __a, uint32x4_t __b) +{ + return __builtin_aarch64_uqaddv4si_uuu (__a, __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqaddq_u64 (uint64x2_t __a, uint64x2_t __b) +{ + return __builtin_aarch64_uqaddv2di_uuu (__a, __b); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqsub_s8 (int8x8_t __a, int8x8_t __b) +{ + return (int8x8_t) __builtin_aarch64_sqsubv8qi (__a, __b); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqsub_s16 (int16x4_t __a, int16x4_t __b) +{ + return (int16x4_t) __builtin_aarch64_sqsubv4hi (__a, __b); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqsub_s32 (int32x2_t __a, int32x2_t __b) +{ + return (int32x2_t) __builtin_aarch64_sqsubv2si (__a, __b); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqsub_s64 (int64x1_t __a, int64x1_t __b) +{ + return (int64x1_t) {__builtin_aarch64_sqsubdi (__a[0], __b[0])}; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqsub_u8 (uint8x8_t __a, uint8x8_t __b) +{ + return __builtin_aarch64_uqsubv8qi_uuu (__a, __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqsub_u16 (uint16x4_t __a, uint16x4_t __b) +{ + return __builtin_aarch64_uqsubv4hi_uuu (__a, __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqsub_u32 (uint32x2_t __a, uint32x2_t __b) +{ + return __builtin_aarch64_uqsubv2si_uuu (__a, __b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqsub_u64 (uint64x1_t __a, uint64x1_t __b) +{ + return (uint64x1_t) {__builtin_aarch64_uqsubdi_uuu (__a[0], __b[0])}; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqsubq_s8 (int8x16_t __a, int8x16_t __b) +{ + return (int8x16_t) __builtin_aarch64_sqsubv16qi (__a, __b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqsubq_s16 (int16x8_t __a, int16x8_t __b) +{ + return (int16x8_t) __builtin_aarch64_sqsubv8hi (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqsubq_s32 (int32x4_t __a, int32x4_t __b) +{ + return (int32x4_t) __builtin_aarch64_sqsubv4si (__a, __b); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqsubq_s64 (int64x2_t __a, int64x2_t __b) +{ + return (int64x2_t) __builtin_aarch64_sqsubv2di (__a, __b); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqsubq_u8 (uint8x16_t __a, uint8x16_t __b) +{ + return __builtin_aarch64_uqsubv16qi_uuu (__a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqsubq_u16 (uint16x8_t __a, uint16x8_t __b) +{ + return __builtin_aarch64_uqsubv8hi_uuu (__a, __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqsubq_u32 (uint32x4_t __a, uint32x4_t __b) +{ + return __builtin_aarch64_uqsubv4si_uuu (__a, __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqsubq_u64 (uint64x2_t __a, uint64x2_t __b) +{ + return __builtin_aarch64_uqsubv2di_uuu (__a, __b); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqneg_s8 (int8x8_t __a) +{ + return (int8x8_t) __builtin_aarch64_sqnegv8qi (__a); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqneg_s16 (int16x4_t __a) +{ + return (int16x4_t) __builtin_aarch64_sqnegv4hi (__a); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqneg_s32 (int32x2_t __a) +{ + return (int32x2_t) __builtin_aarch64_sqnegv2si (__a); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqneg_s64 (int64x1_t __a) +{ + return (int64x1_t) {__builtin_aarch64_sqnegdi (__a[0])}; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqnegq_s8 (int8x16_t __a) +{ + return (int8x16_t) __builtin_aarch64_sqnegv16qi (__a); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqnegq_s16 (int16x8_t __a) +{ + return (int16x8_t) __builtin_aarch64_sqnegv8hi (__a); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqnegq_s32 (int32x4_t __a) +{ + return (int32x4_t) __builtin_aarch64_sqnegv4si (__a); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqabs_s8 (int8x8_t __a) +{ + return (int8x8_t) __builtin_aarch64_sqabsv8qi (__a); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqabs_s16 (int16x4_t __a) +{ + return (int16x4_t) __builtin_aarch64_sqabsv4hi (__a); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqabs_s32 (int32x2_t __a) +{ + return (int32x2_t) __builtin_aarch64_sqabsv2si (__a); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqabs_s64 (int64x1_t __a) +{ + return (int64x1_t) {__builtin_aarch64_sqabsdi (__a[0])}; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqabsq_s8 (int8x16_t __a) +{ + return (int8x16_t) __builtin_aarch64_sqabsv16qi (__a); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqabsq_s16 (int16x8_t __a) +{ + return (int16x8_t) __builtin_aarch64_sqabsv8hi (__a); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqabsq_s32 (int32x4_t __a) +{ + return (int32x4_t) __builtin_aarch64_sqabsv4si (__a); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmulh_s16 (int16x4_t __a, int16x4_t __b) +{ + return (int16x4_t) __builtin_aarch64_sqdmulhv4hi (__a, __b); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmulh_s32 (int32x2_t __a, int32x2_t __b) +{ + return (int32x2_t) __builtin_aarch64_sqdmulhv2si (__a, __b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmulhq_s16 (int16x8_t __a, int16x8_t __b) +{ + return (int16x8_t) __builtin_aarch64_sqdmulhv8hi (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmulhq_s32 (int32x4_t __a, int32x4_t __b) +{ + return (int32x4_t) __builtin_aarch64_sqdmulhv4si (__a, __b); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmulh_s16 (int16x4_t __a, int16x4_t __b) +{ + return (int16x4_t) __builtin_aarch64_sqrdmulhv4hi (__a, __b); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmulh_s32 (int32x2_t __a, int32x2_t __b) +{ + return (int32x2_t) __builtin_aarch64_sqrdmulhv2si (__a, __b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmulhq_s16 (int16x8_t __a, int16x8_t __b) +{ + return (int16x8_t) __builtin_aarch64_sqrdmulhv8hi (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmulhq_s32 (int32x4_t __a, int32x4_t __b) +{ + return (int32x4_t) __builtin_aarch64_sqrdmulhv4si (__a, __b); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcreate_s8 (uint64_t __a) +{ + return (int8x8_t) __a; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcreate_s16 (uint64_t __a) +{ + return (int16x4_t) __a; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcreate_s32 (uint64_t __a) +{ + return (int32x2_t) __a; +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcreate_s64 (uint64_t __a) +{ + return (int64x1_t) {__a}; +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcreate_f16 (uint64_t __a) +{ + return (float16x4_t) __a; +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcreate_f32 (uint64_t __a) +{ + return (float32x2_t) __a; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcreate_u8 (uint64_t __a) +{ + return (uint8x8_t) __a; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcreate_u16 (uint64_t __a) +{ + return (uint16x4_t) __a; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcreate_u32 (uint64_t __a) +{ + return (uint32x2_t) __a; +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcreate_u64 (uint64_t __a) +{ + return (uint64x1_t) {__a}; +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcreate_f64 (uint64_t __a) +{ + return (float64x1_t) __a; +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcreate_p8 (uint64_t __a) +{ + return (poly8x8_t) __a; +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcreate_p16 (uint64_t __a) +{ + return (poly16x4_t) __a; +} + +__extension__ extern __inline poly64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcreate_p64 (uint64_t __a) +{ + return (poly64x1_t) __a; +} + +/* vget_lane */ + +__extension__ extern __inline float16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_lane_f16 (float16x4_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_lane_f32 (float32x2_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_lane_f64 (float64x1_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline poly8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_lane_p8 (poly8x8_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline poly16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_lane_p16 (poly16x4_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline poly64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_lane_p64 (poly64x1_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline int8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_lane_s8 (int8x8_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_lane_s16 (int16x4_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_lane_s32 (int32x2_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_lane_s64 (int64x1_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline uint8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_lane_u8 (uint8x8_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline uint16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_lane_u16 (uint16x4_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_lane_u32 (uint32x2_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_lane_u64 (uint64x1_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +/* vgetq_lane */ + +__extension__ extern __inline float16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vgetq_lane_f16 (float16x8_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vgetq_lane_f32 (float32x4_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vgetq_lane_f64 (float64x2_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline poly8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vgetq_lane_p8 (poly8x16_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline poly16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vgetq_lane_p16 (poly16x8_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline poly64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vgetq_lane_p64 (poly64x2_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline int8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vgetq_lane_s8 (int8x16_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vgetq_lane_s16 (int16x8_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vgetq_lane_s32 (int32x4_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vgetq_lane_s64 (int64x2_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline uint8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vgetq_lane_u8 (uint8x16_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline uint16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vgetq_lane_u16 (uint16x8_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vgetq_lane_u32 (uint32x4_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vgetq_lane_u64 (uint64x2_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +/* vreinterpret */ + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p8_f16 (float16x4_t __a) +{ + return (poly8x8_t) __a; +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p8_f64 (float64x1_t __a) +{ + return (poly8x8_t) __a; +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p8_s8 (int8x8_t __a) +{ + return (poly8x8_t) __a; +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p8_s16 (int16x4_t __a) +{ + return (poly8x8_t) __a; +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p8_s32 (int32x2_t __a) +{ + return (poly8x8_t) __a; +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p8_s64 (int64x1_t __a) +{ + return (poly8x8_t) __a; +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p8_f32 (float32x2_t __a) +{ + return (poly8x8_t) __a; +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p8_u8 (uint8x8_t __a) +{ + return (poly8x8_t) __a; +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p8_u16 (uint16x4_t __a) +{ + return (poly8x8_t) __a; +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p8_u32 (uint32x2_t __a) +{ + return (poly8x8_t) __a; +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p8_u64 (uint64x1_t __a) +{ + return (poly8x8_t) __a; +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p8_p16 (poly16x4_t __a) +{ + return (poly8x8_t) __a; +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p8_p64 (poly64x1_t __a) +{ + return (poly8x8_t) __a; +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p8_f64 (float64x2_t __a) +{ + return (poly8x16_t) __a; +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p8_s8 (int8x16_t __a) +{ + return (poly8x16_t) __a; +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p8_s16 (int16x8_t __a) +{ + return (poly8x16_t) __a; +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p8_s32 (int32x4_t __a) +{ + return (poly8x16_t) __a; +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p8_s64 (int64x2_t __a) +{ + return (poly8x16_t) __a; +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p8_f16 (float16x8_t __a) +{ + return (poly8x16_t) __a; +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p8_f32 (float32x4_t __a) +{ + return (poly8x16_t) __a; +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p8_u8 (uint8x16_t __a) +{ + return (poly8x16_t) __a; +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p8_u16 (uint16x8_t __a) +{ + return (poly8x16_t) __a; +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p8_u32 (uint32x4_t __a) +{ + return (poly8x16_t) __a; +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p8_u64 (uint64x2_t __a) +{ + return (poly8x16_t) __a; +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p8_p16 (poly16x8_t __a) +{ + return (poly8x16_t) __a; +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p8_p64 (poly64x2_t __a) +{ + return (poly8x16_t) __a; +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p8_p128 (poly128_t __a) +{ + return (poly8x16_t)__a; +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p16_f16 (float16x4_t __a) +{ + return (poly16x4_t) __a; +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p16_f64 (float64x1_t __a) +{ + return (poly16x4_t) __a; +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p16_s8 (int8x8_t __a) +{ + return (poly16x4_t) __a; +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p16_s16 (int16x4_t __a) +{ + return (poly16x4_t) __a; +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p16_s32 (int32x2_t __a) +{ + return (poly16x4_t) __a; +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p16_s64 (int64x1_t __a) +{ + return (poly16x4_t) __a; +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p16_f32 (float32x2_t __a) +{ + return (poly16x4_t) __a; +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p16_u8 (uint8x8_t __a) +{ + return (poly16x4_t) __a; +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p16_u16 (uint16x4_t __a) +{ + return (poly16x4_t) __a; +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p16_u32 (uint32x2_t __a) +{ + return (poly16x4_t) __a; +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p16_u64 (uint64x1_t __a) +{ + return (poly16x4_t) __a; +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p16_p8 (poly8x8_t __a) +{ + return (poly16x4_t) __a; +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p16_p64 (poly64x1_t __a) +{ + return (poly16x4_t) __a; +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p16_f64 (float64x2_t __a) +{ + return (poly16x8_t) __a; +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p16_s8 (int8x16_t __a) +{ + return (poly16x8_t) __a; +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p16_s16 (int16x8_t __a) +{ + return (poly16x8_t) __a; +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p16_s32 (int32x4_t __a) +{ + return (poly16x8_t) __a; +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p16_s64 (int64x2_t __a) +{ + return (poly16x8_t) __a; +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p16_f16 (float16x8_t __a) +{ + return (poly16x8_t) __a; +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p16_f32 (float32x4_t __a) +{ + return (poly16x8_t) __a; +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p16_u8 (uint8x16_t __a) +{ + return (poly16x8_t) __a; +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p16_u16 (uint16x8_t __a) +{ + return (poly16x8_t) __a; +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p16_u32 (uint32x4_t __a) +{ + return (poly16x8_t) __a; +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p16_u64 (uint64x2_t __a) +{ + return (poly16x8_t) __a; +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p16_p8 (poly8x16_t __a) +{ + return (poly16x8_t) __a; +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p16_p64 (poly64x2_t __a) +{ + return (poly16x8_t) __a; +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p16_p128 (poly128_t __a) +{ + return (poly16x8_t)__a; +} + +__extension__ extern __inline poly64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p64_f16 (float16x4_t __a) +{ + return (poly64x1_t) __a; +} + +__extension__ extern __inline poly64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p64_f64 (float64x1_t __a) +{ + return (poly64x1_t) __a; +} + +__extension__ extern __inline poly64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p64_s8 (int8x8_t __a) +{ + return (poly64x1_t) __a; +} + +__extension__ extern __inline poly64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p64_s16 (int16x4_t __a) +{ + return (poly64x1_t) __a; +} + +__extension__ extern __inline poly64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p64_s32 (int32x2_t __a) +{ + return (poly64x1_t) __a; +} + +__extension__ extern __inline poly64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p64_s64 (int64x1_t __a) +{ + return (poly64x1_t) __a; +} + +__extension__ extern __inline poly64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p64_f32 (float32x2_t __a) +{ + return (poly64x1_t) __a; +} + +__extension__ extern __inline poly64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p64_u8 (uint8x8_t __a) +{ + return (poly64x1_t) __a; +} + +__extension__ extern __inline poly64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p64_u16 (uint16x4_t __a) +{ + return (poly64x1_t) __a; +} + +__extension__ extern __inline poly64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p64_u32 (uint32x2_t __a) +{ + return (poly64x1_t) __a; +} + +__extension__ extern __inline poly64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p64_u64 (uint64x1_t __a) +{ + return (poly64x1_t) __a; +} + +__extension__ extern __inline poly64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p64_p8 (poly8x8_t __a) +{ + return (poly64x1_t) __a; +} + +__extension__ extern __inline poly64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_p64_p16 (poly16x4_t __a) +{ + return (poly64x1_t)__a; +} + +__extension__ extern __inline poly64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p64_f64 (float64x2_t __a) +{ + return (poly64x2_t) __a; +} + +__extension__ extern __inline poly64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p64_s8 (int8x16_t __a) +{ + return (poly64x2_t) __a; +} + +__extension__ extern __inline poly64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p64_s16 (int16x8_t __a) +{ + return (poly64x2_t) __a; +} + +__extension__ extern __inline poly64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p64_s32 (int32x4_t __a) +{ + return (poly64x2_t) __a; +} + +__extension__ extern __inline poly64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p64_s64 (int64x2_t __a) +{ + return (poly64x2_t) __a; +} + +__extension__ extern __inline poly64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p64_f16 (float16x8_t __a) +{ + return (poly64x2_t) __a; +} + +__extension__ extern __inline poly64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p64_f32 (float32x4_t __a) +{ + return (poly64x2_t) __a; +} + +__extension__ extern __inline poly64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p64_p128 (poly128_t __a) +{ + return (poly64x2_t)__a; +} + +__extension__ extern __inline poly64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p64_u8 (uint8x16_t __a) +{ + return (poly64x2_t) __a; +} + +__extension__ extern __inline poly64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p64_u16 (uint16x8_t __a) +{ + return (poly64x2_t) __a; +} + +__extension__ extern __inline poly64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p64_p16 (poly16x8_t __a) +{ + return (poly64x2_t)__a; +} + +__extension__ extern __inline poly64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p64_u32 (uint32x4_t __a) +{ + return (poly64x2_t) __a; +} + +__extension__ extern __inline poly64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p64_u64 (uint64x2_t __a) +{ + return (poly64x2_t) __a; +} + +__extension__ extern __inline poly64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p64_p8 (poly8x16_t __a) +{ + return (poly64x2_t) __a; +} + +__extension__ extern __inline poly128_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p128_p8 (poly8x16_t __a) +{ + return (poly128_t)__a; +} + +__extension__ extern __inline poly128_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p128_p16 (poly16x8_t __a) +{ + return (poly128_t)__a; +} + +__extension__ extern __inline poly128_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p128_f16 (float16x8_t __a) +{ + return (poly128_t) __a; +} + +__extension__ extern __inline poly128_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p128_f32 (float32x4_t __a) +{ + return (poly128_t)__a; +} + +__extension__ extern __inline poly128_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p128_p64 (poly64x2_t __a) +{ + return (poly128_t)__a; +} + +__extension__ extern __inline poly128_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p128_s64 (int64x2_t __a) +{ + return (poly128_t)__a; +} + +__extension__ extern __inline poly128_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p128_u64 (uint64x2_t __a) +{ + return (poly128_t)__a; +} + +__extension__ extern __inline poly128_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p128_s8 (int8x16_t __a) +{ + return (poly128_t)__a; +} + +__extension__ extern __inline poly128_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p128_s16 (int16x8_t __a) +{ + return (poly128_t)__a; +} + +__extension__ extern __inline poly128_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p128_s32 (int32x4_t __a) +{ + return (poly128_t)__a; +} + +__extension__ extern __inline poly128_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p128_u8 (uint8x16_t __a) +{ + return (poly128_t)__a; +} + +__extension__ extern __inline poly128_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p128_u16 (uint16x8_t __a) +{ + return (poly128_t)__a; +} + +__extension__ extern __inline poly128_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_p128_u32 (uint32x4_t __a) +{ + return (poly128_t)__a; +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f16_f64 (float64x1_t __a) +{ + return (float16x4_t) __a; +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f16_s8 (int8x8_t __a) +{ + return (float16x4_t) __a; +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f16_s16 (int16x4_t __a) +{ + return (float16x4_t) __a; +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f16_s32 (int32x2_t __a) +{ + return (float16x4_t) __a; +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f16_s64 (int64x1_t __a) +{ + return (float16x4_t) __a; +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f16_f32 (float32x2_t __a) +{ + return (float16x4_t) __a; +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f16_u8 (uint8x8_t __a) +{ + return (float16x4_t) __a; +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f16_u16 (uint16x4_t __a) +{ + return (float16x4_t) __a; +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f16_u32 (uint32x2_t __a) +{ + return (float16x4_t) __a; +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f16_u64 (uint64x1_t __a) +{ + return (float16x4_t) __a; +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f16_p8 (poly8x8_t __a) +{ + return (float16x4_t) __a; +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f16_p16 (poly16x4_t __a) +{ + return (float16x4_t) __a; +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f16_p64 (poly64x1_t __a) +{ + return (float16x4_t) __a; +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f16_f64 (float64x2_t __a) +{ + return (float16x8_t) __a; +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f16_s8 (int8x16_t __a) +{ + return (float16x8_t) __a; +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f16_s16 (int16x8_t __a) +{ + return (float16x8_t) __a; +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f16_s32 (int32x4_t __a) +{ + return (float16x8_t) __a; +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f16_s64 (int64x2_t __a) +{ + return (float16x8_t) __a; +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f16_f32 (float32x4_t __a) +{ + return (float16x8_t) __a; +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f16_u8 (uint8x16_t __a) +{ + return (float16x8_t) __a; +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f16_u16 (uint16x8_t __a) +{ + return (float16x8_t) __a; +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f16_u32 (uint32x4_t __a) +{ + return (float16x8_t) __a; +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f16_u64 (uint64x2_t __a) +{ + return (float16x8_t) __a; +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f16_p8 (poly8x16_t __a) +{ + return (float16x8_t) __a; +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f16_p128 (poly128_t __a) +{ + return (float16x8_t) __a; +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f16_p16 (poly16x8_t __a) +{ + return (float16x8_t) __a; +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f16_p64 (poly64x2_t __a) +{ + return (float16x8_t) __a; +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f32_f16 (float16x4_t __a) +{ + return (float32x2_t) __a; +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f32_f64 (float64x1_t __a) +{ + return (float32x2_t) __a; +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f32_s8 (int8x8_t __a) +{ + return (float32x2_t) __a; +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f32_s16 (int16x4_t __a) +{ + return (float32x2_t) __a; +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f32_s32 (int32x2_t __a) +{ + return (float32x2_t) __a; +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f32_s64 (int64x1_t __a) +{ + return (float32x2_t) __a; +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f32_u8 (uint8x8_t __a) +{ + return (float32x2_t) __a; +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f32_u16 (uint16x4_t __a) +{ + return (float32x2_t) __a; +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f32_u32 (uint32x2_t __a) +{ + return (float32x2_t) __a; +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f32_u64 (uint64x1_t __a) +{ + return (float32x2_t) __a; +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f32_p8 (poly8x8_t __a) +{ + return (float32x2_t) __a; +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f32_p16 (poly16x4_t __a) +{ + return (float32x2_t) __a; +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f32_p64 (poly64x1_t __a) +{ + return (float32x2_t) __a; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f32_f16 (float16x8_t __a) +{ + return (float32x4_t) __a; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f32_f64 (float64x2_t __a) +{ + return (float32x4_t) __a; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f32_s8 (int8x16_t __a) +{ + return (float32x4_t) __a; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f32_s16 (int16x8_t __a) +{ + return (float32x4_t) __a; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f32_s32 (int32x4_t __a) +{ + return (float32x4_t) __a; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f32_s64 (int64x2_t __a) +{ + return (float32x4_t) __a; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f32_u8 (uint8x16_t __a) +{ + return (float32x4_t) __a; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f32_u16 (uint16x8_t __a) +{ + return (float32x4_t) __a; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f32_u32 (uint32x4_t __a) +{ + return (float32x4_t) __a; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f32_u64 (uint64x2_t __a) +{ + return (float32x4_t) __a; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f32_p8 (poly8x16_t __a) +{ + return (float32x4_t) __a; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f32_p16 (poly16x8_t __a) +{ + return (float32x4_t) __a; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f32_p64 (poly64x2_t __a) +{ + return (float32x4_t) __a; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f32_p128 (poly128_t __a) +{ + return (float32x4_t)__a; +} + + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f64_f16 (float16x4_t __a) +{ + return (float64x1_t) __a; +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f64_f32 (float32x2_t __a) +{ + return (float64x1_t) __a; +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f64_p8 (poly8x8_t __a) +{ + return (float64x1_t) __a; +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f64_p16 (poly16x4_t __a) +{ + return (float64x1_t) __a; +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f64_p64 (poly64x1_t __a) +{ + return (float64x1_t) __a; +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f64_s8 (int8x8_t __a) +{ + return (float64x1_t) __a; +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f64_s16 (int16x4_t __a) +{ + return (float64x1_t) __a; +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f64_s32 (int32x2_t __a) +{ + return (float64x1_t) __a; +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f64_s64 (int64x1_t __a) +{ + return (float64x1_t) __a; +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f64_u8 (uint8x8_t __a) +{ + return (float64x1_t) __a; +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f64_u16 (uint16x4_t __a) +{ + return (float64x1_t) __a; +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f64_u32 (uint32x2_t __a) +{ + return (float64x1_t) __a; +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_f64_u64 (uint64x1_t __a) +{ + return (float64x1_t) __a; +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f64_f16 (float16x8_t __a) +{ + return (float64x2_t) __a; +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f64_f32 (float32x4_t __a) +{ + return (float64x2_t) __a; +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f64_p8 (poly8x16_t __a) +{ + return (float64x2_t) __a; +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f64_p16 (poly16x8_t __a) +{ + return (float64x2_t) __a; +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f64_p64 (poly64x2_t __a) +{ + return (float64x2_t) __a; +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f64_s8 (int8x16_t __a) +{ + return (float64x2_t) __a; +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f64_s16 (int16x8_t __a) +{ + return (float64x2_t) __a; +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f64_s32 (int32x4_t __a) +{ + return (float64x2_t) __a; +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f64_s64 (int64x2_t __a) +{ + return (float64x2_t) __a; +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f64_u8 (uint8x16_t __a) +{ + return (float64x2_t) __a; +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f64_u16 (uint16x8_t __a) +{ + return (float64x2_t) __a; +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f64_u32 (uint32x4_t __a) +{ + return (float64x2_t) __a; +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_f64_u64 (uint64x2_t __a) +{ + return (float64x2_t) __a; +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s64_f16 (float16x4_t __a) +{ + return (int64x1_t) __a; +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s64_f64 (float64x1_t __a) +{ + return (int64x1_t) __a; +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s64_s8 (int8x8_t __a) +{ + return (int64x1_t) __a; +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s64_s16 (int16x4_t __a) +{ + return (int64x1_t) __a; +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s64_s32 (int32x2_t __a) +{ + return (int64x1_t) __a; +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s64_f32 (float32x2_t __a) +{ + return (int64x1_t) __a; +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s64_u8 (uint8x8_t __a) +{ + return (int64x1_t) __a; +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s64_u16 (uint16x4_t __a) +{ + return (int64x1_t) __a; +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s64_u32 (uint32x2_t __a) +{ + return (int64x1_t) __a; +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s64_u64 (uint64x1_t __a) +{ + return (int64x1_t) __a; +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s64_p8 (poly8x8_t __a) +{ + return (int64x1_t) __a; +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s64_p16 (poly16x4_t __a) +{ + return (int64x1_t) __a; +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s64_p64 (poly64x1_t __a) +{ + return (int64x1_t) __a; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s64_f64 (float64x2_t __a) +{ + return (int64x2_t) __a; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s64_s8 (int8x16_t __a) +{ + return (int64x2_t) __a; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s64_s16 (int16x8_t __a) +{ + return (int64x2_t) __a; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s64_s32 (int32x4_t __a) +{ + return (int64x2_t) __a; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s64_f16 (float16x8_t __a) +{ + return (int64x2_t) __a; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s64_f32 (float32x4_t __a) +{ + return (int64x2_t) __a; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s64_u8 (uint8x16_t __a) +{ + return (int64x2_t) __a; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s64_u16 (uint16x8_t __a) +{ + return (int64x2_t) __a; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s64_u32 (uint32x4_t __a) +{ + return (int64x2_t) __a; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s64_u64 (uint64x2_t __a) +{ + return (int64x2_t) __a; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s64_p8 (poly8x16_t __a) +{ + return (int64x2_t) __a; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s64_p16 (poly16x8_t __a) +{ + return (int64x2_t) __a; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s64_p64 (poly64x2_t __a) +{ + return (int64x2_t) __a; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s64_p128 (poly128_t __a) +{ + return (int64x2_t)__a; +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u64_f16 (float16x4_t __a) +{ + return (uint64x1_t) __a; +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u64_f64 (float64x1_t __a) +{ + return (uint64x1_t) __a; +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u64_s8 (int8x8_t __a) +{ + return (uint64x1_t) __a; +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u64_s16 (int16x4_t __a) +{ + return (uint64x1_t) __a; +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u64_s32 (int32x2_t __a) +{ + return (uint64x1_t) __a; +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u64_s64 (int64x1_t __a) +{ + return (uint64x1_t) __a; +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u64_f32 (float32x2_t __a) +{ + return (uint64x1_t) __a; +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u64_u8 (uint8x8_t __a) +{ + return (uint64x1_t) __a; +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u64_u16 (uint16x4_t __a) +{ + return (uint64x1_t) __a; +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u64_u32 (uint32x2_t __a) +{ + return (uint64x1_t) __a; +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u64_p8 (poly8x8_t __a) +{ + return (uint64x1_t) __a; +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u64_p16 (poly16x4_t __a) +{ + return (uint64x1_t) __a; +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u64_p64 (poly64x1_t __a) +{ + return (uint64x1_t) __a; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u64_f64 (float64x2_t __a) +{ + return (uint64x2_t) __a; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u64_s8 (int8x16_t __a) +{ + return (uint64x2_t) __a; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u64_s16 (int16x8_t __a) +{ + return (uint64x2_t) __a; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u64_s32 (int32x4_t __a) +{ + return (uint64x2_t) __a; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u64_s64 (int64x2_t __a) +{ + return (uint64x2_t) __a; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u64_f16 (float16x8_t __a) +{ + return (uint64x2_t) __a; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u64_f32 (float32x4_t __a) +{ + return (uint64x2_t) __a; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u64_u8 (uint8x16_t __a) +{ + return (uint64x2_t) __a; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u64_u16 (uint16x8_t __a) +{ + return (uint64x2_t) __a; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u64_u32 (uint32x4_t __a) +{ + return (uint64x2_t) __a; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u64_p8 (poly8x16_t __a) +{ + return (uint64x2_t) __a; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u64_p16 (poly16x8_t __a) +{ + return (uint64x2_t) __a; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u64_p64 (poly64x2_t __a) +{ + return (uint64x2_t) __a; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u64_p128 (poly128_t __a) +{ + return (uint64x2_t)__a; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s8_f16 (float16x4_t __a) +{ + return (int8x8_t) __a; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s8_f64 (float64x1_t __a) +{ + return (int8x8_t) __a; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s8_s16 (int16x4_t __a) +{ + return (int8x8_t) __a; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s8_s32 (int32x2_t __a) +{ + return (int8x8_t) __a; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s8_s64 (int64x1_t __a) +{ + return (int8x8_t) __a; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s8_f32 (float32x2_t __a) +{ + return (int8x8_t) __a; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s8_u8 (uint8x8_t __a) +{ + return (int8x8_t) __a; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s8_u16 (uint16x4_t __a) +{ + return (int8x8_t) __a; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s8_u32 (uint32x2_t __a) +{ + return (int8x8_t) __a; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s8_u64 (uint64x1_t __a) +{ + return (int8x8_t) __a; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s8_p8 (poly8x8_t __a) +{ + return (int8x8_t) __a; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s8_p16 (poly16x4_t __a) +{ + return (int8x8_t) __a; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s8_p64 (poly64x1_t __a) +{ + return (int8x8_t) __a; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s8_f64 (float64x2_t __a) +{ + return (int8x16_t) __a; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s8_s16 (int16x8_t __a) +{ + return (int8x16_t) __a; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s8_s32 (int32x4_t __a) +{ + return (int8x16_t) __a; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s8_s64 (int64x2_t __a) +{ + return (int8x16_t) __a; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s8_f16 (float16x8_t __a) +{ + return (int8x16_t) __a; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s8_f32 (float32x4_t __a) +{ + return (int8x16_t) __a; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s8_u8 (uint8x16_t __a) +{ + return (int8x16_t) __a; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s8_u16 (uint16x8_t __a) +{ + return (int8x16_t) __a; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s8_u32 (uint32x4_t __a) +{ + return (int8x16_t) __a; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s8_u64 (uint64x2_t __a) +{ + return (int8x16_t) __a; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s8_p8 (poly8x16_t __a) +{ + return (int8x16_t) __a; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s8_p16 (poly16x8_t __a) +{ + return (int8x16_t) __a; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s8_p64 (poly64x2_t __a) +{ + return (int8x16_t) __a; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s8_p128 (poly128_t __a) +{ + return (int8x16_t)__a; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s16_f16 (float16x4_t __a) +{ + return (int16x4_t) __a; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s16_f64 (float64x1_t __a) +{ + return (int16x4_t) __a; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s16_s8 (int8x8_t __a) +{ + return (int16x4_t) __a; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s16_s32 (int32x2_t __a) +{ + return (int16x4_t) __a; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s16_s64 (int64x1_t __a) +{ + return (int16x4_t) __a; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s16_f32 (float32x2_t __a) +{ + return (int16x4_t) __a; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s16_u8 (uint8x8_t __a) +{ + return (int16x4_t) __a; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s16_u16 (uint16x4_t __a) +{ + return (int16x4_t) __a; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s16_u32 (uint32x2_t __a) +{ + return (int16x4_t) __a; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s16_u64 (uint64x1_t __a) +{ + return (int16x4_t) __a; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s16_p8 (poly8x8_t __a) +{ + return (int16x4_t) __a; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s16_p16 (poly16x4_t __a) +{ + return (int16x4_t) __a; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s16_p64 (poly64x1_t __a) +{ + return (int16x4_t) __a; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s16_f64 (float64x2_t __a) +{ + return (int16x8_t) __a; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s16_s8 (int8x16_t __a) +{ + return (int16x8_t) __a; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s16_s32 (int32x4_t __a) +{ + return (int16x8_t) __a; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s16_s64 (int64x2_t __a) +{ + return (int16x8_t) __a; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s16_f16 (float16x8_t __a) +{ + return (int16x8_t) __a; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s16_f32 (float32x4_t __a) +{ + return (int16x8_t) __a; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s16_u8 (uint8x16_t __a) +{ + return (int16x8_t) __a; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s16_u16 (uint16x8_t __a) +{ + return (int16x8_t) __a; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s16_u32 (uint32x4_t __a) +{ + return (int16x8_t) __a; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s16_u64 (uint64x2_t __a) +{ + return (int16x8_t) __a; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s16_p8 (poly8x16_t __a) +{ + return (int16x8_t) __a; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s16_p16 (poly16x8_t __a) +{ + return (int16x8_t) __a; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s16_p64 (poly64x2_t __a) +{ + return (int16x8_t) __a; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s16_p128 (poly128_t __a) +{ + return (int16x8_t)__a; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s32_f16 (float16x4_t __a) +{ + return (int32x2_t) __a; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s32_f64 (float64x1_t __a) +{ + return (int32x2_t) __a; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s32_s8 (int8x8_t __a) +{ + return (int32x2_t) __a; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s32_s16 (int16x4_t __a) +{ + return (int32x2_t) __a; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s32_s64 (int64x1_t __a) +{ + return (int32x2_t) __a; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s32_f32 (float32x2_t __a) +{ + return (int32x2_t) __a; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s32_u8 (uint8x8_t __a) +{ + return (int32x2_t) __a; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s32_u16 (uint16x4_t __a) +{ + return (int32x2_t) __a; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s32_u32 (uint32x2_t __a) +{ + return (int32x2_t) __a; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s32_u64 (uint64x1_t __a) +{ + return (int32x2_t) __a; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s32_p8 (poly8x8_t __a) +{ + return (int32x2_t) __a; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s32_p16 (poly16x4_t __a) +{ + return (int32x2_t) __a; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_s32_p64 (poly64x1_t __a) +{ + return (int32x2_t) __a; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s32_f64 (float64x2_t __a) +{ + return (int32x4_t) __a; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s32_s8 (int8x16_t __a) +{ + return (int32x4_t) __a; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s32_s16 (int16x8_t __a) +{ + return (int32x4_t) __a; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s32_s64 (int64x2_t __a) +{ + return (int32x4_t) __a; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s32_f16 (float16x8_t __a) +{ + return (int32x4_t) __a; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s32_f32 (float32x4_t __a) +{ + return (int32x4_t) __a; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s32_u8 (uint8x16_t __a) +{ + return (int32x4_t) __a; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s32_u16 (uint16x8_t __a) +{ + return (int32x4_t) __a; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s32_u32 (uint32x4_t __a) +{ + return (int32x4_t) __a; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s32_u64 (uint64x2_t __a) +{ + return (int32x4_t) __a; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s32_p8 (poly8x16_t __a) +{ + return (int32x4_t) __a; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s32_p16 (poly16x8_t __a) +{ + return (int32x4_t) __a; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s32_p64 (poly64x2_t __a) +{ + return (int32x4_t) __a; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_s32_p128 (poly128_t __a) +{ + return (int32x4_t)__a; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u8_f16 (float16x4_t __a) +{ + return (uint8x8_t) __a; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u8_f64 (float64x1_t __a) +{ + return (uint8x8_t) __a; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u8_s8 (int8x8_t __a) +{ + return (uint8x8_t) __a; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u8_s16 (int16x4_t __a) +{ + return (uint8x8_t) __a; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u8_s32 (int32x2_t __a) +{ + return (uint8x8_t) __a; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u8_s64 (int64x1_t __a) +{ + return (uint8x8_t) __a; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u8_f32 (float32x2_t __a) +{ + return (uint8x8_t) __a; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u8_u16 (uint16x4_t __a) +{ + return (uint8x8_t) __a; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u8_u32 (uint32x2_t __a) +{ + return (uint8x8_t) __a; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u8_u64 (uint64x1_t __a) +{ + return (uint8x8_t) __a; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u8_p8 (poly8x8_t __a) +{ + return (uint8x8_t) __a; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u8_p16 (poly16x4_t __a) +{ + return (uint8x8_t) __a; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u8_p64 (poly64x1_t __a) +{ + return (uint8x8_t) __a; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u8_f64 (float64x2_t __a) +{ + return (uint8x16_t) __a; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u8_s8 (int8x16_t __a) +{ + return (uint8x16_t) __a; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u8_s16 (int16x8_t __a) +{ + return (uint8x16_t) __a; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u8_s32 (int32x4_t __a) +{ + return (uint8x16_t) __a; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u8_s64 (int64x2_t __a) +{ + return (uint8x16_t) __a; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u8_f16 (float16x8_t __a) +{ + return (uint8x16_t) __a; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u8_f32 (float32x4_t __a) +{ + return (uint8x16_t) __a; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u8_u16 (uint16x8_t __a) +{ + return (uint8x16_t) __a; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u8_u32 (uint32x4_t __a) +{ + return (uint8x16_t) __a; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u8_u64 (uint64x2_t __a) +{ + return (uint8x16_t) __a; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u8_p8 (poly8x16_t __a) +{ + return (uint8x16_t) __a; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u8_p16 (poly16x8_t __a) +{ + return (uint8x16_t) __a; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u8_p64 (poly64x2_t __a) +{ + return (uint8x16_t) __a; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u8_p128 (poly128_t __a) +{ + return (uint8x16_t)__a; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u16_f16 (float16x4_t __a) +{ + return (uint16x4_t) __a; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u16_f64 (float64x1_t __a) +{ + return (uint16x4_t) __a; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u16_s8 (int8x8_t __a) +{ + return (uint16x4_t) __a; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u16_s16 (int16x4_t __a) +{ + return (uint16x4_t) __a; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u16_s32 (int32x2_t __a) +{ + return (uint16x4_t) __a; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u16_s64 (int64x1_t __a) +{ + return (uint16x4_t) __a; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u16_f32 (float32x2_t __a) +{ + return (uint16x4_t) __a; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u16_u8 (uint8x8_t __a) +{ + return (uint16x4_t) __a; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u16_u32 (uint32x2_t __a) +{ + return (uint16x4_t) __a; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u16_u64 (uint64x1_t __a) +{ + return (uint16x4_t) __a; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u16_p8 (poly8x8_t __a) +{ + return (uint16x4_t) __a; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u16_p16 (poly16x4_t __a) +{ + return (uint16x4_t) __a; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u16_p64 (poly64x1_t __a) +{ + return (uint16x4_t) __a; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u16_f64 (float64x2_t __a) +{ + return (uint16x8_t) __a; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u16_s8 (int8x16_t __a) +{ + return (uint16x8_t) __a; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u16_s16 (int16x8_t __a) +{ + return (uint16x8_t) __a; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u16_s32 (int32x4_t __a) +{ + return (uint16x8_t) __a; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u16_s64 (int64x2_t __a) +{ + return (uint16x8_t) __a; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u16_f16 (float16x8_t __a) +{ + return (uint16x8_t) __a; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u16_f32 (float32x4_t __a) +{ + return (uint16x8_t) __a; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u16_u8 (uint8x16_t __a) +{ + return (uint16x8_t) __a; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u16_u32 (uint32x4_t __a) +{ + return (uint16x8_t) __a; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u16_u64 (uint64x2_t __a) +{ + return (uint16x8_t) __a; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u16_p8 (poly8x16_t __a) +{ + return (uint16x8_t) __a; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u16_p16 (poly16x8_t __a) +{ + return (uint16x8_t) __a; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u16_p64 (poly64x2_t __a) +{ + return (uint16x8_t) __a; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u16_p128 (poly128_t __a) +{ + return (uint16x8_t)__a; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u32_f16 (float16x4_t __a) +{ + return (uint32x2_t) __a; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u32_f64 (float64x1_t __a) +{ + return (uint32x2_t) __a; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u32_s8 (int8x8_t __a) +{ + return (uint32x2_t) __a; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u32_s16 (int16x4_t __a) +{ + return (uint32x2_t) __a; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u32_s32 (int32x2_t __a) +{ + return (uint32x2_t) __a; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u32_s64 (int64x1_t __a) +{ + return (uint32x2_t) __a; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u32_f32 (float32x2_t __a) +{ + return (uint32x2_t) __a; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u32_u8 (uint8x8_t __a) +{ + return (uint32x2_t) __a; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u32_u16 (uint16x4_t __a) +{ + return (uint32x2_t) __a; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u32_u64 (uint64x1_t __a) +{ + return (uint32x2_t) __a; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u32_p8 (poly8x8_t __a) +{ + return (uint32x2_t) __a; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u32_p16 (poly16x4_t __a) +{ + return (uint32x2_t) __a; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpret_u32_p64 (poly64x1_t __a) +{ + return (uint32x2_t) __a; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u32_f64 (float64x2_t __a) +{ + return (uint32x4_t) __a; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u32_s8 (int8x16_t __a) +{ + return (uint32x4_t) __a; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u32_s16 (int16x8_t __a) +{ + return (uint32x4_t) __a; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u32_s32 (int32x4_t __a) +{ + return (uint32x4_t) __a; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u32_s64 (int64x2_t __a) +{ + return (uint32x4_t) __a; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u32_f16 (float16x8_t __a) +{ + return (uint32x4_t) __a; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u32_f32 (float32x4_t __a) +{ + return (uint32x4_t) __a; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u32_u8 (uint8x16_t __a) +{ + return (uint32x4_t) __a; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u32_u16 (uint16x8_t __a) +{ + return (uint32x4_t) __a; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u32_u64 (uint64x2_t __a) +{ + return (uint32x4_t) __a; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u32_p8 (poly8x16_t __a) +{ + return (uint32x4_t) __a; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u32_p16 (poly16x8_t __a) +{ + return (uint32x4_t) __a; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u32_p64 (poly64x2_t __a) +{ + return (uint32x4_t) __a; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vreinterpretq_u32_p128 (poly128_t __a) +{ + return (uint32x4_t)__a; +} + +/* vset_lane */ + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vset_lane_f16 (float16_t __elem, float16x4_t __vec, const int __index) +{ + return __aarch64_vset_lane_any (__elem, __vec, __index); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vset_lane_f32 (float32_t __elem, float32x2_t __vec, const int __index) +{ + return __aarch64_vset_lane_any (__elem, __vec, __index); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vset_lane_f64 (float64_t __elem, float64x1_t __vec, const int __index) +{ + return __aarch64_vset_lane_any (__elem, __vec, __index); +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vset_lane_p8 (poly8_t __elem, poly8x8_t __vec, const int __index) +{ + return __aarch64_vset_lane_any (__elem, __vec, __index); +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vset_lane_p16 (poly16_t __elem, poly16x4_t __vec, const int __index) +{ + return __aarch64_vset_lane_any (__elem, __vec, __index); +} + +__extension__ extern __inline poly64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vset_lane_p64 (poly64_t __elem, poly64x1_t __vec, const int __index) +{ + return __aarch64_vset_lane_any (__elem, __vec, __index); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vset_lane_s8 (int8_t __elem, int8x8_t __vec, const int __index) +{ + return __aarch64_vset_lane_any (__elem, __vec, __index); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vset_lane_s16 (int16_t __elem, int16x4_t __vec, const int __index) +{ + return __aarch64_vset_lane_any (__elem, __vec, __index); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vset_lane_s32 (int32_t __elem, int32x2_t __vec, const int __index) +{ + return __aarch64_vset_lane_any (__elem, __vec, __index); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vset_lane_s64 (int64_t __elem, int64x1_t __vec, const int __index) +{ + return __aarch64_vset_lane_any (__elem, __vec, __index); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vset_lane_u8 (uint8_t __elem, uint8x8_t __vec, const int __index) +{ + return __aarch64_vset_lane_any (__elem, __vec, __index); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vset_lane_u16 (uint16_t __elem, uint16x4_t __vec, const int __index) +{ + return __aarch64_vset_lane_any (__elem, __vec, __index); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vset_lane_u32 (uint32_t __elem, uint32x2_t __vec, const int __index) +{ + return __aarch64_vset_lane_any (__elem, __vec, __index); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vset_lane_u64 (uint64_t __elem, uint64x1_t __vec, const int __index) +{ + return __aarch64_vset_lane_any (__elem, __vec, __index); +} + +/* vsetq_lane */ + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsetq_lane_f16 (float16_t __elem, float16x8_t __vec, const int __index) +{ + return __aarch64_vset_lane_any (__elem, __vec, __index); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsetq_lane_f32 (float32_t __elem, float32x4_t __vec, const int __index) +{ + return __aarch64_vset_lane_any (__elem, __vec, __index); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsetq_lane_f64 (float64_t __elem, float64x2_t __vec, const int __index) +{ + return __aarch64_vset_lane_any (__elem, __vec, __index); +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsetq_lane_p8 (poly8_t __elem, poly8x16_t __vec, const int __index) +{ + return __aarch64_vset_lane_any (__elem, __vec, __index); +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsetq_lane_p16 (poly16_t __elem, poly16x8_t __vec, const int __index) +{ + return __aarch64_vset_lane_any (__elem, __vec, __index); +} + +__extension__ extern __inline poly64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsetq_lane_p64 (poly64_t __elem, poly64x2_t __vec, const int __index) +{ + return __aarch64_vset_lane_any (__elem, __vec, __index); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsetq_lane_s8 (int8_t __elem, int8x16_t __vec, const int __index) +{ + return __aarch64_vset_lane_any (__elem, __vec, __index); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsetq_lane_s16 (int16_t __elem, int16x8_t __vec, const int __index) +{ + return __aarch64_vset_lane_any (__elem, __vec, __index); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsetq_lane_s32 (int32_t __elem, int32x4_t __vec, const int __index) +{ + return __aarch64_vset_lane_any (__elem, __vec, __index); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsetq_lane_s64 (int64_t __elem, int64x2_t __vec, const int __index) +{ + return __aarch64_vset_lane_any (__elem, __vec, __index); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsetq_lane_u8 (uint8_t __elem, uint8x16_t __vec, const int __index) +{ + return __aarch64_vset_lane_any (__elem, __vec, __index); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsetq_lane_u16 (uint16_t __elem, uint16x8_t __vec, const int __index) +{ + return __aarch64_vset_lane_any (__elem, __vec, __index); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsetq_lane_u32 (uint32_t __elem, uint32x4_t __vec, const int __index) +{ + return __aarch64_vset_lane_any (__elem, __vec, __index); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsetq_lane_u64 (uint64_t __elem, uint64x2_t __vec, const int __index) +{ + return __aarch64_vset_lane_any (__elem, __vec, __index); +} + +#define __GET_LOW(__TYPE) \ + uint64x2_t tmp = vreinterpretq_u64_##__TYPE (__a); \ + uint64x1_t lo = vcreate_u64 (vgetq_lane_u64 (tmp, 0)); \ + return vreinterpret_##__TYPE##_u64 (lo); + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_low_f16 (float16x8_t __a) +{ + __GET_LOW (f16); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_low_f32 (float32x4_t __a) +{ + __GET_LOW (f32); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_low_f64 (float64x2_t __a) +{ + return (float64x1_t) {vgetq_lane_f64 (__a, 0)}; +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_low_p8 (poly8x16_t __a) +{ + __GET_LOW (p8); +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_low_p16 (poly16x8_t __a) +{ + __GET_LOW (p16); +} + +__extension__ extern __inline poly64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_low_p64 (poly64x2_t __a) +{ + __GET_LOW (p64); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_low_s8 (int8x16_t __a) +{ + __GET_LOW (s8); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_low_s16 (int16x8_t __a) +{ + __GET_LOW (s16); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_low_s32 (int32x4_t __a) +{ + __GET_LOW (s32); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_low_s64 (int64x2_t __a) +{ + __GET_LOW (s64); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_low_u8 (uint8x16_t __a) +{ + __GET_LOW (u8); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_low_u16 (uint16x8_t __a) +{ + __GET_LOW (u16); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_low_u32 (uint32x4_t __a) +{ + __GET_LOW (u32); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_low_u64 (uint64x2_t __a) +{ + return vcreate_u64 (vgetq_lane_u64 (__a, 0)); +} + +#undef __GET_LOW + +#define __GET_HIGH(__TYPE) \ + uint64x2_t tmp = vreinterpretq_u64_##__TYPE (__a); \ + uint64x1_t hi = vcreate_u64 (vgetq_lane_u64 (tmp, 1)); \ + return vreinterpret_##__TYPE##_u64 (hi); + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_high_f16 (float16x8_t __a) +{ + __GET_HIGH (f16); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_high_f32 (float32x4_t __a) +{ + __GET_HIGH (f32); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_high_f64 (float64x2_t __a) +{ + __GET_HIGH (f64); +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_high_p8 (poly8x16_t __a) +{ + __GET_HIGH (p8); +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_high_p16 (poly16x8_t __a) +{ + __GET_HIGH (p16); +} + +__extension__ extern __inline poly64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_high_p64 (poly64x2_t __a) +{ + __GET_HIGH (p64); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_high_s8 (int8x16_t __a) +{ + __GET_HIGH (s8); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_high_s16 (int16x8_t __a) +{ + __GET_HIGH (s16); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_high_s32 (int32x4_t __a) +{ + __GET_HIGH (s32); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_high_s64 (int64x2_t __a) +{ + __GET_HIGH (s64); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_high_u8 (uint8x16_t __a) +{ + __GET_HIGH (u8); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_high_u16 (uint16x8_t __a) +{ + __GET_HIGH (u16); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_high_u32 (uint32x4_t __a) +{ + __GET_HIGH (u32); +} + +#undef __GET_HIGH + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vget_high_u64 (uint64x2_t __a) +{ + return vcreate_u64 (vgetq_lane_u64 (__a, 1)); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcombine_s8 (int8x8_t __a, int8x8_t __b) +{ + return (int8x16_t) __builtin_aarch64_combinev8qi (__a, __b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcombine_s16 (int16x4_t __a, int16x4_t __b) +{ + return (int16x8_t) __builtin_aarch64_combinev4hi (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcombine_s32 (int32x2_t __a, int32x2_t __b) +{ + return (int32x4_t) __builtin_aarch64_combinev2si (__a, __b); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcombine_s64 (int64x1_t __a, int64x1_t __b) +{ + return __builtin_aarch64_combinedi (__a[0], __b[0]); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcombine_f16 (float16x4_t __a, float16x4_t __b) +{ + return __builtin_aarch64_combinev4hf (__a, __b); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcombine_f32 (float32x2_t __a, float32x2_t __b) +{ + return (float32x4_t) __builtin_aarch64_combinev2sf (__a, __b); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcombine_u8 (uint8x8_t __a, uint8x8_t __b) +{ + return (uint8x16_t) __builtin_aarch64_combinev8qi ((int8x8_t) __a, + (int8x8_t) __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcombine_u16 (uint16x4_t __a, uint16x4_t __b) +{ + return (uint16x8_t) __builtin_aarch64_combinev4hi ((int16x4_t) __a, + (int16x4_t) __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcombine_u32 (uint32x2_t __a, uint32x2_t __b) +{ + return (uint32x4_t) __builtin_aarch64_combinev2si ((int32x2_t) __a, + (int32x2_t) __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcombine_u64 (uint64x1_t __a, uint64x1_t __b) +{ + return (uint64x2_t) __builtin_aarch64_combinedi (__a[0], __b[0]); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcombine_f64 (float64x1_t __a, float64x1_t __b) +{ + return __builtin_aarch64_combinedf (__a[0], __b[0]); +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcombine_p8 (poly8x8_t __a, poly8x8_t __b) +{ + return (poly8x16_t) __builtin_aarch64_combinev8qi ((int8x8_t) __a, + (int8x8_t) __b); +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcombine_p16 (poly16x4_t __a, poly16x4_t __b) +{ + return (poly16x8_t) __builtin_aarch64_combinev4hi ((int16x4_t) __a, + (int16x4_t) __b); +} + +__extension__ extern __inline poly64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcombine_p64 (poly64x1_t __a, poly64x1_t __b) +{ + return (poly64x2_t) __builtin_aarch64_combinedi_ppp (__a[0], __b[0]); +} + +/* Start of temporary inline asm implementations. */ + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaba_s8 (int8x8_t a, int8x8_t b, int8x8_t c) +{ + int8x8_t result; + __asm__ ("saba %0.8b,%2.8b,%3.8b" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaba_s16 (int16x4_t a, int16x4_t b, int16x4_t c) +{ + int16x4_t result; + __asm__ ("saba %0.4h,%2.4h,%3.4h" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaba_s32 (int32x2_t a, int32x2_t b, int32x2_t c) +{ + int32x2_t result; + __asm__ ("saba %0.2s,%2.2s,%3.2s" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaba_u8 (uint8x8_t a, uint8x8_t b, uint8x8_t c) +{ + uint8x8_t result; + __asm__ ("uaba %0.8b,%2.8b,%3.8b" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaba_u16 (uint16x4_t a, uint16x4_t b, uint16x4_t c) +{ + uint16x4_t result; + __asm__ ("uaba %0.4h,%2.4h,%3.4h" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaba_u32 (uint32x2_t a, uint32x2_t b, uint32x2_t c) +{ + uint32x2_t result; + __asm__ ("uaba %0.2s,%2.2s,%3.2s" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabal_high_s8 (int16x8_t a, int8x16_t b, int8x16_t c) +{ + int16x8_t result; + __asm__ ("sabal2 %0.8h,%2.16b,%3.16b" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabal_high_s16 (int32x4_t a, int16x8_t b, int16x8_t c) +{ + int32x4_t result; + __asm__ ("sabal2 %0.4s,%2.8h,%3.8h" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabal_high_s32 (int64x2_t a, int32x4_t b, int32x4_t c) +{ + int64x2_t result; + __asm__ ("sabal2 %0.2d,%2.4s,%3.4s" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabal_high_u8 (uint16x8_t a, uint8x16_t b, uint8x16_t c) +{ + uint16x8_t result; + __asm__ ("uabal2 %0.8h,%2.16b,%3.16b" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabal_high_u16 (uint32x4_t a, uint16x8_t b, uint16x8_t c) +{ + uint32x4_t result; + __asm__ ("uabal2 %0.4s,%2.8h,%3.8h" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabal_high_u32 (uint64x2_t a, uint32x4_t b, uint32x4_t c) +{ + uint64x2_t result; + __asm__ ("uabal2 %0.2d,%2.4s,%3.4s" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabal_s8 (int16x8_t a, int8x8_t b, int8x8_t c) +{ + int16x8_t result; + __asm__ ("sabal %0.8h,%2.8b,%3.8b" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabal_s16 (int32x4_t a, int16x4_t b, int16x4_t c) +{ + int32x4_t result; + __asm__ ("sabal %0.4s,%2.4h,%3.4h" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabal_s32 (int64x2_t a, int32x2_t b, int32x2_t c) +{ + int64x2_t result; + __asm__ ("sabal %0.2d,%2.2s,%3.2s" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabal_u8 (uint16x8_t a, uint8x8_t b, uint8x8_t c) +{ + uint16x8_t result; + __asm__ ("uabal %0.8h,%2.8b,%3.8b" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabal_u16 (uint32x4_t a, uint16x4_t b, uint16x4_t c) +{ + uint32x4_t result; + __asm__ ("uabal %0.4s,%2.4h,%3.4h" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabal_u32 (uint64x2_t a, uint32x2_t b, uint32x2_t c) +{ + uint64x2_t result; + __asm__ ("uabal %0.2d,%2.2s,%3.2s" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabaq_s8 (int8x16_t a, int8x16_t b, int8x16_t c) +{ + int8x16_t result; + __asm__ ("saba %0.16b,%2.16b,%3.16b" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabaq_s16 (int16x8_t a, int16x8_t b, int16x8_t c) +{ + int16x8_t result; + __asm__ ("saba %0.8h,%2.8h,%3.8h" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabaq_s32 (int32x4_t a, int32x4_t b, int32x4_t c) +{ + int32x4_t result; + __asm__ ("saba %0.4s,%2.4s,%3.4s" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabaq_u8 (uint8x16_t a, uint8x16_t b, uint8x16_t c) +{ + uint8x16_t result; + __asm__ ("uaba %0.16b,%2.16b,%3.16b" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabaq_u16 (uint16x8_t a, uint16x8_t b, uint16x8_t c) +{ + uint16x8_t result; + __asm__ ("uaba %0.8h,%2.8h,%3.8h" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabaq_u32 (uint32x4_t a, uint32x4_t b, uint32x4_t c) +{ + uint32x4_t result; + __asm__ ("uaba %0.4s,%2.4s,%3.4s" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabd_s8 (int8x8_t a, int8x8_t b) +{ + int8x8_t result; + __asm__ ("sabd %0.8b, %1.8b, %2.8b" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabd_s16 (int16x4_t a, int16x4_t b) +{ + int16x4_t result; + __asm__ ("sabd %0.4h, %1.4h, %2.4h" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabd_s32 (int32x2_t a, int32x2_t b) +{ + int32x2_t result; + __asm__ ("sabd %0.2s, %1.2s, %2.2s" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabd_u8 (uint8x8_t a, uint8x8_t b) +{ + uint8x8_t result; + __asm__ ("uabd %0.8b, %1.8b, %2.8b" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabd_u16 (uint16x4_t a, uint16x4_t b) +{ + uint16x4_t result; + __asm__ ("uabd %0.4h, %1.4h, %2.4h" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabd_u32 (uint32x2_t a, uint32x2_t b) +{ + uint32x2_t result; + __asm__ ("uabd %0.2s, %1.2s, %2.2s" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabdl_high_s8 (int8x16_t a, int8x16_t b) +{ + int16x8_t result; + __asm__ ("sabdl2 %0.8h,%1.16b,%2.16b" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabdl_high_s16 (int16x8_t a, int16x8_t b) +{ + int32x4_t result; + __asm__ ("sabdl2 %0.4s,%1.8h,%2.8h" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabdl_high_s32 (int32x4_t a, int32x4_t b) +{ + int64x2_t result; + __asm__ ("sabdl2 %0.2d,%1.4s,%2.4s" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabdl_high_u8 (uint8x16_t a, uint8x16_t b) +{ + uint16x8_t result; + __asm__ ("uabdl2 %0.8h,%1.16b,%2.16b" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabdl_high_u16 (uint16x8_t a, uint16x8_t b) +{ + uint32x4_t result; + __asm__ ("uabdl2 %0.4s,%1.8h,%2.8h" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabdl_high_u32 (uint32x4_t a, uint32x4_t b) +{ + uint64x2_t result; + __asm__ ("uabdl2 %0.2d,%1.4s,%2.4s" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabdl_s8 (int8x8_t a, int8x8_t b) +{ + int16x8_t result; + __asm__ ("sabdl %0.8h, %1.8b, %2.8b" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabdl_s16 (int16x4_t a, int16x4_t b) +{ + int32x4_t result; + __asm__ ("sabdl %0.4s, %1.4h, %2.4h" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabdl_s32 (int32x2_t a, int32x2_t b) +{ + int64x2_t result; + __asm__ ("sabdl %0.2d, %1.2s, %2.2s" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabdl_u8 (uint8x8_t a, uint8x8_t b) +{ + uint16x8_t result; + __asm__ ("uabdl %0.8h, %1.8b, %2.8b" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabdl_u16 (uint16x4_t a, uint16x4_t b) +{ + uint32x4_t result; + __asm__ ("uabdl %0.4s, %1.4h, %2.4h" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabdl_u32 (uint32x2_t a, uint32x2_t b) +{ + uint64x2_t result; + __asm__ ("uabdl %0.2d, %1.2s, %2.2s" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabdq_s8 (int8x16_t a, int8x16_t b) +{ + int8x16_t result; + __asm__ ("sabd %0.16b, %1.16b, %2.16b" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabdq_s16 (int16x8_t a, int16x8_t b) +{ + int16x8_t result; + __asm__ ("sabd %0.8h, %1.8h, %2.8h" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabdq_s32 (int32x4_t a, int32x4_t b) +{ + int32x4_t result; + __asm__ ("sabd %0.4s, %1.4s, %2.4s" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabdq_u8 (uint8x16_t a, uint8x16_t b) +{ + uint8x16_t result; + __asm__ ("uabd %0.16b, %1.16b, %2.16b" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabdq_u16 (uint16x8_t a, uint16x8_t b) +{ + uint16x8_t result; + __asm__ ("uabd %0.8h, %1.8h, %2.8h" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabdq_u32 (uint32x4_t a, uint32x4_t b) +{ + uint32x4_t result; + __asm__ ("uabd %0.4s, %1.4s, %2.4s" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddlv_s8 (int8x8_t a) +{ + int16_t result; + __asm__ ("saddlv %h0,%1.8b" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddlv_s16 (int16x4_t a) +{ + int32_t result; + __asm__ ("saddlv %s0,%1.4h" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddlv_u8 (uint8x8_t a) +{ + uint16_t result; + __asm__ ("uaddlv %h0,%1.8b" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddlv_u16 (uint16x4_t a) +{ + uint32_t result; + __asm__ ("uaddlv %s0,%1.4h" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddlvq_s8 (int8x16_t a) +{ + int16_t result; + __asm__ ("saddlv %h0,%1.16b" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddlvq_s16 (int16x8_t a) +{ + int32_t result; + __asm__ ("saddlv %s0,%1.8h" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddlvq_s32 (int32x4_t a) +{ + int64_t result; + __asm__ ("saddlv %d0,%1.4s" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddlvq_u8 (uint8x16_t a) +{ + uint16_t result; + __asm__ ("uaddlv %h0,%1.16b" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddlvq_u16 (uint16x8_t a) +{ + uint32_t result; + __asm__ ("uaddlv %s0,%1.8h" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddlvq_u32 (uint32x4_t a) +{ + uint64_t result; + __asm__ ("uaddlv %d0,%1.4s" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtx_f32_f64 (float64x2_t a) +{ + float32x2_t result; + __asm__ ("fcvtxn %0.2s,%1.2d" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtx_high_f32_f64 (float32x2_t a, float64x2_t b) +{ + float32x4_t result; + __asm__ ("fcvtxn2 %0.4s,%1.2d" + : "=w"(result) + : "w" (b), "0"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtxd_f32_f64 (float64_t a) +{ + float32_t result; + __asm__ ("fcvtxn %s0,%d1" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmla_n_f32 (float32x2_t a, float32x2_t b, float32_t c) +{ + float32x2_t result; + float32x2_t t1; + __asm__ ("fmul %1.2s, %3.2s, %4.s[0]; fadd %0.2s, %0.2s, %1.2s" + : "=w"(result), "=w"(t1) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmla_n_s16 (int16x4_t a, int16x4_t b, int16_t c) +{ + int16x4_t result; + __asm__ ("mla %0.4h,%2.4h,%3.h[0]" + : "=w"(result) + : "0"(a), "w"(b), "x"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmla_n_s32 (int32x2_t a, int32x2_t b, int32_t c) +{ + int32x2_t result; + __asm__ ("mla %0.2s,%2.2s,%3.s[0]" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmla_n_u16 (uint16x4_t a, uint16x4_t b, uint16_t c) +{ + uint16x4_t result; + __asm__ ("mla %0.4h,%2.4h,%3.h[0]" + : "=w"(result) + : "0"(a), "w"(b), "x"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmla_n_u32 (uint32x2_t a, uint32x2_t b, uint32_t c) +{ + uint32x2_t result; + __asm__ ("mla %0.2s,%2.2s,%3.s[0]" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmla_s8 (int8x8_t a, int8x8_t b, int8x8_t c) +{ + int8x8_t result; + __asm__ ("mla %0.8b, %2.8b, %3.8b" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmla_s16 (int16x4_t a, int16x4_t b, int16x4_t c) +{ + int16x4_t result; + __asm__ ("mla %0.4h, %2.4h, %3.4h" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmla_s32 (int32x2_t a, int32x2_t b, int32x2_t c) +{ + int32x2_t result; + __asm__ ("mla %0.2s, %2.2s, %3.2s" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmla_u8 (uint8x8_t a, uint8x8_t b, uint8x8_t c) +{ + uint8x8_t result; + __asm__ ("mla %0.8b, %2.8b, %3.8b" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmla_u16 (uint16x4_t a, uint16x4_t b, uint16x4_t c) +{ + uint16x4_t result; + __asm__ ("mla %0.4h, %2.4h, %3.4h" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmla_u32 (uint32x2_t a, uint32x2_t b, uint32x2_t c) +{ + uint32x2_t result; + __asm__ ("mla %0.2s, %2.2s, %3.2s" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +#define vmlal_high_lane_s16(a, b, c, d) \ + __extension__ \ + ({ \ + int16x4_t c_ = (c); \ + int16x8_t b_ = (b); \ + int32x4_t a_ = (a); \ + int32x4_t result; \ + __asm__ ("smlal2 %0.4s, %2.8h, %3.h[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "x"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmlal_high_lane_s32(a, b, c, d) \ + __extension__ \ + ({ \ + int32x2_t c_ = (c); \ + int32x4_t b_ = (b); \ + int64x2_t a_ = (a); \ + int64x2_t result; \ + __asm__ ("smlal2 %0.2d, %2.4s, %3.s[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "w"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmlal_high_lane_u16(a, b, c, d) \ + __extension__ \ + ({ \ + uint16x4_t c_ = (c); \ + uint16x8_t b_ = (b); \ + uint32x4_t a_ = (a); \ + uint32x4_t result; \ + __asm__ ("umlal2 %0.4s, %2.8h, %3.h[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "x"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmlal_high_lane_u32(a, b, c, d) \ + __extension__ \ + ({ \ + uint32x2_t c_ = (c); \ + uint32x4_t b_ = (b); \ + uint64x2_t a_ = (a); \ + uint64x2_t result; \ + __asm__ ("umlal2 %0.2d, %2.4s, %3.s[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "w"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmlal_high_laneq_s16(a, b, c, d) \ + __extension__ \ + ({ \ + int16x8_t c_ = (c); \ + int16x8_t b_ = (b); \ + int32x4_t a_ = (a); \ + int32x4_t result; \ + __asm__ ("smlal2 %0.4s, %2.8h, %3.h[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "x"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmlal_high_laneq_s32(a, b, c, d) \ + __extension__ \ + ({ \ + int32x4_t c_ = (c); \ + int32x4_t b_ = (b); \ + int64x2_t a_ = (a); \ + int64x2_t result; \ + __asm__ ("smlal2 %0.2d, %2.4s, %3.s[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "w"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmlal_high_laneq_u16(a, b, c, d) \ + __extension__ \ + ({ \ + uint16x8_t c_ = (c); \ + uint16x8_t b_ = (b); \ + uint32x4_t a_ = (a); \ + uint32x4_t result; \ + __asm__ ("umlal2 %0.4s, %2.8h, %3.h[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "x"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmlal_high_laneq_u32(a, b, c, d) \ + __extension__ \ + ({ \ + uint32x4_t c_ = (c); \ + uint32x4_t b_ = (b); \ + uint64x2_t a_ = (a); \ + uint64x2_t result; \ + __asm__ ("umlal2 %0.2d, %2.4s, %3.s[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "w"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlal_high_n_s16 (int32x4_t a, int16x8_t b, int16_t c) +{ + int32x4_t result; + __asm__ ("smlal2 %0.4s,%2.8h,%3.h[0]" + : "=w"(result) + : "0"(a), "w"(b), "x"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlal_high_n_s32 (int64x2_t a, int32x4_t b, int32_t c) +{ + int64x2_t result; + __asm__ ("smlal2 %0.2d,%2.4s,%3.s[0]" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlal_high_n_u16 (uint32x4_t a, uint16x8_t b, uint16_t c) +{ + uint32x4_t result; + __asm__ ("umlal2 %0.4s,%2.8h,%3.h[0]" + : "=w"(result) + : "0"(a), "w"(b), "x"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlal_high_n_u32 (uint64x2_t a, uint32x4_t b, uint32_t c) +{ + uint64x2_t result; + __asm__ ("umlal2 %0.2d,%2.4s,%3.s[0]" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlal_high_s8 (int16x8_t a, int8x16_t b, int8x16_t c) +{ + int16x8_t result; + __asm__ ("smlal2 %0.8h,%2.16b,%3.16b" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlal_high_s16 (int32x4_t a, int16x8_t b, int16x8_t c) +{ + int32x4_t result; + __asm__ ("smlal2 %0.4s,%2.8h,%3.8h" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlal_high_s32 (int64x2_t a, int32x4_t b, int32x4_t c) +{ + int64x2_t result; + __asm__ ("smlal2 %0.2d,%2.4s,%3.4s" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlal_high_u8 (uint16x8_t a, uint8x16_t b, uint8x16_t c) +{ + uint16x8_t result; + __asm__ ("umlal2 %0.8h,%2.16b,%3.16b" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlal_high_u16 (uint32x4_t a, uint16x8_t b, uint16x8_t c) +{ + uint32x4_t result; + __asm__ ("umlal2 %0.4s,%2.8h,%3.8h" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlal_high_u32 (uint64x2_t a, uint32x4_t b, uint32x4_t c) +{ + uint64x2_t result; + __asm__ ("umlal2 %0.2d,%2.4s,%3.4s" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +#define vmlal_lane_s16(a, b, c, d) \ + __extension__ \ + ({ \ + int16x4_t c_ = (c); \ + int16x4_t b_ = (b); \ + int32x4_t a_ = (a); \ + int32x4_t result; \ + __asm__ ("smlal %0.4s,%2.4h,%3.h[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "x"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmlal_lane_s32(a, b, c, d) \ + __extension__ \ + ({ \ + int32x2_t c_ = (c); \ + int32x2_t b_ = (b); \ + int64x2_t a_ = (a); \ + int64x2_t result; \ + __asm__ ("smlal %0.2d,%2.2s,%3.s[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "w"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmlal_lane_u16(a, b, c, d) \ + __extension__ \ + ({ \ + uint16x4_t c_ = (c); \ + uint16x4_t b_ = (b); \ + uint32x4_t a_ = (a); \ + uint32x4_t result; \ + __asm__ ("umlal %0.4s,%2.4h,%3.h[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "x"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmlal_lane_u32(a, b, c, d) \ + __extension__ \ + ({ \ + uint32x2_t c_ = (c); \ + uint32x2_t b_ = (b); \ + uint64x2_t a_ = (a); \ + uint64x2_t result; \ + __asm__ ("umlal %0.2d, %2.2s, %3.s[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "w"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmlal_laneq_s16(a, b, c, d) \ + __extension__ \ + ({ \ + int16x8_t c_ = (c); \ + int16x4_t b_ = (b); \ + int32x4_t a_ = (a); \ + int32x4_t result; \ + __asm__ ("smlal %0.4s, %2.4h, %3.h[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "x"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmlal_laneq_s32(a, b, c, d) \ + __extension__ \ + ({ \ + int32x4_t c_ = (c); \ + int32x2_t b_ = (b); \ + int64x2_t a_ = (a); \ + int64x2_t result; \ + __asm__ ("smlal %0.2d, %2.2s, %3.s[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "w"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmlal_laneq_u16(a, b, c, d) \ + __extension__ \ + ({ \ + uint16x8_t c_ = (c); \ + uint16x4_t b_ = (b); \ + uint32x4_t a_ = (a); \ + uint32x4_t result; \ + __asm__ ("umlal %0.4s, %2.4h, %3.h[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "x"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmlal_laneq_u32(a, b, c, d) \ + __extension__ \ + ({ \ + uint32x4_t c_ = (c); \ + uint32x2_t b_ = (b); \ + uint64x2_t a_ = (a); \ + uint64x2_t result; \ + __asm__ ("umlal %0.2d, %2.2s, %3.s[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "w"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlal_n_s16 (int32x4_t a, int16x4_t b, int16_t c) +{ + int32x4_t result; + __asm__ ("smlal %0.4s,%2.4h,%3.h[0]" + : "=w"(result) + : "0"(a), "w"(b), "x"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlal_n_s32 (int64x2_t a, int32x2_t b, int32_t c) +{ + int64x2_t result; + __asm__ ("smlal %0.2d,%2.2s,%3.s[0]" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlal_n_u16 (uint32x4_t a, uint16x4_t b, uint16_t c) +{ + uint32x4_t result; + __asm__ ("umlal %0.4s,%2.4h,%3.h[0]" + : "=w"(result) + : "0"(a), "w"(b), "x"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlal_n_u32 (uint64x2_t a, uint32x2_t b, uint32_t c) +{ + uint64x2_t result; + __asm__ ("umlal %0.2d,%2.2s,%3.s[0]" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlal_s8 (int16x8_t a, int8x8_t b, int8x8_t c) +{ + int16x8_t result; + __asm__ ("smlal %0.8h,%2.8b,%3.8b" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlal_s16 (int32x4_t a, int16x4_t b, int16x4_t c) +{ + int32x4_t result; + __asm__ ("smlal %0.4s,%2.4h,%3.4h" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlal_s32 (int64x2_t a, int32x2_t b, int32x2_t c) +{ + int64x2_t result; + __asm__ ("smlal %0.2d,%2.2s,%3.2s" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlal_u8 (uint16x8_t a, uint8x8_t b, uint8x8_t c) +{ + uint16x8_t result; + __asm__ ("umlal %0.8h,%2.8b,%3.8b" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlal_u16 (uint32x4_t a, uint16x4_t b, uint16x4_t c) +{ + uint32x4_t result; + __asm__ ("umlal %0.4s,%2.4h,%3.4h" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlal_u32 (uint64x2_t a, uint32x2_t b, uint32x2_t c) +{ + uint64x2_t result; + __asm__ ("umlal %0.2d,%2.2s,%3.2s" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlaq_n_f32 (float32x4_t a, float32x4_t b, float32_t c) +{ + float32x4_t result; + float32x4_t t1; + __asm__ ("fmul %1.4s, %3.4s, %4.s[0]; fadd %0.4s, %0.4s, %1.4s" + : "=w"(result), "=w"(t1) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlaq_n_s16 (int16x8_t a, int16x8_t b, int16_t c) +{ + int16x8_t result; + __asm__ ("mla %0.8h,%2.8h,%3.h[0]" + : "=w"(result) + : "0"(a), "w"(b), "x"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlaq_n_s32 (int32x4_t a, int32x4_t b, int32_t c) +{ + int32x4_t result; + __asm__ ("mla %0.4s,%2.4s,%3.s[0]" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlaq_n_u16 (uint16x8_t a, uint16x8_t b, uint16_t c) +{ + uint16x8_t result; + __asm__ ("mla %0.8h,%2.8h,%3.h[0]" + : "=w"(result) + : "0"(a), "w"(b), "x"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlaq_n_u32 (uint32x4_t a, uint32x4_t b, uint32_t c) +{ + uint32x4_t result; + __asm__ ("mla %0.4s,%2.4s,%3.s[0]" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlaq_s8 (int8x16_t a, int8x16_t b, int8x16_t c) +{ + int8x16_t result; + __asm__ ("mla %0.16b, %2.16b, %3.16b" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlaq_s16 (int16x8_t a, int16x8_t b, int16x8_t c) +{ + int16x8_t result; + __asm__ ("mla %0.8h, %2.8h, %3.8h" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlaq_s32 (int32x4_t a, int32x4_t b, int32x4_t c) +{ + int32x4_t result; + __asm__ ("mla %0.4s, %2.4s, %3.4s" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlaq_u8 (uint8x16_t a, uint8x16_t b, uint8x16_t c) +{ + uint8x16_t result; + __asm__ ("mla %0.16b, %2.16b, %3.16b" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlaq_u16 (uint16x8_t a, uint16x8_t b, uint16x8_t c) +{ + uint16x8_t result; + __asm__ ("mla %0.8h, %2.8h, %3.8h" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlaq_u32 (uint32x4_t a, uint32x4_t b, uint32x4_t c) +{ + uint32x4_t result; + __asm__ ("mla %0.4s, %2.4s, %3.4s" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmls_n_f32 (float32x2_t a, float32x2_t b, float32_t c) +{ + float32x2_t result; + float32x2_t t1; + __asm__ ("fmul %1.2s, %3.2s, %4.s[0]; fsub %0.2s, %0.2s, %1.2s" + : "=w"(result), "=w"(t1) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmls_n_s16 (int16x4_t a, int16x4_t b, int16_t c) +{ + int16x4_t result; + __asm__ ("mls %0.4h, %2.4h, %3.h[0]" + : "=w"(result) + : "0"(a), "w"(b), "x"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmls_n_s32 (int32x2_t a, int32x2_t b, int32_t c) +{ + int32x2_t result; + __asm__ ("mls %0.2s, %2.2s, %3.s[0]" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmls_n_u16 (uint16x4_t a, uint16x4_t b, uint16_t c) +{ + uint16x4_t result; + __asm__ ("mls %0.4h, %2.4h, %3.h[0]" + : "=w"(result) + : "0"(a), "w"(b), "x"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmls_n_u32 (uint32x2_t a, uint32x2_t b, uint32_t c) +{ + uint32x2_t result; + __asm__ ("mls %0.2s, %2.2s, %3.s[0]" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmls_s8 (int8x8_t a, int8x8_t b, int8x8_t c) +{ + int8x8_t result; + __asm__ ("mls %0.8b,%2.8b,%3.8b" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmls_s16 (int16x4_t a, int16x4_t b, int16x4_t c) +{ + int16x4_t result; + __asm__ ("mls %0.4h,%2.4h,%3.4h" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmls_s32 (int32x2_t a, int32x2_t b, int32x2_t c) +{ + int32x2_t result; + __asm__ ("mls %0.2s,%2.2s,%3.2s" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmls_u8 (uint8x8_t a, uint8x8_t b, uint8x8_t c) +{ + uint8x8_t result; + __asm__ ("mls %0.8b,%2.8b,%3.8b" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmls_u16 (uint16x4_t a, uint16x4_t b, uint16x4_t c) +{ + uint16x4_t result; + __asm__ ("mls %0.4h,%2.4h,%3.4h" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmls_u32 (uint32x2_t a, uint32x2_t b, uint32x2_t c) +{ + uint32x2_t result; + __asm__ ("mls %0.2s,%2.2s,%3.2s" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +#define vmlsl_high_lane_s16(a, b, c, d) \ + __extension__ \ + ({ \ + int16x4_t c_ = (c); \ + int16x8_t b_ = (b); \ + int32x4_t a_ = (a); \ + int32x4_t result; \ + __asm__ ("smlsl2 %0.4s, %2.8h, %3.h[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "x"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmlsl_high_lane_s32(a, b, c, d) \ + __extension__ \ + ({ \ + int32x2_t c_ = (c); \ + int32x4_t b_ = (b); \ + int64x2_t a_ = (a); \ + int64x2_t result; \ + __asm__ ("smlsl2 %0.2d, %2.4s, %3.s[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "w"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmlsl_high_lane_u16(a, b, c, d) \ + __extension__ \ + ({ \ + uint16x4_t c_ = (c); \ + uint16x8_t b_ = (b); \ + uint32x4_t a_ = (a); \ + uint32x4_t result; \ + __asm__ ("umlsl2 %0.4s, %2.8h, %3.h[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "x"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmlsl_high_lane_u32(a, b, c, d) \ + __extension__ \ + ({ \ + uint32x2_t c_ = (c); \ + uint32x4_t b_ = (b); \ + uint64x2_t a_ = (a); \ + uint64x2_t result; \ + __asm__ ("umlsl2 %0.2d, %2.4s, %3.s[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "w"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmlsl_high_laneq_s16(a, b, c, d) \ + __extension__ \ + ({ \ + int16x8_t c_ = (c); \ + int16x8_t b_ = (b); \ + int32x4_t a_ = (a); \ + int32x4_t result; \ + __asm__ ("smlsl2 %0.4s, %2.8h, %3.h[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "x"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmlsl_high_laneq_s32(a, b, c, d) \ + __extension__ \ + ({ \ + int32x4_t c_ = (c); \ + int32x4_t b_ = (b); \ + int64x2_t a_ = (a); \ + int64x2_t result; \ + __asm__ ("smlsl2 %0.2d, %2.4s, %3.s[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "w"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmlsl_high_laneq_u16(a, b, c, d) \ + __extension__ \ + ({ \ + uint16x8_t c_ = (c); \ + uint16x8_t b_ = (b); \ + uint32x4_t a_ = (a); \ + uint32x4_t result; \ + __asm__ ("umlsl2 %0.4s, %2.8h, %3.h[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "x"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmlsl_high_laneq_u32(a, b, c, d) \ + __extension__ \ + ({ \ + uint32x4_t c_ = (c); \ + uint32x4_t b_ = (b); \ + uint64x2_t a_ = (a); \ + uint64x2_t result; \ + __asm__ ("umlsl2 %0.2d, %2.4s, %3.s[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "w"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsl_high_n_s16 (int32x4_t a, int16x8_t b, int16_t c) +{ + int32x4_t result; + __asm__ ("smlsl2 %0.4s, %2.8h, %3.h[0]" + : "=w"(result) + : "0"(a), "w"(b), "x"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsl_high_n_s32 (int64x2_t a, int32x4_t b, int32_t c) +{ + int64x2_t result; + __asm__ ("smlsl2 %0.2d, %2.4s, %3.s[0]" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsl_high_n_u16 (uint32x4_t a, uint16x8_t b, uint16_t c) +{ + uint32x4_t result; + __asm__ ("umlsl2 %0.4s, %2.8h, %3.h[0]" + : "=w"(result) + : "0"(a), "w"(b), "x"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsl_high_n_u32 (uint64x2_t a, uint32x4_t b, uint32_t c) +{ + uint64x2_t result; + __asm__ ("umlsl2 %0.2d, %2.4s, %3.s[0]" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsl_high_s8 (int16x8_t a, int8x16_t b, int8x16_t c) +{ + int16x8_t result; + __asm__ ("smlsl2 %0.8h,%2.16b,%3.16b" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsl_high_s16 (int32x4_t a, int16x8_t b, int16x8_t c) +{ + int32x4_t result; + __asm__ ("smlsl2 %0.4s,%2.8h,%3.8h" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsl_high_s32 (int64x2_t a, int32x4_t b, int32x4_t c) +{ + int64x2_t result; + __asm__ ("smlsl2 %0.2d,%2.4s,%3.4s" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsl_high_u8 (uint16x8_t a, uint8x16_t b, uint8x16_t c) +{ + uint16x8_t result; + __asm__ ("umlsl2 %0.8h,%2.16b,%3.16b" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsl_high_u16 (uint32x4_t a, uint16x8_t b, uint16x8_t c) +{ + uint32x4_t result; + __asm__ ("umlsl2 %0.4s,%2.8h,%3.8h" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsl_high_u32 (uint64x2_t a, uint32x4_t b, uint32x4_t c) +{ + uint64x2_t result; + __asm__ ("umlsl2 %0.2d,%2.4s,%3.4s" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +#define vmlsl_lane_s16(a, b, c, d) \ + __extension__ \ + ({ \ + int16x4_t c_ = (c); \ + int16x4_t b_ = (b); \ + int32x4_t a_ = (a); \ + int32x4_t result; \ + __asm__ ("smlsl %0.4s, %2.4h, %3.h[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "x"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmlsl_lane_s32(a, b, c, d) \ + __extension__ \ + ({ \ + int32x2_t c_ = (c); \ + int32x2_t b_ = (b); \ + int64x2_t a_ = (a); \ + int64x2_t result; \ + __asm__ ("smlsl %0.2d, %2.2s, %3.s[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "w"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmlsl_lane_u16(a, b, c, d) \ + __extension__ \ + ({ \ + uint16x4_t c_ = (c); \ + uint16x4_t b_ = (b); \ + uint32x4_t a_ = (a); \ + uint32x4_t result; \ + __asm__ ("umlsl %0.4s, %2.4h, %3.h[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "x"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmlsl_lane_u32(a, b, c, d) \ + __extension__ \ + ({ \ + uint32x2_t c_ = (c); \ + uint32x2_t b_ = (b); \ + uint64x2_t a_ = (a); \ + uint64x2_t result; \ + __asm__ ("umlsl %0.2d, %2.2s, %3.s[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "w"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmlsl_laneq_s16(a, b, c, d) \ + __extension__ \ + ({ \ + int16x8_t c_ = (c); \ + int16x4_t b_ = (b); \ + int32x4_t a_ = (a); \ + int32x4_t result; \ + __asm__ ("smlsl %0.4s, %2.4h, %3.h[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "x"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmlsl_laneq_s32(a, b, c, d) \ + __extension__ \ + ({ \ + int32x4_t c_ = (c); \ + int32x2_t b_ = (b); \ + int64x2_t a_ = (a); \ + int64x2_t result; \ + __asm__ ("smlsl %0.2d, %2.2s, %3.s[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "w"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmlsl_laneq_u16(a, b, c, d) \ + __extension__ \ + ({ \ + uint16x8_t c_ = (c); \ + uint16x4_t b_ = (b); \ + uint32x4_t a_ = (a); \ + uint32x4_t result; \ + __asm__ ("umlsl %0.4s, %2.4h, %3.h[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "x"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmlsl_laneq_u32(a, b, c, d) \ + __extension__ \ + ({ \ + uint32x4_t c_ = (c); \ + uint32x2_t b_ = (b); \ + uint64x2_t a_ = (a); \ + uint64x2_t result; \ + __asm__ ("umlsl %0.2d, %2.2s, %3.s[%4]" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "w"(c_), "i"(d) \ + : /* No clobbers */); \ + result; \ + }) + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsl_n_s16 (int32x4_t a, int16x4_t b, int16_t c) +{ + int32x4_t result; + __asm__ ("smlsl %0.4s, %2.4h, %3.h[0]" + : "=w"(result) + : "0"(a), "w"(b), "x"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsl_n_s32 (int64x2_t a, int32x2_t b, int32_t c) +{ + int64x2_t result; + __asm__ ("smlsl %0.2d, %2.2s, %3.s[0]" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsl_n_u16 (uint32x4_t a, uint16x4_t b, uint16_t c) +{ + uint32x4_t result; + __asm__ ("umlsl %0.4s, %2.4h, %3.h[0]" + : "=w"(result) + : "0"(a), "w"(b), "x"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsl_n_u32 (uint64x2_t a, uint32x2_t b, uint32_t c) +{ + uint64x2_t result; + __asm__ ("umlsl %0.2d, %2.2s, %3.s[0]" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsl_s8 (int16x8_t a, int8x8_t b, int8x8_t c) +{ + int16x8_t result; + __asm__ ("smlsl %0.8h, %2.8b, %3.8b" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsl_s16 (int32x4_t a, int16x4_t b, int16x4_t c) +{ + int32x4_t result; + __asm__ ("smlsl %0.4s, %2.4h, %3.4h" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsl_s32 (int64x2_t a, int32x2_t b, int32x2_t c) +{ + int64x2_t result; + __asm__ ("smlsl %0.2d, %2.2s, %3.2s" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsl_u8 (uint16x8_t a, uint8x8_t b, uint8x8_t c) +{ + uint16x8_t result; + __asm__ ("umlsl %0.8h, %2.8b, %3.8b" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsl_u16 (uint32x4_t a, uint16x4_t b, uint16x4_t c) +{ + uint32x4_t result; + __asm__ ("umlsl %0.4s, %2.4h, %3.4h" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsl_u32 (uint64x2_t a, uint32x2_t b, uint32x2_t c) +{ + uint64x2_t result; + __asm__ ("umlsl %0.2d, %2.2s, %3.2s" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsq_n_f32 (float32x4_t a, float32x4_t b, float32_t c) +{ + float32x4_t result; + float32x4_t t1; + __asm__ ("fmul %1.4s, %3.4s, %4.s[0]; fsub %0.4s, %0.4s, %1.4s" + : "=w"(result), "=w"(t1) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsq_n_s16 (int16x8_t a, int16x8_t b, int16_t c) +{ + int16x8_t result; + __asm__ ("mls %0.8h, %2.8h, %3.h[0]" + : "=w"(result) + : "0"(a), "w"(b), "x"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsq_n_s32 (int32x4_t a, int32x4_t b, int32_t c) +{ + int32x4_t result; + __asm__ ("mls %0.4s, %2.4s, %3.s[0]" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsq_n_u16 (uint16x8_t a, uint16x8_t b, uint16_t c) +{ + uint16x8_t result; + __asm__ ("mls %0.8h, %2.8h, %3.h[0]" + : "=w"(result) + : "0"(a), "w"(b), "x"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsq_n_u32 (uint32x4_t a, uint32x4_t b, uint32_t c) +{ + uint32x4_t result; + __asm__ ("mls %0.4s, %2.4s, %3.s[0]" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsq_s8 (int8x16_t a, int8x16_t b, int8x16_t c) +{ + int8x16_t result; + __asm__ ("mls %0.16b,%2.16b,%3.16b" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsq_s16 (int16x8_t a, int16x8_t b, int16x8_t c) +{ + int16x8_t result; + __asm__ ("mls %0.8h,%2.8h,%3.8h" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsq_s32 (int32x4_t a, int32x4_t b, int32x4_t c) +{ + int32x4_t result; + __asm__ ("mls %0.4s,%2.4s,%3.4s" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsq_u8 (uint8x16_t a, uint8x16_t b, uint8x16_t c) +{ + uint8x16_t result; + __asm__ ("mls %0.16b,%2.16b,%3.16b" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsq_u16 (uint16x8_t a, uint16x8_t b, uint16x8_t c) +{ + uint16x8_t result; + __asm__ ("mls %0.8h,%2.8h,%3.8h" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsq_u32 (uint32x4_t a, uint32x4_t b, uint32x4_t c) +{ + uint32x4_t result; + __asm__ ("mls %0.4s,%2.4s,%3.4s" + : "=w"(result) + : "0"(a), "w"(b), "w"(c) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovl_high_s8 (int8x16_t a) +{ + int16x8_t result; + __asm__ ("sshll2 %0.8h,%1.16b,#0" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovl_high_s16 (int16x8_t a) +{ + int32x4_t result; + __asm__ ("sshll2 %0.4s,%1.8h,#0" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovl_high_s32 (int32x4_t a) +{ + int64x2_t result; + __asm__ ("sshll2 %0.2d,%1.4s,#0" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovl_high_u8 (uint8x16_t a) +{ + uint16x8_t result; + __asm__ ("ushll2 %0.8h,%1.16b,#0" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovl_high_u16 (uint16x8_t a) +{ + uint32x4_t result; + __asm__ ("ushll2 %0.4s,%1.8h,#0" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovl_high_u32 (uint32x4_t a) +{ + uint64x2_t result; + __asm__ ("ushll2 %0.2d,%1.4s,#0" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovl_s8 (int8x8_t a) +{ + int16x8_t result; + __asm__ ("sshll %0.8h,%1.8b,#0" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovl_s16 (int16x4_t a) +{ + int32x4_t result; + __asm__ ("sshll %0.4s,%1.4h,#0" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovl_s32 (int32x2_t a) +{ + int64x2_t result; + __asm__ ("sshll %0.2d,%1.2s,#0" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovl_u8 (uint8x8_t a) +{ + uint16x8_t result; + __asm__ ("ushll %0.8h,%1.8b,#0" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovl_u16 (uint16x4_t a) +{ + uint32x4_t result; + __asm__ ("ushll %0.4s,%1.4h,#0" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovl_u32 (uint32x2_t a) +{ + uint64x2_t result; + __asm__ ("ushll %0.2d,%1.2s,#0" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovn_high_s16 (int8x8_t a, int16x8_t b) +{ + int8x16_t result = vcombine_s8 (a, vcreate_s8 (__AARCH64_UINT64_C (0x0))); + __asm__ ("xtn2 %0.16b,%1.8h" + : "+w"(result) + : "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovn_high_s32 (int16x4_t a, int32x4_t b) +{ + int16x8_t result = vcombine_s16 (a, vcreate_s16 (__AARCH64_UINT64_C (0x0))); + __asm__ ("xtn2 %0.8h,%1.4s" + : "+w"(result) + : "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovn_high_s64 (int32x2_t a, int64x2_t b) +{ + int32x4_t result = vcombine_s32 (a, vcreate_s32 (__AARCH64_UINT64_C (0x0))); + __asm__ ("xtn2 %0.4s,%1.2d" + : "+w"(result) + : "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovn_high_u16 (uint8x8_t a, uint16x8_t b) +{ + uint8x16_t result = vcombine_u8 (a, vcreate_u8 (__AARCH64_UINT64_C (0x0))); + __asm__ ("xtn2 %0.16b,%1.8h" + : "+w"(result) + : "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovn_high_u32 (uint16x4_t a, uint32x4_t b) +{ + uint16x8_t result = vcombine_u16 (a, vcreate_u16 (__AARCH64_UINT64_C (0x0))); + __asm__ ("xtn2 %0.8h,%1.4s" + : "+w"(result) + : "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovn_high_u64 (uint32x2_t a, uint64x2_t b) +{ + uint32x4_t result = vcombine_u32 (a, vcreate_u32 (__AARCH64_UINT64_C (0x0))); + __asm__ ("xtn2 %0.4s,%1.2d" + : "+w"(result) + : "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovn_s16 (int16x8_t a) +{ + int8x8_t result; + __asm__ ("xtn %0.8b,%1.8h" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovn_s32 (int32x4_t a) +{ + int16x4_t result; + __asm__ ("xtn %0.4h,%1.4s" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovn_s64 (int64x2_t a) +{ + int32x2_t result; + __asm__ ("xtn %0.2s,%1.2d" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovn_u16 (uint16x8_t a) +{ + uint8x8_t result; + __asm__ ("xtn %0.8b,%1.8h" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovn_u32 (uint32x4_t a) +{ + uint16x4_t result; + __asm__ ("xtn %0.4h,%1.4s" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovn_u64 (uint64x2_t a) +{ + uint32x2_t result; + __asm__ ("xtn %0.2s,%1.2d" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +#define vmull_high_lane_s16(a, b, c) \ + __extension__ \ + ({ \ + int16x4_t b_ = (b); \ + int16x8_t a_ = (a); \ + int32x4_t result; \ + __asm__ ("smull2 %0.4s, %1.8h, %2.h[%3]" \ + : "=w"(result) \ + : "w"(a_), "x"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmull_high_lane_s32(a, b, c) \ + __extension__ \ + ({ \ + int32x2_t b_ = (b); \ + int32x4_t a_ = (a); \ + int64x2_t result; \ + __asm__ ("smull2 %0.2d, %1.4s, %2.s[%3]" \ + : "=w"(result) \ + : "w"(a_), "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmull_high_lane_u16(a, b, c) \ + __extension__ \ + ({ \ + uint16x4_t b_ = (b); \ + uint16x8_t a_ = (a); \ + uint32x4_t result; \ + __asm__ ("umull2 %0.4s, %1.8h, %2.h[%3]" \ + : "=w"(result) \ + : "w"(a_), "x"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmull_high_lane_u32(a, b, c) \ + __extension__ \ + ({ \ + uint32x2_t b_ = (b); \ + uint32x4_t a_ = (a); \ + uint64x2_t result; \ + __asm__ ("umull2 %0.2d, %1.4s, %2.s[%3]" \ + : "=w"(result) \ + : "w"(a_), "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmull_high_laneq_s16(a, b, c) \ + __extension__ \ + ({ \ + int16x8_t b_ = (b); \ + int16x8_t a_ = (a); \ + int32x4_t result; \ + __asm__ ("smull2 %0.4s, %1.8h, %2.h[%3]" \ + : "=w"(result) \ + : "w"(a_), "x"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmull_high_laneq_s32(a, b, c) \ + __extension__ \ + ({ \ + int32x4_t b_ = (b); \ + int32x4_t a_ = (a); \ + int64x2_t result; \ + __asm__ ("smull2 %0.2d, %1.4s, %2.s[%3]" \ + : "=w"(result) \ + : "w"(a_), "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmull_high_laneq_u16(a, b, c) \ + __extension__ \ + ({ \ + uint16x8_t b_ = (b); \ + uint16x8_t a_ = (a); \ + uint32x4_t result; \ + __asm__ ("umull2 %0.4s, %1.8h, %2.h[%3]" \ + : "=w"(result) \ + : "w"(a_), "x"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmull_high_laneq_u32(a, b, c) \ + __extension__ \ + ({ \ + uint32x4_t b_ = (b); \ + uint32x4_t a_ = (a); \ + uint64x2_t result; \ + __asm__ ("umull2 %0.2d, %1.4s, %2.s[%3]" \ + : "=w"(result) \ + : "w"(a_), "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmull_high_n_s16 (int16x8_t a, int16_t b) +{ + int32x4_t result; + __asm__ ("smull2 %0.4s,%1.8h,%2.h[0]" + : "=w"(result) + : "w"(a), "x"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmull_high_n_s32 (int32x4_t a, int32_t b) +{ + int64x2_t result; + __asm__ ("smull2 %0.2d,%1.4s,%2.s[0]" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmull_high_n_u16 (uint16x8_t a, uint16_t b) +{ + uint32x4_t result; + __asm__ ("umull2 %0.4s,%1.8h,%2.h[0]" + : "=w"(result) + : "w"(a), "x"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmull_high_n_u32 (uint32x4_t a, uint32_t b) +{ + uint64x2_t result; + __asm__ ("umull2 %0.2d,%1.4s,%2.s[0]" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmull_high_p8 (poly8x16_t a, poly8x16_t b) +{ + poly16x8_t result; + __asm__ ("pmull2 %0.8h,%1.16b,%2.16b" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmull_high_s8 (int8x16_t a, int8x16_t b) +{ + int16x8_t result; + __asm__ ("smull2 %0.8h,%1.16b,%2.16b" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmull_high_s16 (int16x8_t a, int16x8_t b) +{ + int32x4_t result; + __asm__ ("smull2 %0.4s,%1.8h,%2.8h" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmull_high_s32 (int32x4_t a, int32x4_t b) +{ + int64x2_t result; + __asm__ ("smull2 %0.2d,%1.4s,%2.4s" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmull_high_u8 (uint8x16_t a, uint8x16_t b) +{ + uint16x8_t result; + __asm__ ("umull2 %0.8h,%1.16b,%2.16b" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmull_high_u16 (uint16x8_t a, uint16x8_t b) +{ + uint32x4_t result; + __asm__ ("umull2 %0.4s,%1.8h,%2.8h" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmull_high_u32 (uint32x4_t a, uint32x4_t b) +{ + uint64x2_t result; + __asm__ ("umull2 %0.2d,%1.4s,%2.4s" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +#define vmull_lane_s16(a, b, c) \ + __extension__ \ + ({ \ + int16x4_t b_ = (b); \ + int16x4_t a_ = (a); \ + int32x4_t result; \ + __asm__ ("smull %0.4s,%1.4h,%2.h[%3]" \ + : "=w"(result) \ + : "w"(a_), "x"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmull_lane_s32(a, b, c) \ + __extension__ \ + ({ \ + int32x2_t b_ = (b); \ + int32x2_t a_ = (a); \ + int64x2_t result; \ + __asm__ ("smull %0.2d,%1.2s,%2.s[%3]" \ + : "=w"(result) \ + : "w"(a_), "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmull_lane_u16(a, b, c) \ + __extension__ \ + ({ \ + uint16x4_t b_ = (b); \ + uint16x4_t a_ = (a); \ + uint32x4_t result; \ + __asm__ ("umull %0.4s,%1.4h,%2.h[%3]" \ + : "=w"(result) \ + : "w"(a_), "x"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmull_lane_u32(a, b, c) \ + __extension__ \ + ({ \ + uint32x2_t b_ = (b); \ + uint32x2_t a_ = (a); \ + uint64x2_t result; \ + __asm__ ("umull %0.2d, %1.2s, %2.s[%3]" \ + : "=w"(result) \ + : "w"(a_), "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmull_laneq_s16(a, b, c) \ + __extension__ \ + ({ \ + int16x8_t b_ = (b); \ + int16x4_t a_ = (a); \ + int32x4_t result; \ + __asm__ ("smull %0.4s, %1.4h, %2.h[%3]" \ + : "=w"(result) \ + : "w"(a_), "x"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmull_laneq_s32(a, b, c) \ + __extension__ \ + ({ \ + int32x4_t b_ = (b); \ + int32x2_t a_ = (a); \ + int64x2_t result; \ + __asm__ ("smull %0.2d, %1.2s, %2.s[%3]" \ + : "=w"(result) \ + : "w"(a_), "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmull_laneq_u16(a, b, c) \ + __extension__ \ + ({ \ + uint16x8_t b_ = (b); \ + uint16x4_t a_ = (a); \ + uint32x4_t result; \ + __asm__ ("umull %0.4s, %1.4h, %2.h[%3]" \ + : "=w"(result) \ + : "w"(a_), "x"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vmull_laneq_u32(a, b, c) \ + __extension__ \ + ({ \ + uint32x4_t b_ = (b); \ + uint32x2_t a_ = (a); \ + uint64x2_t result; \ + __asm__ ("umull %0.2d, %1.2s, %2.s[%3]" \ + : "=w"(result) \ + : "w"(a_), "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmull_n_s16 (int16x4_t a, int16_t b) +{ + int32x4_t result; + __asm__ ("smull %0.4s,%1.4h,%2.h[0]" + : "=w"(result) + : "w"(a), "x"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmull_n_s32 (int32x2_t a, int32_t b) +{ + int64x2_t result; + __asm__ ("smull %0.2d,%1.2s,%2.s[0]" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmull_n_u16 (uint16x4_t a, uint16_t b) +{ + uint32x4_t result; + __asm__ ("umull %0.4s,%1.4h,%2.h[0]" + : "=w"(result) + : "w"(a), "x"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmull_n_u32 (uint32x2_t a, uint32_t b) +{ + uint64x2_t result; + __asm__ ("umull %0.2d,%1.2s,%2.s[0]" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmull_p8 (poly8x8_t a, poly8x8_t b) +{ + poly16x8_t result; + __asm__ ("pmull %0.8h, %1.8b, %2.8b" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmull_s8 (int8x8_t a, int8x8_t b) +{ + int16x8_t result; + __asm__ ("smull %0.8h, %1.8b, %2.8b" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmull_s16 (int16x4_t a, int16x4_t b) +{ + int32x4_t result; + __asm__ ("smull %0.4s, %1.4h, %2.4h" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmull_s32 (int32x2_t a, int32x2_t b) +{ + int64x2_t result; + __asm__ ("smull %0.2d, %1.2s, %2.2s" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmull_u8 (uint8x8_t a, uint8x8_t b) +{ + uint16x8_t result; + __asm__ ("umull %0.8h, %1.8b, %2.8b" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmull_u16 (uint16x4_t a, uint16x4_t b) +{ + uint32x4_t result; + __asm__ ("umull %0.4s, %1.4h, %2.4h" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmull_u32 (uint32x2_t a, uint32x2_t b) +{ + uint64x2_t result; + __asm__ ("umull %0.2d, %1.2s, %2.2s" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpadal_s8 (int16x4_t a, int8x8_t b) +{ + int16x4_t result; + __asm__ ("sadalp %0.4h,%2.8b" + : "=w"(result) + : "0"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpadal_s16 (int32x2_t a, int16x4_t b) +{ + int32x2_t result; + __asm__ ("sadalp %0.2s,%2.4h" + : "=w"(result) + : "0"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpadal_s32 (int64x1_t a, int32x2_t b) +{ + int64x1_t result; + __asm__ ("sadalp %0.1d,%2.2s" + : "=w"(result) + : "0"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpadal_u8 (uint16x4_t a, uint8x8_t b) +{ + uint16x4_t result; + __asm__ ("uadalp %0.4h,%2.8b" + : "=w"(result) + : "0"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpadal_u16 (uint32x2_t a, uint16x4_t b) +{ + uint32x2_t result; + __asm__ ("uadalp %0.2s,%2.4h" + : "=w"(result) + : "0"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpadal_u32 (uint64x1_t a, uint32x2_t b) +{ + uint64x1_t result; + __asm__ ("uadalp %0.1d,%2.2s" + : "=w"(result) + : "0"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpadalq_s8 (int16x8_t a, int8x16_t b) +{ + int16x8_t result; + __asm__ ("sadalp %0.8h,%2.16b" + : "=w"(result) + : "0"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpadalq_s16 (int32x4_t a, int16x8_t b) +{ + int32x4_t result; + __asm__ ("sadalp %0.4s,%2.8h" + : "=w"(result) + : "0"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpadalq_s32 (int64x2_t a, int32x4_t b) +{ + int64x2_t result; + __asm__ ("sadalp %0.2d,%2.4s" + : "=w"(result) + : "0"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpadalq_u8 (uint16x8_t a, uint8x16_t b) +{ + uint16x8_t result; + __asm__ ("uadalp %0.8h,%2.16b" + : "=w"(result) + : "0"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpadalq_u16 (uint32x4_t a, uint16x8_t b) +{ + uint32x4_t result; + __asm__ ("uadalp %0.4s,%2.8h" + : "=w"(result) + : "0"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpadalq_u32 (uint64x2_t a, uint32x4_t b) +{ + uint64x2_t result; + __asm__ ("uadalp %0.2d,%2.4s" + : "=w"(result) + : "0"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpaddl_s8 (int8x8_t a) +{ + int16x4_t result; + __asm__ ("saddlp %0.4h,%1.8b" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpaddl_s16 (int16x4_t a) +{ + int32x2_t result; + __asm__ ("saddlp %0.2s,%1.4h" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpaddl_s32 (int32x2_t a) +{ + int64x1_t result; + __asm__ ("saddlp %0.1d,%1.2s" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpaddl_u8 (uint8x8_t a) +{ + uint16x4_t result; + __asm__ ("uaddlp %0.4h,%1.8b" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpaddl_u16 (uint16x4_t a) +{ + uint32x2_t result; + __asm__ ("uaddlp %0.2s,%1.4h" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpaddl_u32 (uint32x2_t a) +{ + uint64x1_t result; + __asm__ ("uaddlp %0.1d,%1.2s" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpaddlq_s8 (int8x16_t a) +{ + int16x8_t result; + __asm__ ("saddlp %0.8h,%1.16b" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpaddlq_s16 (int16x8_t a) +{ + int32x4_t result; + __asm__ ("saddlp %0.4s,%1.8h" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpaddlq_s32 (int32x4_t a) +{ + int64x2_t result; + __asm__ ("saddlp %0.2d,%1.4s" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpaddlq_u8 (uint8x16_t a) +{ + uint16x8_t result; + __asm__ ("uaddlp %0.8h,%1.16b" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpaddlq_u16 (uint16x8_t a) +{ + uint32x4_t result; + __asm__ ("uaddlp %0.4s,%1.8h" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpaddlq_u32 (uint32x4_t a) +{ + uint64x2_t result; + __asm__ ("uaddlp %0.2d,%1.4s" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpaddq_s8 (int8x16_t a, int8x16_t b) +{ + int8x16_t result; + __asm__ ("addp %0.16b,%1.16b,%2.16b" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpaddq_s16 (int16x8_t a, int16x8_t b) +{ + int16x8_t result; + __asm__ ("addp %0.8h,%1.8h,%2.8h" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpaddq_s32 (int32x4_t a, int32x4_t b) +{ + int32x4_t result; + __asm__ ("addp %0.4s,%1.4s,%2.4s" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpaddq_s64 (int64x2_t a, int64x2_t b) +{ + int64x2_t result; + __asm__ ("addp %0.2d,%1.2d,%2.2d" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpaddq_u8 (uint8x16_t a, uint8x16_t b) +{ + uint8x16_t result; + __asm__ ("addp %0.16b,%1.16b,%2.16b" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpaddq_u16 (uint16x8_t a, uint16x8_t b) +{ + uint16x8_t result; + __asm__ ("addp %0.8h,%1.8h,%2.8h" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpaddq_u32 (uint32x4_t a, uint32x4_t b) +{ + uint32x4_t result; + __asm__ ("addp %0.4s,%1.4s,%2.4s" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpaddq_u64 (uint64x2_t a, uint64x2_t b) +{ + uint64x2_t result; + __asm__ ("addp %0.2d,%1.2d,%2.2d" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmulh_n_s16 (int16x4_t a, int16_t b) +{ + int16x4_t result; + __asm__ ("sqdmulh %0.4h,%1.4h,%2.h[0]" + : "=w"(result) + : "w"(a), "x"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmulh_n_s32 (int32x2_t a, int32_t b) +{ + int32x2_t result; + __asm__ ("sqdmulh %0.2s,%1.2s,%2.s[0]" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmulhq_n_s16 (int16x8_t a, int16_t b) +{ + int16x8_t result; + __asm__ ("sqdmulh %0.8h,%1.8h,%2.h[0]" + : "=w"(result) + : "w"(a), "x"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmulhq_n_s32 (int32x4_t a, int32_t b) +{ + int32x4_t result; + __asm__ ("sqdmulh %0.4s,%1.4s,%2.s[0]" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqmovn_high_s16 (int8x8_t a, int16x8_t b) +{ + int8x16_t result = vcombine_s8 (a, vcreate_s8 (__AARCH64_UINT64_C (0x0))); + __asm__ ("sqxtn2 %0.16b, %1.8h" + : "+w"(result) + : "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqmovn_high_s32 (int16x4_t a, int32x4_t b) +{ + int16x8_t result = vcombine_s16 (a, vcreate_s16 (__AARCH64_UINT64_C (0x0))); + __asm__ ("sqxtn2 %0.8h, %1.4s" + : "+w"(result) + : "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqmovn_high_s64 (int32x2_t a, int64x2_t b) +{ + int32x4_t result = vcombine_s32 (a, vcreate_s32 (__AARCH64_UINT64_C (0x0))); + __asm__ ("sqxtn2 %0.4s, %1.2d" + : "+w"(result) + : "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqmovn_high_u16 (uint8x8_t a, uint16x8_t b) +{ + uint8x16_t result = vcombine_u8 (a, vcreate_u8 (__AARCH64_UINT64_C (0x0))); + __asm__ ("uqxtn2 %0.16b, %1.8h" + : "+w"(result) + : "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqmovn_high_u32 (uint16x4_t a, uint32x4_t b) +{ + uint16x8_t result = vcombine_u16 (a, vcreate_u16 (__AARCH64_UINT64_C (0x0))); + __asm__ ("uqxtn2 %0.8h, %1.4s" + : "+w"(result) + : "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqmovn_high_u64 (uint32x2_t a, uint64x2_t b) +{ + uint32x4_t result = vcombine_u32 (a, vcreate_u32 (__AARCH64_UINT64_C (0x0))); + __asm__ ("uqxtn2 %0.4s, %1.2d" + : "+w"(result) + : "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqmovun_high_s16 (uint8x8_t a, int16x8_t b) +{ + uint8x16_t result = vcombine_u8 (a, vcreate_u8 (__AARCH64_UINT64_C (0x0))); + __asm__ ("sqxtun2 %0.16b, %1.8h" + : "+w"(result) + : "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqmovun_high_s32 (uint16x4_t a, int32x4_t b) +{ + uint16x8_t result = vcombine_u16 (a, vcreate_u16 (__AARCH64_UINT64_C (0x0))); + __asm__ ("sqxtun2 %0.8h, %1.4s" + : "+w"(result) + : "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqmovun_high_s64 (uint32x2_t a, int64x2_t b) +{ + uint32x4_t result = vcombine_u32 (a, vcreate_u32 (__AARCH64_UINT64_C (0x0))); + __asm__ ("sqxtun2 %0.4s, %1.2d" + : "+w"(result) + : "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmulh_n_s16 (int16x4_t a, int16_t b) +{ + int16x4_t result; + __asm__ ("sqrdmulh %0.4h,%1.4h,%2.h[0]" + : "=w"(result) + : "w"(a), "x"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmulh_n_s32 (int32x2_t a, int32_t b) +{ + int32x2_t result; + __asm__ ("sqrdmulh %0.2s,%1.2s,%2.s[0]" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmulhq_n_s16 (int16x8_t a, int16_t b) +{ + int16x8_t result; + __asm__ ("sqrdmulh %0.8h,%1.8h,%2.h[0]" + : "=w"(result) + : "w"(a), "x"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmulhq_n_s32 (int32x4_t a, int32_t b) +{ + int32x4_t result; + __asm__ ("sqrdmulh %0.4s,%1.4s,%2.s[0]" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +#define vqrshrn_high_n_s16(a, b, c) \ + __extension__ \ + ({ \ + int16x8_t b_ = (b); \ + int8x8_t a_ = (a); \ + int8x16_t result = vcombine_s8 \ + (a_, vcreate_s8 \ + (__AARCH64_UINT64_C (0x0))); \ + __asm__ ("sqrshrn2 %0.16b, %1.8h, #%2" \ + : "+w"(result) \ + : "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vqrshrn_high_n_s32(a, b, c) \ + __extension__ \ + ({ \ + int32x4_t b_ = (b); \ + int16x4_t a_ = (a); \ + int16x8_t result = vcombine_s16 \ + (a_, vcreate_s16 \ + (__AARCH64_UINT64_C (0x0))); \ + __asm__ ("sqrshrn2 %0.8h, %1.4s, #%2" \ + : "+w"(result) \ + : "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vqrshrn_high_n_s64(a, b, c) \ + __extension__ \ + ({ \ + int64x2_t b_ = (b); \ + int32x2_t a_ = (a); \ + int32x4_t result = vcombine_s32 \ + (a_, vcreate_s32 \ + (__AARCH64_UINT64_C (0x0))); \ + __asm__ ("sqrshrn2 %0.4s, %1.2d, #%2" \ + : "+w"(result) \ + : "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vqrshrn_high_n_u16(a, b, c) \ + __extension__ \ + ({ \ + uint16x8_t b_ = (b); \ + uint8x8_t a_ = (a); \ + uint8x16_t result = vcombine_u8 \ + (a_, vcreate_u8 \ + (__AARCH64_UINT64_C (0x0))); \ + __asm__ ("uqrshrn2 %0.16b, %1.8h, #%2" \ + : "+w"(result) \ + : "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vqrshrn_high_n_u32(a, b, c) \ + __extension__ \ + ({ \ + uint32x4_t b_ = (b); \ + uint16x4_t a_ = (a); \ + uint16x8_t result = vcombine_u16 \ + (a_, vcreate_u16 \ + (__AARCH64_UINT64_C (0x0))); \ + __asm__ ("uqrshrn2 %0.8h, %1.4s, #%2" \ + : "+w"(result) \ + : "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vqrshrn_high_n_u64(a, b, c) \ + __extension__ \ + ({ \ + uint64x2_t b_ = (b); \ + uint32x2_t a_ = (a); \ + uint32x4_t result = vcombine_u32 \ + (a_, vcreate_u32 \ + (__AARCH64_UINT64_C (0x0))); \ + __asm__ ("uqrshrn2 %0.4s, %1.2d, #%2" \ + : "+w"(result) \ + : "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vqrshrun_high_n_s16(a, b, c) \ + __extension__ \ + ({ \ + int16x8_t b_ = (b); \ + uint8x8_t a_ = (a); \ + uint8x16_t result = vcombine_u8 \ + (a_, vcreate_u8 \ + (__AARCH64_UINT64_C (0x0))); \ + __asm__ ("sqrshrun2 %0.16b, %1.8h, #%2" \ + : "+w"(result) \ + : "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vqrshrun_high_n_s32(a, b, c) \ + __extension__ \ + ({ \ + int32x4_t b_ = (b); \ + uint16x4_t a_ = (a); \ + uint16x8_t result = vcombine_u16 \ + (a_, vcreate_u16 \ + (__AARCH64_UINT64_C (0x0))); \ + __asm__ ("sqrshrun2 %0.8h, %1.4s, #%2" \ + : "+w"(result) \ + : "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vqrshrun_high_n_s64(a, b, c) \ + __extension__ \ + ({ \ + int64x2_t b_ = (b); \ + uint32x2_t a_ = (a); \ + uint32x4_t result = vcombine_u32 \ + (a_, vcreate_u32 \ + (__AARCH64_UINT64_C (0x0))); \ + __asm__ ("sqrshrun2 %0.4s, %1.2d, #%2" \ + : "+w"(result) \ + : "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vqshrn_high_n_s16(a, b, c) \ + __extension__ \ + ({ \ + int16x8_t b_ = (b); \ + int8x8_t a_ = (a); \ + int8x16_t result = vcombine_s8 \ + (a_, vcreate_s8 \ + (__AARCH64_UINT64_C (0x0))); \ + __asm__ ("sqshrn2 %0.16b, %1.8h, #%2" \ + : "+w"(result) \ + : "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vqshrn_high_n_s32(a, b, c) \ + __extension__ \ + ({ \ + int32x4_t b_ = (b); \ + int16x4_t a_ = (a); \ + int16x8_t result = vcombine_s16 \ + (a_, vcreate_s16 \ + (__AARCH64_UINT64_C (0x0))); \ + __asm__ ("sqshrn2 %0.8h, %1.4s, #%2" \ + : "+w"(result) \ + : "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vqshrn_high_n_s64(a, b, c) \ + __extension__ \ + ({ \ + int64x2_t b_ = (b); \ + int32x2_t a_ = (a); \ + int32x4_t result = vcombine_s32 \ + (a_, vcreate_s32 \ + (__AARCH64_UINT64_C (0x0))); \ + __asm__ ("sqshrn2 %0.4s, %1.2d, #%2" \ + : "+w"(result) \ + : "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vqshrn_high_n_u16(a, b, c) \ + __extension__ \ + ({ \ + uint16x8_t b_ = (b); \ + uint8x8_t a_ = (a); \ + uint8x16_t result = vcombine_u8 \ + (a_, vcreate_u8 \ + (__AARCH64_UINT64_C (0x0))); \ + __asm__ ("uqshrn2 %0.16b, %1.8h, #%2" \ + : "+w"(result) \ + : "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vqshrn_high_n_u32(a, b, c) \ + __extension__ \ + ({ \ + uint32x4_t b_ = (b); \ + uint16x4_t a_ = (a); \ + uint16x8_t result = vcombine_u16 \ + (a_, vcreate_u16 \ + (__AARCH64_UINT64_C (0x0))); \ + __asm__ ("uqshrn2 %0.8h, %1.4s, #%2" \ + : "+w"(result) \ + : "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vqshrn_high_n_u64(a, b, c) \ + __extension__ \ + ({ \ + uint64x2_t b_ = (b); \ + uint32x2_t a_ = (a); \ + uint32x4_t result = vcombine_u32 \ + (a_, vcreate_u32 \ + (__AARCH64_UINT64_C (0x0))); \ + __asm__ ("uqshrn2 %0.4s, %1.2d, #%2" \ + : "+w"(result) \ + : "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vqshrun_high_n_s16(a, b, c) \ + __extension__ \ + ({ \ + int16x8_t b_ = (b); \ + uint8x8_t a_ = (a); \ + uint8x16_t result = vcombine_u8 \ + (a_, vcreate_u8 \ + (__AARCH64_UINT64_C (0x0))); \ + __asm__ ("sqshrun2 %0.16b, %1.8h, #%2" \ + : "+w"(result) \ + : "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vqshrun_high_n_s32(a, b, c) \ + __extension__ \ + ({ \ + int32x4_t b_ = (b); \ + uint16x4_t a_ = (a); \ + uint16x8_t result = vcombine_u16 \ + (a_, vcreate_u16 \ + (__AARCH64_UINT64_C (0x0))); \ + __asm__ ("sqshrun2 %0.8h, %1.4s, #%2" \ + : "+w"(result) \ + : "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vqshrun_high_n_s64(a, b, c) \ + __extension__ \ + ({ \ + int64x2_t b_ = (b); \ + uint32x2_t a_ = (a); \ + uint32x4_t result = vcombine_u32 \ + (a_, vcreate_u32 \ + (__AARCH64_UINT64_C (0x0))); \ + __asm__ ("sqshrun2 %0.4s, %1.2d, #%2" \ + : "+w"(result) \ + : "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vrshrn_high_n_s16(a, b, c) \ + __extension__ \ + ({ \ + int16x8_t b_ = (b); \ + int8x8_t a_ = (a); \ + int8x16_t result = vcombine_s8 \ + (a_, vcreate_s8 \ + (__AARCH64_UINT64_C (0x0))); \ + __asm__ ("rshrn2 %0.16b,%1.8h,#%2" \ + : "+w"(result) \ + : "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vrshrn_high_n_s32(a, b, c) \ + __extension__ \ + ({ \ + int32x4_t b_ = (b); \ + int16x4_t a_ = (a); \ + int16x8_t result = vcombine_s16 \ + (a_, vcreate_s16 \ + (__AARCH64_UINT64_C (0x0))); \ + __asm__ ("rshrn2 %0.8h,%1.4s,#%2" \ + : "+w"(result) \ + : "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vrshrn_high_n_s64(a, b, c) \ + __extension__ \ + ({ \ + int64x2_t b_ = (b); \ + int32x2_t a_ = (a); \ + int32x4_t result = vcombine_s32 \ + (a_, vcreate_s32 \ + (__AARCH64_UINT64_C (0x0))); \ + __asm__ ("rshrn2 %0.4s,%1.2d,#%2" \ + : "+w"(result) \ + : "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vrshrn_high_n_u16(a, b, c) \ + __extension__ \ + ({ \ + uint16x8_t b_ = (b); \ + uint8x8_t a_ = (a); \ + uint8x16_t result = vcombine_u8 \ + (a_, vcreate_u8 \ + (__AARCH64_UINT64_C (0x0))); \ + __asm__ ("rshrn2 %0.16b,%1.8h,#%2" \ + : "+w"(result) \ + : "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vrshrn_high_n_u32(a, b, c) \ + __extension__ \ + ({ \ + uint32x4_t b_ = (b); \ + uint16x4_t a_ = (a); \ + uint16x8_t result = vcombine_u16 \ + (a_, vcreate_u16 \ + (__AARCH64_UINT64_C (0x0))); \ + __asm__ ("rshrn2 %0.8h,%1.4s,#%2" \ + : "+w"(result) \ + : "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vrshrn_high_n_u64(a, b, c) \ + __extension__ \ + ({ \ + uint64x2_t b_ = (b); \ + uint32x2_t a_ = (a); \ + uint32x4_t result = vcombine_u32 \ + (a_, vcreate_u32 \ + (__AARCH64_UINT64_C (0x0))); \ + __asm__ ("rshrn2 %0.4s,%1.2d,#%2" \ + : "+w"(result) \ + : "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vrshrn_n_s16(a, b) \ + __extension__ \ + ({ \ + int16x8_t a_ = (a); \ + int8x8_t result; \ + __asm__ ("rshrn %0.8b,%1.8h,%2" \ + : "=w"(result) \ + : "w"(a_), "i"(b) \ + : /* No clobbers */); \ + result; \ + }) + +#define vrshrn_n_s32(a, b) \ + __extension__ \ + ({ \ + int32x4_t a_ = (a); \ + int16x4_t result; \ + __asm__ ("rshrn %0.4h,%1.4s,%2" \ + : "=w"(result) \ + : "w"(a_), "i"(b) \ + : /* No clobbers */); \ + result; \ + }) + +#define vrshrn_n_s64(a, b) \ + __extension__ \ + ({ \ + int64x2_t a_ = (a); \ + int32x2_t result; \ + __asm__ ("rshrn %0.2s,%1.2d,%2" \ + : "=w"(result) \ + : "w"(a_), "i"(b) \ + : /* No clobbers */); \ + result; \ + }) + +#define vrshrn_n_u16(a, b) \ + __extension__ \ + ({ \ + uint16x8_t a_ = (a); \ + uint8x8_t result; \ + __asm__ ("rshrn %0.8b,%1.8h,%2" \ + : "=w"(result) \ + : "w"(a_), "i"(b) \ + : /* No clobbers */); \ + result; \ + }) + +#define vrshrn_n_u32(a, b) \ + __extension__ \ + ({ \ + uint32x4_t a_ = (a); \ + uint16x4_t result; \ + __asm__ ("rshrn %0.4h,%1.4s,%2" \ + : "=w"(result) \ + : "w"(a_), "i"(b) \ + : /* No clobbers */); \ + result; \ + }) + +#define vrshrn_n_u64(a, b) \ + __extension__ \ + ({ \ + uint64x2_t a_ = (a); \ + uint32x2_t result; \ + __asm__ ("rshrn %0.2s,%1.2d,%2" \ + : "=w"(result) \ + : "w"(a_), "i"(b) \ + : /* No clobbers */); \ + result; \ + }) + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsqrte_u32 (uint32x2_t a) +{ + uint32x2_t result; + __asm__ ("ursqrte %0.2s,%1.2s" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsqrteq_u32 (uint32x4_t a) +{ + uint32x4_t result; + __asm__ ("ursqrte %0.4s,%1.4s" + : "=w"(result) + : "w"(a) + : /* No clobbers */); + return result; +} + +#define vshrn_high_n_s16(a, b, c) \ + __extension__ \ + ({ \ + int16x8_t b_ = (b); \ + int8x8_t a_ = (a); \ + int8x16_t result = vcombine_s8 \ + (a_, vcreate_s8 \ + (__AARCH64_UINT64_C (0x0))); \ + __asm__ ("shrn2 %0.16b,%1.8h,#%2" \ + : "+w"(result) \ + : "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vshrn_high_n_s32(a, b, c) \ + __extension__ \ + ({ \ + int32x4_t b_ = (b); \ + int16x4_t a_ = (a); \ + int16x8_t result = vcombine_s16 \ + (a_, vcreate_s16 \ + (__AARCH64_UINT64_C (0x0))); \ + __asm__ ("shrn2 %0.8h,%1.4s,#%2" \ + : "+w"(result) \ + : "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vshrn_high_n_s64(a, b, c) \ + __extension__ \ + ({ \ + int64x2_t b_ = (b); \ + int32x2_t a_ = (a); \ + int32x4_t result = vcombine_s32 \ + (a_, vcreate_s32 \ + (__AARCH64_UINT64_C (0x0))); \ + __asm__ ("shrn2 %0.4s,%1.2d,#%2" \ + : "+w"(result) \ + : "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vshrn_high_n_u16(a, b, c) \ + __extension__ \ + ({ \ + uint16x8_t b_ = (b); \ + uint8x8_t a_ = (a); \ + uint8x16_t result = vcombine_u8 \ + (a_, vcreate_u8 \ + (__AARCH64_UINT64_C (0x0))); \ + __asm__ ("shrn2 %0.16b,%1.8h,#%2" \ + : "+w"(result) \ + : "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vshrn_high_n_u32(a, b, c) \ + __extension__ \ + ({ \ + uint32x4_t b_ = (b); \ + uint16x4_t a_ = (a); \ + uint16x8_t result = vcombine_u16 \ + (a_, vcreate_u16 \ + (__AARCH64_UINT64_C (0x0))); \ + __asm__ ("shrn2 %0.8h,%1.4s,#%2" \ + : "+w"(result) \ + : "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vshrn_high_n_u64(a, b, c) \ + __extension__ \ + ({ \ + uint64x2_t b_ = (b); \ + uint32x2_t a_ = (a); \ + uint32x4_t result = vcombine_u32 \ + (a_, vcreate_u32 \ + (__AARCH64_UINT64_C (0x0))); \ + __asm__ ("shrn2 %0.4s,%1.2d,#%2" \ + : "+w"(result) \ + : "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vshrn_n_s16(a, b) \ + __extension__ \ + ({ \ + int16x8_t a_ = (a); \ + int8x8_t result; \ + __asm__ ("shrn %0.8b,%1.8h,%2" \ + : "=w"(result) \ + : "w"(a_), "i"(b) \ + : /* No clobbers */); \ + result; \ + }) + +#define vshrn_n_s32(a, b) \ + __extension__ \ + ({ \ + int32x4_t a_ = (a); \ + int16x4_t result; \ + __asm__ ("shrn %0.4h,%1.4s,%2" \ + : "=w"(result) \ + : "w"(a_), "i"(b) \ + : /* No clobbers */); \ + result; \ + }) + +#define vshrn_n_s64(a, b) \ + __extension__ \ + ({ \ + int64x2_t a_ = (a); \ + int32x2_t result; \ + __asm__ ("shrn %0.2s,%1.2d,%2" \ + : "=w"(result) \ + : "w"(a_), "i"(b) \ + : /* No clobbers */); \ + result; \ + }) + +#define vshrn_n_u16(a, b) \ + __extension__ \ + ({ \ + uint16x8_t a_ = (a); \ + uint8x8_t result; \ + __asm__ ("shrn %0.8b,%1.8h,%2" \ + : "=w"(result) \ + : "w"(a_), "i"(b) \ + : /* No clobbers */); \ + result; \ + }) + +#define vshrn_n_u32(a, b) \ + __extension__ \ + ({ \ + uint32x4_t a_ = (a); \ + uint16x4_t result; \ + __asm__ ("shrn %0.4h,%1.4s,%2" \ + : "=w"(result) \ + : "w"(a_), "i"(b) \ + : /* No clobbers */); \ + result; \ + }) + +#define vshrn_n_u64(a, b) \ + __extension__ \ + ({ \ + uint64x2_t a_ = (a); \ + uint32x2_t result; \ + __asm__ ("shrn %0.2s,%1.2d,%2" \ + : "=w"(result) \ + : "w"(a_), "i"(b) \ + : /* No clobbers */); \ + result; \ + }) + +#define vsli_n_p8(a, b, c) \ + __extension__ \ + ({ \ + poly8x8_t b_ = (b); \ + poly8x8_t a_ = (a); \ + poly8x8_t result; \ + __asm__ ("sli %0.8b,%2.8b,%3" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vsli_n_p16(a, b, c) \ + __extension__ \ + ({ \ + poly16x4_t b_ = (b); \ + poly16x4_t a_ = (a); \ + poly16x4_t result; \ + __asm__ ("sli %0.4h,%2.4h,%3" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vsliq_n_p8(a, b, c) \ + __extension__ \ + ({ \ + poly8x16_t b_ = (b); \ + poly8x16_t a_ = (a); \ + poly8x16_t result; \ + __asm__ ("sli %0.16b,%2.16b,%3" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vsliq_n_p16(a, b, c) \ + __extension__ \ + ({ \ + poly16x8_t b_ = (b); \ + poly16x8_t a_ = (a); \ + poly16x8_t result; \ + __asm__ ("sli %0.8h,%2.8h,%3" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vsri_n_p8(a, b, c) \ + __extension__ \ + ({ \ + poly8x8_t b_ = (b); \ + poly8x8_t a_ = (a); \ + poly8x8_t result; \ + __asm__ ("sri %0.8b,%2.8b,%3" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vsri_n_p16(a, b, c) \ + __extension__ \ + ({ \ + poly16x4_t b_ = (b); \ + poly16x4_t a_ = (a); \ + poly16x4_t result; \ + __asm__ ("sri %0.4h,%2.4h,%3" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vsri_n_p64(a, b, c) \ + __extension__ \ + ({ \ + poly64x1_t b_ = (b); \ + poly64x1_t a_ = (a); \ + poly64x1_t result; \ + __asm__ ("sri %d0,%d2,%3" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "i"(c) \ + : /* No clobbers. */); \ + result; \ + }) + +#define vsriq_n_p8(a, b, c) \ + __extension__ \ + ({ \ + poly8x16_t b_ = (b); \ + poly8x16_t a_ = (a); \ + poly8x16_t result; \ + __asm__ ("sri %0.16b,%2.16b,%3" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vsriq_n_p16(a, b, c) \ + __extension__ \ + ({ \ + poly16x8_t b_ = (b); \ + poly16x8_t a_ = (a); \ + poly16x8_t result; \ + __asm__ ("sri %0.8h,%2.8h,%3" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "i"(c) \ + : /* No clobbers */); \ + result; \ + }) + +#define vsriq_n_p64(a, b, c) \ + __extension__ \ + ({ \ + poly64x2_t b_ = (b); \ + poly64x2_t a_ = (a); \ + poly64x2_t result; \ + __asm__ ("sri %0.2d,%2.2d,%3" \ + : "=w"(result) \ + : "0"(a_), "w"(b_), "i"(c) \ + : /* No clobbers. */); \ + result; \ + }) + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtst_p8 (poly8x8_t a, poly8x8_t b) +{ + return (uint8x8_t) ((((uint8x8_t) a) & ((uint8x8_t) b)) + != 0); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtst_p16 (poly16x4_t a, poly16x4_t b) +{ + return (uint16x4_t) ((((uint16x4_t) a) & ((uint16x4_t) b)) + != 0); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtst_p64 (poly64x1_t a, poly64x1_t b) +{ + return (uint64x1_t) ((a & b) != __AARCH64_INT64_C (0)); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtstq_p8 (poly8x16_t a, poly8x16_t b) +{ + return (uint8x16_t) ((((uint8x16_t) a) & ((uint8x16_t) b)) + != 0); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtstq_p16 (poly16x8_t a, poly16x8_t b) +{ + return (uint16x8_t) ((((uint16x8_t) a) & ((uint16x8_t) b)) + != 0); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtstq_p64 (poly64x2_t a, poly64x2_t b) +{ + return (uint64x2_t) ((((uint64x2_t) a) & ((uint64x2_t) b)) + != __AARCH64_INT64_C (0)); +} + +/* End of temporary inline asm implementations. */ + +/* Start of temporary inline asm for vldn, vstn and friends. */ + +/* Create struct element types for duplicating loads. + + Create 2 element structures of: + + +------+----+----+----+----+ + | | 8 | 16 | 32 | 64 | + +------+----+----+----+----+ + |int | Y | Y | N | N | + +------+----+----+----+----+ + |uint | Y | Y | N | N | + +------+----+----+----+----+ + |float | - | Y | N | N | + +------+----+----+----+----+ + |poly | Y | Y | - | - | + +------+----+----+----+----+ + + Create 3 element structures of: + + +------+----+----+----+----+ + | | 8 | 16 | 32 | 64 | + +------+----+----+----+----+ + |int | Y | Y | Y | Y | + +------+----+----+----+----+ + |uint | Y | Y | Y | Y | + +------+----+----+----+----+ + |float | - | Y | Y | Y | + +------+----+----+----+----+ + |poly | Y | Y | - | - | + +------+----+----+----+----+ + + Create 4 element structures of: + + +------+----+----+----+----+ + | | 8 | 16 | 32 | 64 | + +------+----+----+----+----+ + |int | Y | N | N | Y | + +------+----+----+----+----+ + |uint | Y | N | N | Y | + +------+----+----+----+----+ + |float | - | N | N | Y | + +------+----+----+----+----+ + |poly | Y | N | - | - | + +------+----+----+----+----+ + + This is required for casting memory reference. */ +#define __STRUCTN(t, sz, nelem) \ + typedef struct t ## sz ## x ## nelem ## _t { \ + t ## sz ## _t val[nelem]; \ + } t ## sz ## x ## nelem ## _t; + +/* 2-element structs. */ +__STRUCTN (int, 8, 2) +__STRUCTN (int, 16, 2) +__STRUCTN (uint, 8, 2) +__STRUCTN (uint, 16, 2) +__STRUCTN (float, 16, 2) +__STRUCTN (poly, 8, 2) +__STRUCTN (poly, 16, 2) +/* 3-element structs. */ +__STRUCTN (int, 8, 3) +__STRUCTN (int, 16, 3) +__STRUCTN (int, 32, 3) +__STRUCTN (int, 64, 3) +__STRUCTN (uint, 8, 3) +__STRUCTN (uint, 16, 3) +__STRUCTN (uint, 32, 3) +__STRUCTN (uint, 64, 3) +__STRUCTN (float, 16, 3) +__STRUCTN (float, 32, 3) +__STRUCTN (float, 64, 3) +__STRUCTN (poly, 8, 3) +__STRUCTN (poly, 16, 3) +/* 4-element structs. */ +__STRUCTN (int, 8, 4) +__STRUCTN (int, 64, 4) +__STRUCTN (uint, 8, 4) +__STRUCTN (uint, 64, 4) +__STRUCTN (poly, 8, 4) +__STRUCTN (float, 64, 4) +#undef __STRUCTN + + +#define __ST2_LANE_FUNC(intype, largetype, ptrtype, mode, \ + qmode, ptr_mode, funcsuffix, signedtype) \ +__extension__ extern __inline void \ +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) \ +vst2_lane_ ## funcsuffix (ptrtype *__ptr, \ + intype __b, const int __c) \ +{ \ + __builtin_aarch64_simd_oi __o; \ + largetype __temp; \ + __temp.val[0] \ + = vcombine_##funcsuffix (__b.val[0], \ + vcreate_##funcsuffix (__AARCH64_UINT64_C (0))); \ + __temp.val[1] \ + = vcombine_##funcsuffix (__b.val[1], \ + vcreate_##funcsuffix (__AARCH64_UINT64_C (0))); \ + __o = __builtin_aarch64_set_qregoi##qmode (__o, \ + (signedtype) __temp.val[0], 0); \ + __o = __builtin_aarch64_set_qregoi##qmode (__o, \ + (signedtype) __temp.val[1], 1); \ + __builtin_aarch64_st2_lane##mode ((__builtin_aarch64_simd_ ## ptr_mode *) \ + __ptr, __o, __c); \ +} + +__ST2_LANE_FUNC (float16x4x2_t, float16x8x2_t, float16_t, v4hf, v8hf, hf, f16, + float16x8_t) +__ST2_LANE_FUNC (float32x2x2_t, float32x4x2_t, float32_t, v2sf, v4sf, sf, f32, + float32x4_t) +__ST2_LANE_FUNC (float64x1x2_t, float64x2x2_t, float64_t, df, v2df, df, f64, + float64x2_t) +__ST2_LANE_FUNC (poly8x8x2_t, poly8x16x2_t, poly8_t, v8qi, v16qi, qi, p8, + int8x16_t) +__ST2_LANE_FUNC (poly16x4x2_t, poly16x8x2_t, poly16_t, v4hi, v8hi, hi, p16, + int16x8_t) +__ST2_LANE_FUNC (poly64x1x2_t, poly64x2x2_t, poly64_t, di, v2di_ssps, di, p64, + poly64x2_t) +__ST2_LANE_FUNC (int8x8x2_t, int8x16x2_t, int8_t, v8qi, v16qi, qi, s8, + int8x16_t) +__ST2_LANE_FUNC (int16x4x2_t, int16x8x2_t, int16_t, v4hi, v8hi, hi, s16, + int16x8_t) +__ST2_LANE_FUNC (int32x2x2_t, int32x4x2_t, int32_t, v2si, v4si, si, s32, + int32x4_t) +__ST2_LANE_FUNC (int64x1x2_t, int64x2x2_t, int64_t, di, v2di, di, s64, + int64x2_t) +__ST2_LANE_FUNC (uint8x8x2_t, uint8x16x2_t, uint8_t, v8qi, v16qi, qi, u8, + int8x16_t) +__ST2_LANE_FUNC (uint16x4x2_t, uint16x8x2_t, uint16_t, v4hi, v8hi, hi, u16, + int16x8_t) +__ST2_LANE_FUNC (uint32x2x2_t, uint32x4x2_t, uint32_t, v2si, v4si, si, u32, + int32x4_t) +__ST2_LANE_FUNC (uint64x1x2_t, uint64x2x2_t, uint64_t, di, v2di, di, u64, + int64x2_t) + +#undef __ST2_LANE_FUNC +#define __ST2_LANE_FUNC(intype, ptrtype, mode, ptr_mode, funcsuffix) \ +__extension__ extern __inline void \ +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) \ +vst2q_lane_ ## funcsuffix (ptrtype *__ptr, \ + intype __b, const int __c) \ +{ \ + union { intype __i; \ + __builtin_aarch64_simd_oi __o; } __temp = { __b }; \ + __builtin_aarch64_st2_lane##mode ((__builtin_aarch64_simd_ ## ptr_mode *) \ + __ptr, __temp.__o, __c); \ +} + +__ST2_LANE_FUNC (float16x8x2_t, float16_t, v8hf, hf, f16) +__ST2_LANE_FUNC (float32x4x2_t, float32_t, v4sf, sf, f32) +__ST2_LANE_FUNC (float64x2x2_t, float64_t, v2df, df, f64) +__ST2_LANE_FUNC (poly8x16x2_t, poly8_t, v16qi, qi, p8) +__ST2_LANE_FUNC (poly16x8x2_t, poly16_t, v8hi, hi, p16) +__ST2_LANE_FUNC (poly64x2x2_t, poly64_t, v2di, di, p64) +__ST2_LANE_FUNC (int8x16x2_t, int8_t, v16qi, qi, s8) +__ST2_LANE_FUNC (int16x8x2_t, int16_t, v8hi, hi, s16) +__ST2_LANE_FUNC (int32x4x2_t, int32_t, v4si, si, s32) +__ST2_LANE_FUNC (int64x2x2_t, int64_t, v2di, di, s64) +__ST2_LANE_FUNC (uint8x16x2_t, uint8_t, v16qi, qi, u8) +__ST2_LANE_FUNC (uint16x8x2_t, uint16_t, v8hi, hi, u16) +__ST2_LANE_FUNC (uint32x4x2_t, uint32_t, v4si, si, u32) +__ST2_LANE_FUNC (uint64x2x2_t, uint64_t, v2di, di, u64) + +#define __ST3_LANE_FUNC(intype, largetype, ptrtype, mode, \ + qmode, ptr_mode, funcsuffix, signedtype) \ +__extension__ extern __inline void \ +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) \ +vst3_lane_ ## funcsuffix (ptrtype *__ptr, \ + intype __b, const int __c) \ +{ \ + __builtin_aarch64_simd_ci __o; \ + largetype __temp; \ + __temp.val[0] \ + = vcombine_##funcsuffix (__b.val[0], \ + vcreate_##funcsuffix (__AARCH64_UINT64_C (0))); \ + __temp.val[1] \ + = vcombine_##funcsuffix (__b.val[1], \ + vcreate_##funcsuffix (__AARCH64_UINT64_C (0))); \ + __temp.val[2] \ + = vcombine_##funcsuffix (__b.val[2], \ + vcreate_##funcsuffix (__AARCH64_UINT64_C (0))); \ + __o = __builtin_aarch64_set_qregci##qmode (__o, \ + (signedtype) __temp.val[0], 0); \ + __o = __builtin_aarch64_set_qregci##qmode (__o, \ + (signedtype) __temp.val[1], 1); \ + __o = __builtin_aarch64_set_qregci##qmode (__o, \ + (signedtype) __temp.val[2], 2); \ + __builtin_aarch64_st3_lane##mode ((__builtin_aarch64_simd_ ## ptr_mode *) \ + __ptr, __o, __c); \ +} + +__ST3_LANE_FUNC (float16x4x3_t, float16x8x3_t, float16_t, v4hf, v8hf, hf, f16, + float16x8_t) +__ST3_LANE_FUNC (float32x2x3_t, float32x4x3_t, float32_t, v2sf, v4sf, sf, f32, + float32x4_t) +__ST3_LANE_FUNC (float64x1x3_t, float64x2x3_t, float64_t, df, v2df, df, f64, + float64x2_t) +__ST3_LANE_FUNC (poly8x8x3_t, poly8x16x3_t, poly8_t, v8qi, v16qi, qi, p8, + int8x16_t) +__ST3_LANE_FUNC (poly16x4x3_t, poly16x8x3_t, poly16_t, v4hi, v8hi, hi, p16, + int16x8_t) +__ST3_LANE_FUNC (poly64x1x3_t, poly64x2x3_t, poly64_t, di, v2di_ssps, di, p64, + poly64x2_t) +__ST3_LANE_FUNC (int8x8x3_t, int8x16x3_t, int8_t, v8qi, v16qi, qi, s8, + int8x16_t) +__ST3_LANE_FUNC (int16x4x3_t, int16x8x3_t, int16_t, v4hi, v8hi, hi, s16, + int16x8_t) +__ST3_LANE_FUNC (int32x2x3_t, int32x4x3_t, int32_t, v2si, v4si, si, s32, + int32x4_t) +__ST3_LANE_FUNC (int64x1x3_t, int64x2x3_t, int64_t, di, v2di, di, s64, + int64x2_t) +__ST3_LANE_FUNC (uint8x8x3_t, uint8x16x3_t, uint8_t, v8qi, v16qi, qi, u8, + int8x16_t) +__ST3_LANE_FUNC (uint16x4x3_t, uint16x8x3_t, uint16_t, v4hi, v8hi, hi, u16, + int16x8_t) +__ST3_LANE_FUNC (uint32x2x3_t, uint32x4x3_t, uint32_t, v2si, v4si, si, u32, + int32x4_t) +__ST3_LANE_FUNC (uint64x1x3_t, uint64x2x3_t, uint64_t, di, v2di, di, u64, + int64x2_t) + +#undef __ST3_LANE_FUNC +#define __ST3_LANE_FUNC(intype, ptrtype, mode, ptr_mode, funcsuffix) \ +__extension__ extern __inline void \ +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) \ +vst3q_lane_ ## funcsuffix (ptrtype *__ptr, \ + intype __b, const int __c) \ +{ \ + union { intype __i; \ + __builtin_aarch64_simd_ci __o; } __temp = { __b }; \ + __builtin_aarch64_st3_lane##mode ((__builtin_aarch64_simd_ ## ptr_mode *) \ + __ptr, __temp.__o, __c); \ +} + +__ST3_LANE_FUNC (float16x8x3_t, float16_t, v8hf, hf, f16) +__ST3_LANE_FUNC (float32x4x3_t, float32_t, v4sf, sf, f32) +__ST3_LANE_FUNC (float64x2x3_t, float64_t, v2df, df, f64) +__ST3_LANE_FUNC (poly8x16x3_t, poly8_t, v16qi, qi, p8) +__ST3_LANE_FUNC (poly16x8x3_t, poly16_t, v8hi, hi, p16) +__ST3_LANE_FUNC (poly64x2x3_t, poly64_t, v2di, di, p64) +__ST3_LANE_FUNC (int8x16x3_t, int8_t, v16qi, qi, s8) +__ST3_LANE_FUNC (int16x8x3_t, int16_t, v8hi, hi, s16) +__ST3_LANE_FUNC (int32x4x3_t, int32_t, v4si, si, s32) +__ST3_LANE_FUNC (int64x2x3_t, int64_t, v2di, di, s64) +__ST3_LANE_FUNC (uint8x16x3_t, uint8_t, v16qi, qi, u8) +__ST3_LANE_FUNC (uint16x8x3_t, uint16_t, v8hi, hi, u16) +__ST3_LANE_FUNC (uint32x4x3_t, uint32_t, v4si, si, u32) +__ST3_LANE_FUNC (uint64x2x3_t, uint64_t, v2di, di, u64) + +#define __ST4_LANE_FUNC(intype, largetype, ptrtype, mode, \ + qmode, ptr_mode, funcsuffix, signedtype) \ +__extension__ extern __inline void \ +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) \ +vst4_lane_ ## funcsuffix (ptrtype *__ptr, \ + intype __b, const int __c) \ +{ \ + __builtin_aarch64_simd_xi __o; \ + largetype __temp; \ + __temp.val[0] \ + = vcombine_##funcsuffix (__b.val[0], \ + vcreate_##funcsuffix (__AARCH64_UINT64_C (0))); \ + __temp.val[1] \ + = vcombine_##funcsuffix (__b.val[1], \ + vcreate_##funcsuffix (__AARCH64_UINT64_C (0))); \ + __temp.val[2] \ + = vcombine_##funcsuffix (__b.val[2], \ + vcreate_##funcsuffix (__AARCH64_UINT64_C (0))); \ + __temp.val[3] \ + = vcombine_##funcsuffix (__b.val[3], \ + vcreate_##funcsuffix (__AARCH64_UINT64_C (0))); \ + __o = __builtin_aarch64_set_qregxi##qmode (__o, \ + (signedtype) __temp.val[0], 0); \ + __o = __builtin_aarch64_set_qregxi##qmode (__o, \ + (signedtype) __temp.val[1], 1); \ + __o = __builtin_aarch64_set_qregxi##qmode (__o, \ + (signedtype) __temp.val[2], 2); \ + __o = __builtin_aarch64_set_qregxi##qmode (__o, \ + (signedtype) __temp.val[3], 3); \ + __builtin_aarch64_st4_lane##mode ((__builtin_aarch64_simd_ ## ptr_mode *) \ + __ptr, __o, __c); \ +} + +__ST4_LANE_FUNC (float16x4x4_t, float16x8x4_t, float16_t, v4hf, v8hf, hf, f16, + float16x8_t) +__ST4_LANE_FUNC (float32x2x4_t, float32x4x4_t, float32_t, v2sf, v4sf, sf, f32, + float32x4_t) +__ST4_LANE_FUNC (float64x1x4_t, float64x2x4_t, float64_t, df, v2df, df, f64, + float64x2_t) +__ST4_LANE_FUNC (poly8x8x4_t, poly8x16x4_t, poly8_t, v8qi, v16qi, qi, p8, + int8x16_t) +__ST4_LANE_FUNC (poly16x4x4_t, poly16x8x4_t, poly16_t, v4hi, v8hi, hi, p16, + int16x8_t) +__ST4_LANE_FUNC (poly64x1x4_t, poly64x2x4_t, poly64_t, di, v2di_ssps, di, p64, + poly64x2_t) +__ST4_LANE_FUNC (int8x8x4_t, int8x16x4_t, int8_t, v8qi, v16qi, qi, s8, + int8x16_t) +__ST4_LANE_FUNC (int16x4x4_t, int16x8x4_t, int16_t, v4hi, v8hi, hi, s16, + int16x8_t) +__ST4_LANE_FUNC (int32x2x4_t, int32x4x4_t, int32_t, v2si, v4si, si, s32, + int32x4_t) +__ST4_LANE_FUNC (int64x1x4_t, int64x2x4_t, int64_t, di, v2di, di, s64, + int64x2_t) +__ST4_LANE_FUNC (uint8x8x4_t, uint8x16x4_t, uint8_t, v8qi, v16qi, qi, u8, + int8x16_t) +__ST4_LANE_FUNC (uint16x4x4_t, uint16x8x4_t, uint16_t, v4hi, v8hi, hi, u16, + int16x8_t) +__ST4_LANE_FUNC (uint32x2x4_t, uint32x4x4_t, uint32_t, v2si, v4si, si, u32, + int32x4_t) +__ST4_LANE_FUNC (uint64x1x4_t, uint64x2x4_t, uint64_t, di, v2di, di, u64, + int64x2_t) + +#undef __ST4_LANE_FUNC +#define __ST4_LANE_FUNC(intype, ptrtype, mode, ptr_mode, funcsuffix) \ +__extension__ extern __inline void \ +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) \ +vst4q_lane_ ## funcsuffix (ptrtype *__ptr, \ + intype __b, const int __c) \ +{ \ + union { intype __i; \ + __builtin_aarch64_simd_xi __o; } __temp = { __b }; \ + __builtin_aarch64_st4_lane##mode ((__builtin_aarch64_simd_ ## ptr_mode *) \ + __ptr, __temp.__o, __c); \ +} + +__ST4_LANE_FUNC (float16x8x4_t, float16_t, v8hf, hf, f16) +__ST4_LANE_FUNC (float32x4x4_t, float32_t, v4sf, sf, f32) +__ST4_LANE_FUNC (float64x2x4_t, float64_t, v2df, df, f64) +__ST4_LANE_FUNC (poly8x16x4_t, poly8_t, v16qi, qi, p8) +__ST4_LANE_FUNC (poly16x8x4_t, poly16_t, v8hi, hi, p16) +__ST4_LANE_FUNC (poly64x2x4_t, poly64_t, v2di, di, p64) +__ST4_LANE_FUNC (int8x16x4_t, int8_t, v16qi, qi, s8) +__ST4_LANE_FUNC (int16x8x4_t, int16_t, v8hi, hi, s16) +__ST4_LANE_FUNC (int32x4x4_t, int32_t, v4si, si, s32) +__ST4_LANE_FUNC (int64x2x4_t, int64_t, v2di, di, s64) +__ST4_LANE_FUNC (uint8x16x4_t, uint8_t, v16qi, qi, u8) +__ST4_LANE_FUNC (uint16x8x4_t, uint16_t, v8hi, hi, u16) +__ST4_LANE_FUNC (uint32x4x4_t, uint32_t, v4si, si, u32) +__ST4_LANE_FUNC (uint64x2x4_t, uint64_t, v2di, di, u64) + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddlv_s32 (int32x2_t a) +{ + int64_t result; + __asm__ ("saddlp %0.1d, %1.2s" : "=w"(result) : "w"(a) : ); + return result; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddlv_u32 (uint32x2_t a) +{ + uint64_t result; + __asm__ ("uaddlp %0.1d, %1.2s" : "=w"(result) : "w"(a) : ); + return result; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmulh_laneq_s16 (int16x4_t __a, int16x8_t __b, const int __c) +{ + return __builtin_aarch64_sqdmulh_laneqv4hi (__a, __b, __c); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmulh_laneq_s32 (int32x2_t __a, int32x4_t __b, const int __c) +{ + return __builtin_aarch64_sqdmulh_laneqv2si (__a, __b, __c); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmulhq_laneq_s16 (int16x8_t __a, int16x8_t __b, const int __c) +{ + return __builtin_aarch64_sqdmulh_laneqv8hi (__a, __b, __c); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmulhq_laneq_s32 (int32x4_t __a, int32x4_t __b, const int __c) +{ + return __builtin_aarch64_sqdmulh_laneqv4si (__a, __b, __c); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmulh_laneq_s16 (int16x4_t __a, int16x8_t __b, const int __c) +{ + return __builtin_aarch64_sqrdmulh_laneqv4hi (__a, __b, __c); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmulh_laneq_s32 (int32x2_t __a, int32x4_t __b, const int __c) +{ + return __builtin_aarch64_sqrdmulh_laneqv2si (__a, __b, __c); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmulhq_laneq_s16 (int16x8_t __a, int16x8_t __b, const int __c) +{ + return __builtin_aarch64_sqrdmulh_laneqv8hi (__a, __b, __c); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmulhq_laneq_s32 (int32x4_t __a, int32x4_t __b, const int __c) +{ + return __builtin_aarch64_sqrdmulh_laneqv4si (__a, __b, __c); +} + +/* Table intrinsics. */ + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbl1_p8 (poly8x16_t a, uint8x8_t b) +{ + poly8x8_t result; + __asm__ ("tbl %0.8b, {%1.16b}, %2.8b" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbl1_s8 (int8x16_t a, uint8x8_t b) +{ + int8x8_t result; + __asm__ ("tbl %0.8b, {%1.16b}, %2.8b" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbl1_u8 (uint8x16_t a, uint8x8_t b) +{ + uint8x8_t result; + __asm__ ("tbl %0.8b, {%1.16b}, %2.8b" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbl1q_p8 (poly8x16_t a, uint8x16_t b) +{ + poly8x16_t result; + __asm__ ("tbl %0.16b, {%1.16b}, %2.16b" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbl1q_s8 (int8x16_t a, uint8x16_t b) +{ + int8x16_t result; + __asm__ ("tbl %0.16b, {%1.16b}, %2.16b" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbl1q_u8 (uint8x16_t a, uint8x16_t b) +{ + uint8x16_t result; + __asm__ ("tbl %0.16b, {%1.16b}, %2.16b" + : "=w"(result) + : "w"(a), "w"(b) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbx1_s8 (int8x8_t r, int8x16_t tab, uint8x8_t idx) +{ + int8x8_t result = r; + __asm__ ("tbx %0.8b,{%1.16b},%2.8b" + : "+w"(result) + : "w"(tab), "w"(idx) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbx1_u8 (uint8x8_t r, uint8x16_t tab, uint8x8_t idx) +{ + uint8x8_t result = r; + __asm__ ("tbx %0.8b,{%1.16b},%2.8b" + : "+w"(result) + : "w"(tab), "w"(idx) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbx1_p8 (poly8x8_t r, poly8x16_t tab, uint8x8_t idx) +{ + poly8x8_t result = r; + __asm__ ("tbx %0.8b,{%1.16b},%2.8b" + : "+w"(result) + : "w"(tab), "w"(idx) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbx1q_s8 (int8x16_t r, int8x16_t tab, uint8x16_t idx) +{ + int8x16_t result = r; + __asm__ ("tbx %0.16b,{%1.16b},%2.16b" + : "+w"(result) + : "w"(tab), "w"(idx) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbx1q_u8 (uint8x16_t r, uint8x16_t tab, uint8x16_t idx) +{ + uint8x16_t result = r; + __asm__ ("tbx %0.16b,{%1.16b},%2.16b" + : "+w"(result) + : "w"(tab), "w"(idx) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbx1q_p8 (poly8x16_t r, poly8x16_t tab, uint8x16_t idx) +{ + poly8x16_t result = r; + __asm__ ("tbx %0.16b,{%1.16b},%2.16b" + : "+w"(result) + : "w"(tab), "w"(idx) + : /* No clobbers */); + return result; +} + +/* V7 legacy table intrinsics. */ + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtbl1_s8 (int8x8_t tab, int8x8_t idx) +{ + int8x8_t result; + int8x16_t temp = vcombine_s8 (tab, vcreate_s8 (__AARCH64_UINT64_C (0x0))); + __asm__ ("tbl %0.8b, {%1.16b}, %2.8b" + : "=w"(result) + : "w"(temp), "w"(idx) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtbl1_u8 (uint8x8_t tab, uint8x8_t idx) +{ + uint8x8_t result; + uint8x16_t temp = vcombine_u8 (tab, vcreate_u8 (__AARCH64_UINT64_C (0x0))); + __asm__ ("tbl %0.8b, {%1.16b}, %2.8b" + : "=w"(result) + : "w"(temp), "w"(idx) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtbl1_p8 (poly8x8_t tab, uint8x8_t idx) +{ + poly8x8_t result; + poly8x16_t temp = vcombine_p8 (tab, vcreate_p8 (__AARCH64_UINT64_C (0x0))); + __asm__ ("tbl %0.8b, {%1.16b}, %2.8b" + : "=w"(result) + : "w"(temp), "w"(idx) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtbl2_s8 (int8x8x2_t tab, int8x8_t idx) +{ + int8x8_t result; + int8x16_t temp = vcombine_s8 (tab.val[0], tab.val[1]); + __asm__ ("tbl %0.8b, {%1.16b}, %2.8b" + : "=w"(result) + : "w"(temp), "w"(idx) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtbl2_u8 (uint8x8x2_t tab, uint8x8_t idx) +{ + uint8x8_t result; + uint8x16_t temp = vcombine_u8 (tab.val[0], tab.val[1]); + __asm__ ("tbl %0.8b, {%1.16b}, %2.8b" + : "=w"(result) + : "w"(temp), "w"(idx) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtbl2_p8 (poly8x8x2_t tab, uint8x8_t idx) +{ + poly8x8_t result; + poly8x16_t temp = vcombine_p8 (tab.val[0], tab.val[1]); + __asm__ ("tbl %0.8b, {%1.16b}, %2.8b" + : "=w"(result) + : "w"(temp), "w"(idx) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtbl3_s8 (int8x8x3_t tab, int8x8_t idx) +{ + int8x8_t result; + int8x16x2_t temp; + __builtin_aarch64_simd_oi __o; + temp.val[0] = vcombine_s8 (tab.val[0], tab.val[1]); + temp.val[1] = vcombine_s8 (tab.val[2], vcreate_s8 (__AARCH64_UINT64_C (0x0))); + __o = __builtin_aarch64_set_qregoiv16qi (__o, + (int8x16_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, + (int8x16_t) temp.val[1], 1); + result = __builtin_aarch64_tbl3v8qi (__o, idx); + return result; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtbl3_u8 (uint8x8x3_t tab, uint8x8_t idx) +{ + uint8x8_t result; + uint8x16x2_t temp; + __builtin_aarch64_simd_oi __o; + temp.val[0] = vcombine_u8 (tab.val[0], tab.val[1]); + temp.val[1] = vcombine_u8 (tab.val[2], vcreate_u8 (__AARCH64_UINT64_C (0x0))); + __o = __builtin_aarch64_set_qregoiv16qi (__o, + (int8x16_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, + (int8x16_t) temp.val[1], 1); + result = (uint8x8_t)__builtin_aarch64_tbl3v8qi (__o, (int8x8_t)idx); + return result; +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtbl3_p8 (poly8x8x3_t tab, uint8x8_t idx) +{ + poly8x8_t result; + poly8x16x2_t temp; + __builtin_aarch64_simd_oi __o; + temp.val[0] = vcombine_p8 (tab.val[0], tab.val[1]); + temp.val[1] = vcombine_p8 (tab.val[2], vcreate_p8 (__AARCH64_UINT64_C (0x0))); + __o = __builtin_aarch64_set_qregoiv16qi (__o, + (int8x16_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, + (int8x16_t) temp.val[1], 1); + result = (poly8x8_t)__builtin_aarch64_tbl3v8qi (__o, (int8x8_t)idx); + return result; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtbl4_s8 (int8x8x4_t tab, int8x8_t idx) +{ + int8x8_t result; + int8x16x2_t temp; + __builtin_aarch64_simd_oi __o; + temp.val[0] = vcombine_s8 (tab.val[0], tab.val[1]); + temp.val[1] = vcombine_s8 (tab.val[2], tab.val[3]); + __o = __builtin_aarch64_set_qregoiv16qi (__o, + (int8x16_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, + (int8x16_t) temp.val[1], 1); + result = __builtin_aarch64_tbl3v8qi (__o, idx); + return result; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtbl4_u8 (uint8x8x4_t tab, uint8x8_t idx) +{ + uint8x8_t result; + uint8x16x2_t temp; + __builtin_aarch64_simd_oi __o; + temp.val[0] = vcombine_u8 (tab.val[0], tab.val[1]); + temp.val[1] = vcombine_u8 (tab.val[2], tab.val[3]); + __o = __builtin_aarch64_set_qregoiv16qi (__o, + (int8x16_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, + (int8x16_t) temp.val[1], 1); + result = (uint8x8_t)__builtin_aarch64_tbl3v8qi (__o, (int8x8_t)idx); + return result; +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtbl4_p8 (poly8x8x4_t tab, uint8x8_t idx) +{ + poly8x8_t result; + poly8x16x2_t temp; + __builtin_aarch64_simd_oi __o; + temp.val[0] = vcombine_p8 (tab.val[0], tab.val[1]); + temp.val[1] = vcombine_p8 (tab.val[2], tab.val[3]); + __o = __builtin_aarch64_set_qregoiv16qi (__o, + (int8x16_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, + (int8x16_t) temp.val[1], 1); + result = (poly8x8_t)__builtin_aarch64_tbl3v8qi (__o, (int8x8_t)idx); + return result; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtbx2_s8 (int8x8_t r, int8x8x2_t tab, int8x8_t idx) +{ + int8x8_t result = r; + int8x16_t temp = vcombine_s8 (tab.val[0], tab.val[1]); + __asm__ ("tbx %0.8b, {%1.16b}, %2.8b" + : "+w"(result) + : "w"(temp), "w"(idx) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtbx2_u8 (uint8x8_t r, uint8x8x2_t tab, uint8x8_t idx) +{ + uint8x8_t result = r; + uint8x16_t temp = vcombine_u8 (tab.val[0], tab.val[1]); + __asm__ ("tbx %0.8b, {%1.16b}, %2.8b" + : "+w"(result) + : "w"(temp), "w"(idx) + : /* No clobbers */); + return result; +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtbx2_p8 (poly8x8_t r, poly8x8x2_t tab, uint8x8_t idx) +{ + poly8x8_t result = r; + poly8x16_t temp = vcombine_p8 (tab.val[0], tab.val[1]); + __asm__ ("tbx %0.8b, {%1.16b}, %2.8b" + : "+w"(result) + : "w"(temp), "w"(idx) + : /* No clobbers */); + return result; +} + +/* End of temporary inline asm. */ + +/* Start of optimal implementations in approved order. */ + +/* vabd. */ + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabds_f32 (float32_t __a, float32_t __b) +{ + return __builtin_aarch64_fabdsf (__a, __b); +} + +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabdd_f64 (float64_t __a, float64_t __b) +{ + return __builtin_aarch64_fabddf (__a, __b); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabd_f32 (float32x2_t __a, float32x2_t __b) +{ + return __builtin_aarch64_fabdv2sf (__a, __b); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabd_f64 (float64x1_t __a, float64x1_t __b) +{ + return (float64x1_t) {vabdd_f64 (vget_lane_f64 (__a, 0), + vget_lane_f64 (__b, 0))}; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabdq_f32 (float32x4_t __a, float32x4_t __b) +{ + return __builtin_aarch64_fabdv4sf (__a, __b); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabdq_f64 (float64x2_t __a, float64x2_t __b) +{ + return __builtin_aarch64_fabdv2df (__a, __b); +} + +/* vabs */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabs_f32 (float32x2_t __a) +{ + return __builtin_aarch64_absv2sf (__a); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabs_f64 (float64x1_t __a) +{ + return (float64x1_t) {__builtin_fabs (__a[0])}; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabs_s8 (int8x8_t __a) +{ + return __builtin_aarch64_absv8qi (__a); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabs_s16 (int16x4_t __a) +{ + return __builtin_aarch64_absv4hi (__a); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabs_s32 (int32x2_t __a) +{ + return __builtin_aarch64_absv2si (__a); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabs_s64 (int64x1_t __a) +{ + return (int64x1_t) {__builtin_aarch64_absdi (__a[0])}; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabsq_f32 (float32x4_t __a) +{ + return __builtin_aarch64_absv4sf (__a); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabsq_f64 (float64x2_t __a) +{ + return __builtin_aarch64_absv2df (__a); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabsq_s8 (int8x16_t __a) +{ + return __builtin_aarch64_absv16qi (__a); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabsq_s16 (int16x8_t __a) +{ + return __builtin_aarch64_absv8hi (__a); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabsq_s32 (int32x4_t __a) +{ + return __builtin_aarch64_absv4si (__a); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabsq_s64 (int64x2_t __a) +{ + return __builtin_aarch64_absv2di (__a); +} + +/* Try to avoid moving between integer and vector registers. + For why the cast to unsigned is needed check the vnegd_s64 intrinsic. + There is a testcase related to this issue: + gcc.target/aarch64/vabsd_s64.c. */ + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabsd_s64 (int64_t __a) +{ + return __a < 0 ? - (uint64_t) __a : __a; +} + +/* vadd */ + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddd_s64 (int64_t __a, int64_t __b) +{ + return __a + __b; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddd_u64 (uint64_t __a, uint64_t __b) +{ + return __a + __b; +} + +/* vaddv */ + +__extension__ extern __inline int8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddv_s8 (int8x8_t __a) +{ + return __builtin_aarch64_reduc_plus_scal_v8qi (__a); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddv_s16 (int16x4_t __a) +{ + return __builtin_aarch64_reduc_plus_scal_v4hi (__a); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddv_s32 (int32x2_t __a) +{ + return __builtin_aarch64_reduc_plus_scal_v2si (__a); +} + +__extension__ extern __inline uint8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddv_u8 (uint8x8_t __a) +{ + return (uint8_t) __builtin_aarch64_reduc_plus_scal_v8qi ((int8x8_t) __a); +} + +__extension__ extern __inline uint16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddv_u16 (uint16x4_t __a) +{ + return (uint16_t) __builtin_aarch64_reduc_plus_scal_v4hi ((int16x4_t) __a); +} + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddv_u32 (uint32x2_t __a) +{ + return (int32_t) __builtin_aarch64_reduc_plus_scal_v2si ((int32x2_t) __a); +} + +__extension__ extern __inline int8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddvq_s8 (int8x16_t __a) +{ + return __builtin_aarch64_reduc_plus_scal_v16qi (__a); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddvq_s16 (int16x8_t __a) +{ + return __builtin_aarch64_reduc_plus_scal_v8hi (__a); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddvq_s32 (int32x4_t __a) +{ + return __builtin_aarch64_reduc_plus_scal_v4si (__a); +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddvq_s64 (int64x2_t __a) +{ + return __builtin_aarch64_reduc_plus_scal_v2di (__a); +} + +__extension__ extern __inline uint8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddvq_u8 (uint8x16_t __a) +{ + return (uint8_t) __builtin_aarch64_reduc_plus_scal_v16qi ((int8x16_t) __a); +} + +__extension__ extern __inline uint16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddvq_u16 (uint16x8_t __a) +{ + return (uint16_t) __builtin_aarch64_reduc_plus_scal_v8hi ((int16x8_t) __a); +} + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddvq_u32 (uint32x4_t __a) +{ + return (uint32_t) __builtin_aarch64_reduc_plus_scal_v4si ((int32x4_t) __a); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddvq_u64 (uint64x2_t __a) +{ + return (uint64_t) __builtin_aarch64_reduc_plus_scal_v2di ((int64x2_t) __a); +} + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddv_f32 (float32x2_t __a) +{ + return __builtin_aarch64_reduc_plus_scal_v2sf (__a); +} + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddvq_f32 (float32x4_t __a) +{ + return __builtin_aarch64_reduc_plus_scal_v4sf (__a); +} + +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddvq_f64 (float64x2_t __a) +{ + return __builtin_aarch64_reduc_plus_scal_v2df (__a); +} + +/* vbsl */ + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbsl_f16 (uint16x4_t __a, float16x4_t __b, float16x4_t __c) +{ + return __builtin_aarch64_simd_bslv4hf_suss (__a, __b, __c); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbsl_f32 (uint32x2_t __a, float32x2_t __b, float32x2_t __c) +{ + return __builtin_aarch64_simd_bslv2sf_suss (__a, __b, __c); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbsl_f64 (uint64x1_t __a, float64x1_t __b, float64x1_t __c) +{ + return (float64x1_t) + { __builtin_aarch64_simd_bsldf_suss (__a[0], __b[0], __c[0]) }; +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbsl_p8 (uint8x8_t __a, poly8x8_t __b, poly8x8_t __c) +{ + return __builtin_aarch64_simd_bslv8qi_pupp (__a, __b, __c); +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbsl_p16 (uint16x4_t __a, poly16x4_t __b, poly16x4_t __c) +{ + return __builtin_aarch64_simd_bslv4hi_pupp (__a, __b, __c); +} +__extension__ extern __inline poly64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbsl_p64 (uint64x1_t __a, poly64x1_t __b, poly64x1_t __c) +{ + return (poly64x1_t) + {__builtin_aarch64_simd_bsldi_pupp (__a[0], __b[0], __c[0])}; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbsl_s8 (uint8x8_t __a, int8x8_t __b, int8x8_t __c) +{ + return __builtin_aarch64_simd_bslv8qi_suss (__a, __b, __c); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbsl_s16 (uint16x4_t __a, int16x4_t __b, int16x4_t __c) +{ + return __builtin_aarch64_simd_bslv4hi_suss (__a, __b, __c); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbsl_s32 (uint32x2_t __a, int32x2_t __b, int32x2_t __c) +{ + return __builtin_aarch64_simd_bslv2si_suss (__a, __b, __c); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbsl_s64 (uint64x1_t __a, int64x1_t __b, int64x1_t __c) +{ + return (int64x1_t) + {__builtin_aarch64_simd_bsldi_suss (__a[0], __b[0], __c[0])}; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbsl_u8 (uint8x8_t __a, uint8x8_t __b, uint8x8_t __c) +{ + return __builtin_aarch64_simd_bslv8qi_uuuu (__a, __b, __c); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbsl_u16 (uint16x4_t __a, uint16x4_t __b, uint16x4_t __c) +{ + return __builtin_aarch64_simd_bslv4hi_uuuu (__a, __b, __c); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbsl_u32 (uint32x2_t __a, uint32x2_t __b, uint32x2_t __c) +{ + return __builtin_aarch64_simd_bslv2si_uuuu (__a, __b, __c); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbsl_u64 (uint64x1_t __a, uint64x1_t __b, uint64x1_t __c) +{ + return (uint64x1_t) + {__builtin_aarch64_simd_bsldi_uuuu (__a[0], __b[0], __c[0])}; +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbslq_f16 (uint16x8_t __a, float16x8_t __b, float16x8_t __c) +{ + return __builtin_aarch64_simd_bslv8hf_suss (__a, __b, __c); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbslq_f32 (uint32x4_t __a, float32x4_t __b, float32x4_t __c) +{ + return __builtin_aarch64_simd_bslv4sf_suss (__a, __b, __c); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbslq_f64 (uint64x2_t __a, float64x2_t __b, float64x2_t __c) +{ + return __builtin_aarch64_simd_bslv2df_suss (__a, __b, __c); +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbslq_p8 (uint8x16_t __a, poly8x16_t __b, poly8x16_t __c) +{ + return __builtin_aarch64_simd_bslv16qi_pupp (__a, __b, __c); +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbslq_p16 (uint16x8_t __a, poly16x8_t __b, poly16x8_t __c) +{ + return __builtin_aarch64_simd_bslv8hi_pupp (__a, __b, __c); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbslq_s8 (uint8x16_t __a, int8x16_t __b, int8x16_t __c) +{ + return __builtin_aarch64_simd_bslv16qi_suss (__a, __b, __c); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbslq_s16 (uint16x8_t __a, int16x8_t __b, int16x8_t __c) +{ + return __builtin_aarch64_simd_bslv8hi_suss (__a, __b, __c); +} + +__extension__ extern __inline poly64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbslq_p64 (uint64x2_t __a, poly64x2_t __b, poly64x2_t __c) +{ + return __builtin_aarch64_simd_bslv2di_pupp (__a, __b, __c); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbslq_s32 (uint32x4_t __a, int32x4_t __b, int32x4_t __c) +{ + return __builtin_aarch64_simd_bslv4si_suss (__a, __b, __c); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbslq_s64 (uint64x2_t __a, int64x2_t __b, int64x2_t __c) +{ + return __builtin_aarch64_simd_bslv2di_suss (__a, __b, __c); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbslq_u8 (uint8x16_t __a, uint8x16_t __b, uint8x16_t __c) +{ + return __builtin_aarch64_simd_bslv16qi_uuuu (__a, __b, __c); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbslq_u16 (uint16x8_t __a, uint16x8_t __b, uint16x8_t __c) +{ + return __builtin_aarch64_simd_bslv8hi_uuuu (__a, __b, __c); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbslq_u32 (uint32x4_t __a, uint32x4_t __b, uint32x4_t __c) +{ + return __builtin_aarch64_simd_bslv4si_uuuu (__a, __b, __c); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbslq_u64 (uint64x2_t __a, uint64x2_t __b, uint64x2_t __c) +{ + return __builtin_aarch64_simd_bslv2di_uuuu (__a, __b, __c); +} + +/* ARMv8.1-A instrinsics. */ +#pragma GCC push_options +#pragma GCC target ("+nothing+rdma") + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlah_s16 (int16x4_t __a, int16x4_t __b, int16x4_t __c) +{ + return __builtin_aarch64_sqrdmlahv4hi (__a, __b, __c); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlah_s32 (int32x2_t __a, int32x2_t __b, int32x2_t __c) +{ + return __builtin_aarch64_sqrdmlahv2si (__a, __b, __c); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlahq_s16 (int16x8_t __a, int16x8_t __b, int16x8_t __c) +{ + return __builtin_aarch64_sqrdmlahv8hi (__a, __b, __c); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlahq_s32 (int32x4_t __a, int32x4_t __b, int32x4_t __c) +{ + return __builtin_aarch64_sqrdmlahv4si (__a, __b, __c); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlsh_s16 (int16x4_t __a, int16x4_t __b, int16x4_t __c) +{ + return __builtin_aarch64_sqrdmlshv4hi (__a, __b, __c); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlsh_s32 (int32x2_t __a, int32x2_t __b, int32x2_t __c) +{ + return __builtin_aarch64_sqrdmlshv2si (__a, __b, __c); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlshq_s16 (int16x8_t __a, int16x8_t __b, int16x8_t __c) +{ + return __builtin_aarch64_sqrdmlshv8hi (__a, __b, __c); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlshq_s32 (int32x4_t __a, int32x4_t __b, int32x4_t __c) +{ + return __builtin_aarch64_sqrdmlshv4si (__a, __b, __c); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlah_laneq_s16 (int16x4_t __a, int16x4_t __b, int16x8_t __c, const int __d) +{ + return __builtin_aarch64_sqrdmlah_laneqv4hi (__a, __b, __c, __d); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlah_laneq_s32 (int32x2_t __a, int32x2_t __b, int32x4_t __c, const int __d) +{ + return __builtin_aarch64_sqrdmlah_laneqv2si (__a, __b, __c, __d); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlahq_laneq_s16 (int16x8_t __a, int16x8_t __b, int16x8_t __c, const int __d) +{ + return __builtin_aarch64_sqrdmlah_laneqv8hi (__a, __b, __c, __d); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlahq_laneq_s32 (int32x4_t __a, int32x4_t __b, int32x4_t __c, const int __d) +{ + return __builtin_aarch64_sqrdmlah_laneqv4si (__a, __b, __c, __d); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlsh_laneq_s16 (int16x4_t __a, int16x4_t __b, int16x8_t __c, const int __d) +{ + return __builtin_aarch64_sqrdmlsh_laneqv4hi (__a, __b, __c, __d); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlsh_laneq_s32 (int32x2_t __a, int32x2_t __b, int32x4_t __c, const int __d) +{ + return __builtin_aarch64_sqrdmlsh_laneqv2si (__a, __b, __c, __d); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlshq_laneq_s16 (int16x8_t __a, int16x8_t __b, int16x8_t __c, const int __d) +{ + return __builtin_aarch64_sqrdmlsh_laneqv8hi (__a, __b, __c, __d); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlshq_laneq_s32 (int32x4_t __a, int32x4_t __b, int32x4_t __c, const int __d) +{ + return __builtin_aarch64_sqrdmlsh_laneqv4si (__a, __b, __c, __d); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlah_lane_s16 (int16x4_t __a, int16x4_t __b, int16x4_t __c, const int __d) +{ + return __builtin_aarch64_sqrdmlah_lanev4hi (__a, __b, __c, __d); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlah_lane_s32 (int32x2_t __a, int32x2_t __b, int32x2_t __c, const int __d) +{ + return __builtin_aarch64_sqrdmlah_lanev2si (__a, __b, __c, __d); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlahq_lane_s16 (int16x8_t __a, int16x8_t __b, int16x4_t __c, const int __d) +{ + return __builtin_aarch64_sqrdmlah_lanev8hi (__a, __b, __c, __d); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlahq_lane_s32 (int32x4_t __a, int32x4_t __b, int32x2_t __c, const int __d) +{ + return __builtin_aarch64_sqrdmlah_lanev4si (__a, __b, __c, __d); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlahh_s16 (int16_t __a, int16_t __b, int16_t __c) +{ + return (int16_t) __builtin_aarch64_sqrdmlahhi (__a, __b, __c); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlahh_lane_s16 (int16_t __a, int16_t __b, int16x4_t __c, const int __d) +{ + return __builtin_aarch64_sqrdmlah_lanehi (__a, __b, __c, __d); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlahh_laneq_s16 (int16_t __a, int16_t __b, int16x8_t __c, const int __d) +{ + return __builtin_aarch64_sqrdmlah_laneqhi (__a, __b, __c, __d); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlahs_s32 (int32_t __a, int32_t __b, int32_t __c) +{ + return (int32_t) __builtin_aarch64_sqrdmlahsi (__a, __b, __c); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlahs_lane_s32 (int32_t __a, int32_t __b, int32x2_t __c, const int __d) +{ + return __builtin_aarch64_sqrdmlah_lanesi (__a, __b, __c, __d); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlahs_laneq_s32 (int32_t __a, int32_t __b, int32x4_t __c, const int __d) +{ + return __builtin_aarch64_sqrdmlah_laneqsi (__a, __b, __c, __d); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlsh_lane_s16 (int16x4_t __a, int16x4_t __b, int16x4_t __c, const int __d) +{ + return __builtin_aarch64_sqrdmlsh_lanev4hi (__a, __b, __c, __d); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlsh_lane_s32 (int32x2_t __a, int32x2_t __b, int32x2_t __c, const int __d) +{ + return __builtin_aarch64_sqrdmlsh_lanev2si (__a, __b, __c, __d); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlshq_lane_s16 (int16x8_t __a, int16x8_t __b, int16x4_t __c, const int __d) +{ + return __builtin_aarch64_sqrdmlsh_lanev8hi (__a, __b, __c, __d); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlshq_lane_s32 (int32x4_t __a, int32x4_t __b, int32x2_t __c, const int __d) +{ + return __builtin_aarch64_sqrdmlsh_lanev4si (__a, __b, __c, __d); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlshh_s16 (int16_t __a, int16_t __b, int16_t __c) +{ + return (int16_t) __builtin_aarch64_sqrdmlshhi (__a, __b, __c); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlshh_lane_s16 (int16_t __a, int16_t __b, int16x4_t __c, const int __d) +{ + return __builtin_aarch64_sqrdmlsh_lanehi (__a, __b, __c, __d); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlshh_laneq_s16 (int16_t __a, int16_t __b, int16x8_t __c, const int __d) +{ + return __builtin_aarch64_sqrdmlsh_laneqhi (__a, __b, __c, __d); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlshs_s32 (int32_t __a, int32_t __b, int32_t __c) +{ + return (int32_t) __builtin_aarch64_sqrdmlshsi (__a, __b, __c); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlshs_lane_s32 (int32_t __a, int32_t __b, int32x2_t __c, const int __d) +{ + return __builtin_aarch64_sqrdmlsh_lanesi (__a, __b, __c, __d); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmlshs_laneq_s32 (int32_t __a, int32_t __b, int32x4_t __c, const int __d) +{ + return __builtin_aarch64_sqrdmlsh_laneqsi (__a, __b, __c, __d); +} +#pragma GCC pop_options + +#pragma GCC push_options +#pragma GCC target ("+nothing+crypto") +/* vaes */ + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaeseq_u8 (uint8x16_t data, uint8x16_t key) +{ + return __builtin_aarch64_crypto_aesev16qi_uuu (data, key); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaesdq_u8 (uint8x16_t data, uint8x16_t key) +{ + return __builtin_aarch64_crypto_aesdv16qi_uuu (data, key); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaesmcq_u8 (uint8x16_t data) +{ + return __builtin_aarch64_crypto_aesmcv16qi_uu (data); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaesimcq_u8 (uint8x16_t data) +{ + return __builtin_aarch64_crypto_aesimcv16qi_uu (data); +} +#pragma GCC pop_options + +/* vcage */ + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcage_f64 (float64x1_t __a, float64x1_t __b) +{ + return vabs_f64 (__a) >= vabs_f64 (__b); +} + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcages_f32 (float32_t __a, float32_t __b) +{ + return __builtin_fabsf (__a) >= __builtin_fabsf (__b) ? -1 : 0; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcage_f32 (float32x2_t __a, float32x2_t __b) +{ + return vabs_f32 (__a) >= vabs_f32 (__b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcageq_f32 (float32x4_t __a, float32x4_t __b) +{ + return vabsq_f32 (__a) >= vabsq_f32 (__b); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcaged_f64 (float64_t __a, float64_t __b) +{ + return __builtin_fabs (__a) >= __builtin_fabs (__b) ? -1 : 0; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcageq_f64 (float64x2_t __a, float64x2_t __b) +{ + return vabsq_f64 (__a) >= vabsq_f64 (__b); +} + +/* vcagt */ + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcagts_f32 (float32_t __a, float32_t __b) +{ + return __builtin_fabsf (__a) > __builtin_fabsf (__b) ? -1 : 0; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcagt_f32 (float32x2_t __a, float32x2_t __b) +{ + return vabs_f32 (__a) > vabs_f32 (__b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcagt_f64 (float64x1_t __a, float64x1_t __b) +{ + return vabs_f64 (__a) > vabs_f64 (__b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcagtq_f32 (float32x4_t __a, float32x4_t __b) +{ + return vabsq_f32 (__a) > vabsq_f32 (__b); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcagtd_f64 (float64_t __a, float64_t __b) +{ + return __builtin_fabs (__a) > __builtin_fabs (__b) ? -1 : 0; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcagtq_f64 (float64x2_t __a, float64x2_t __b) +{ + return vabsq_f64 (__a) > vabsq_f64 (__b); +} + +/* vcale */ + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcale_f32 (float32x2_t __a, float32x2_t __b) +{ + return vabs_f32 (__a) <= vabs_f32 (__b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcale_f64 (float64x1_t __a, float64x1_t __b) +{ + return vabs_f64 (__a) <= vabs_f64 (__b); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcaled_f64 (float64_t __a, float64_t __b) +{ + return __builtin_fabs (__a) <= __builtin_fabs (__b) ? -1 : 0; +} + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcales_f32 (float32_t __a, float32_t __b) +{ + return __builtin_fabsf (__a) <= __builtin_fabsf (__b) ? -1 : 0; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcaleq_f32 (float32x4_t __a, float32x4_t __b) +{ + return vabsq_f32 (__a) <= vabsq_f32 (__b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcaleq_f64 (float64x2_t __a, float64x2_t __b) +{ + return vabsq_f64 (__a) <= vabsq_f64 (__b); +} + +/* vcalt */ + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcalt_f32 (float32x2_t __a, float32x2_t __b) +{ + return vabs_f32 (__a) < vabs_f32 (__b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcalt_f64 (float64x1_t __a, float64x1_t __b) +{ + return vabs_f64 (__a) < vabs_f64 (__b); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcaltd_f64 (float64_t __a, float64_t __b) +{ + return __builtin_fabs (__a) < __builtin_fabs (__b) ? -1 : 0; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcaltq_f32 (float32x4_t __a, float32x4_t __b) +{ + return vabsq_f32 (__a) < vabsq_f32 (__b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcaltq_f64 (float64x2_t __a, float64x2_t __b) +{ + return vabsq_f64 (__a) < vabsq_f64 (__b); +} + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcalts_f32 (float32_t __a, float32_t __b) +{ + return __builtin_fabsf (__a) < __builtin_fabsf (__b) ? -1 : 0; +} + +/* vceq - vector. */ + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceq_f32 (float32x2_t __a, float32x2_t __b) +{ + return (uint32x2_t) (__a == __b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceq_f64 (float64x1_t __a, float64x1_t __b) +{ + return (uint64x1_t) (__a == __b); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceq_p8 (poly8x8_t __a, poly8x8_t __b) +{ + return (uint8x8_t) (__a == __b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceq_p64 (poly64x1_t __a, poly64x1_t __b) +{ + return (uint64x1_t) (__a == __b); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceq_s8 (int8x8_t __a, int8x8_t __b) +{ + return (uint8x8_t) (__a == __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceq_s16 (int16x4_t __a, int16x4_t __b) +{ + return (uint16x4_t) (__a == __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceq_s32 (int32x2_t __a, int32x2_t __b) +{ + return (uint32x2_t) (__a == __b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceq_s64 (int64x1_t __a, int64x1_t __b) +{ + return (uint64x1_t) (__a == __b); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceq_u8 (uint8x8_t __a, uint8x8_t __b) +{ + return (__a == __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceq_u16 (uint16x4_t __a, uint16x4_t __b) +{ + return (__a == __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceq_u32 (uint32x2_t __a, uint32x2_t __b) +{ + return (__a == __b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceq_u64 (uint64x1_t __a, uint64x1_t __b) +{ + return (__a == __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqq_f32 (float32x4_t __a, float32x4_t __b) +{ + return (uint32x4_t) (__a == __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqq_f64 (float64x2_t __a, float64x2_t __b) +{ + return (uint64x2_t) (__a == __b); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqq_p8 (poly8x16_t __a, poly8x16_t __b) +{ + return (uint8x16_t) (__a == __b); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqq_s8 (int8x16_t __a, int8x16_t __b) +{ + return (uint8x16_t) (__a == __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqq_s16 (int16x8_t __a, int16x8_t __b) +{ + return (uint16x8_t) (__a == __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqq_s32 (int32x4_t __a, int32x4_t __b) +{ + return (uint32x4_t) (__a == __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqq_s64 (int64x2_t __a, int64x2_t __b) +{ + return (uint64x2_t) (__a == __b); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqq_u8 (uint8x16_t __a, uint8x16_t __b) +{ + return (__a == __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqq_u16 (uint16x8_t __a, uint16x8_t __b) +{ + return (__a == __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqq_u32 (uint32x4_t __a, uint32x4_t __b) +{ + return (__a == __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqq_u64 (uint64x2_t __a, uint64x2_t __b) +{ + return (__a == __b); +} + +/* vceq - scalar. */ + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqs_f32 (float32_t __a, float32_t __b) +{ + return __a == __b ? -1 : 0; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqd_s64 (int64_t __a, int64_t __b) +{ + return __a == __b ? -1ll : 0ll; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqd_u64 (uint64_t __a, uint64_t __b) +{ + return __a == __b ? -1ll : 0ll; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqd_f64 (float64_t __a, float64_t __b) +{ + return __a == __b ? -1ll : 0ll; +} + +/* vceqz - vector. */ + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqz_f32 (float32x2_t __a) +{ + return (uint32x2_t) (__a == 0.0f); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqz_f64 (float64x1_t __a) +{ + return (uint64x1_t) (__a == (float64x1_t) {0.0}); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqz_p8 (poly8x8_t __a) +{ + return (uint8x8_t) (__a == 0); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqz_s8 (int8x8_t __a) +{ + return (uint8x8_t) (__a == 0); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqz_s16 (int16x4_t __a) +{ + return (uint16x4_t) (__a == 0); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqz_s32 (int32x2_t __a) +{ + return (uint32x2_t) (__a == 0); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqz_s64 (int64x1_t __a) +{ + return (uint64x1_t) (__a == __AARCH64_INT64_C (0)); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqz_u8 (uint8x8_t __a) +{ + return (__a == 0); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqz_u16 (uint16x4_t __a) +{ + return (__a == 0); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqz_u32 (uint32x2_t __a) +{ + return (__a == 0); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqz_u64 (uint64x1_t __a) +{ + return (__a == __AARCH64_UINT64_C (0)); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqzq_f32 (float32x4_t __a) +{ + return (uint32x4_t) (__a == 0.0f); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqzq_f64 (float64x2_t __a) +{ + return (uint64x2_t) (__a == 0.0f); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqzq_p8 (poly8x16_t __a) +{ + return (uint8x16_t) (__a == 0); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqzq_s8 (int8x16_t __a) +{ + return (uint8x16_t) (__a == 0); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqzq_s16 (int16x8_t __a) +{ + return (uint16x8_t) (__a == 0); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqzq_s32 (int32x4_t __a) +{ + return (uint32x4_t) (__a == 0); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqzq_s64 (int64x2_t __a) +{ + return (uint64x2_t) (__a == __AARCH64_INT64_C (0)); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqzq_u8 (uint8x16_t __a) +{ + return (__a == 0); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqzq_u16 (uint16x8_t __a) +{ + return (__a == 0); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqzq_u32 (uint32x4_t __a) +{ + return (__a == 0); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqzq_u64 (uint64x2_t __a) +{ + return (__a == __AARCH64_UINT64_C (0)); +} + +/* vceqz - scalar. */ + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqzs_f32 (float32_t __a) +{ + return __a == 0.0f ? -1 : 0; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqzd_s64 (int64_t __a) +{ + return __a == 0 ? -1ll : 0ll; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqzd_u64 (uint64_t __a) +{ + return __a == 0 ? -1ll : 0ll; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqzd_f64 (float64_t __a) +{ + return __a == 0.0 ? -1ll : 0ll; +} + +/* vcge - vector. */ + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcge_f32 (float32x2_t __a, float32x2_t __b) +{ + return (uint32x2_t) (__a >= __b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcge_f64 (float64x1_t __a, float64x1_t __b) +{ + return (uint64x1_t) (__a >= __b); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcge_s8 (int8x8_t __a, int8x8_t __b) +{ + return (uint8x8_t) (__a >= __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcge_s16 (int16x4_t __a, int16x4_t __b) +{ + return (uint16x4_t) (__a >= __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcge_s32 (int32x2_t __a, int32x2_t __b) +{ + return (uint32x2_t) (__a >= __b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcge_s64 (int64x1_t __a, int64x1_t __b) +{ + return (uint64x1_t) (__a >= __b); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcge_u8 (uint8x8_t __a, uint8x8_t __b) +{ + return (__a >= __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcge_u16 (uint16x4_t __a, uint16x4_t __b) +{ + return (__a >= __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcge_u32 (uint32x2_t __a, uint32x2_t __b) +{ + return (__a >= __b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcge_u64 (uint64x1_t __a, uint64x1_t __b) +{ + return (__a >= __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgeq_f32 (float32x4_t __a, float32x4_t __b) +{ + return (uint32x4_t) (__a >= __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgeq_f64 (float64x2_t __a, float64x2_t __b) +{ + return (uint64x2_t) (__a >= __b); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgeq_s8 (int8x16_t __a, int8x16_t __b) +{ + return (uint8x16_t) (__a >= __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgeq_s16 (int16x8_t __a, int16x8_t __b) +{ + return (uint16x8_t) (__a >= __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgeq_s32 (int32x4_t __a, int32x4_t __b) +{ + return (uint32x4_t) (__a >= __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgeq_s64 (int64x2_t __a, int64x2_t __b) +{ + return (uint64x2_t) (__a >= __b); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgeq_u8 (uint8x16_t __a, uint8x16_t __b) +{ + return (__a >= __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgeq_u16 (uint16x8_t __a, uint16x8_t __b) +{ + return (__a >= __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgeq_u32 (uint32x4_t __a, uint32x4_t __b) +{ + return (__a >= __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgeq_u64 (uint64x2_t __a, uint64x2_t __b) +{ + return (__a >= __b); +} + +/* vcge - scalar. */ + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcges_f32 (float32_t __a, float32_t __b) +{ + return __a >= __b ? -1 : 0; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcged_s64 (int64_t __a, int64_t __b) +{ + return __a >= __b ? -1ll : 0ll; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcged_u64 (uint64_t __a, uint64_t __b) +{ + return __a >= __b ? -1ll : 0ll; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcged_f64 (float64_t __a, float64_t __b) +{ + return __a >= __b ? -1ll : 0ll; +} + +/* vcgez - vector. */ + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgez_f32 (float32x2_t __a) +{ + return (uint32x2_t) (__a >= 0.0f); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgez_f64 (float64x1_t __a) +{ + return (uint64x1_t) (__a[0] >= (float64x1_t) {0.0}); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgez_s8 (int8x8_t __a) +{ + return (uint8x8_t) (__a >= 0); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgez_s16 (int16x4_t __a) +{ + return (uint16x4_t) (__a >= 0); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgez_s32 (int32x2_t __a) +{ + return (uint32x2_t) (__a >= 0); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgez_s64 (int64x1_t __a) +{ + return (uint64x1_t) (__a >= __AARCH64_INT64_C (0)); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgezq_f32 (float32x4_t __a) +{ + return (uint32x4_t) (__a >= 0.0f); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgezq_f64 (float64x2_t __a) +{ + return (uint64x2_t) (__a >= 0.0); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgezq_s8 (int8x16_t __a) +{ + return (uint8x16_t) (__a >= 0); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgezq_s16 (int16x8_t __a) +{ + return (uint16x8_t) (__a >= 0); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgezq_s32 (int32x4_t __a) +{ + return (uint32x4_t) (__a >= 0); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgezq_s64 (int64x2_t __a) +{ + return (uint64x2_t) (__a >= __AARCH64_INT64_C (0)); +} + +/* vcgez - scalar. */ + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgezs_f32 (float32_t __a) +{ + return __a >= 0.0f ? -1 : 0; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgezd_s64 (int64_t __a) +{ + return __a >= 0 ? -1ll : 0ll; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgezd_f64 (float64_t __a) +{ + return __a >= 0.0 ? -1ll : 0ll; +} + +/* vcgt - vector. */ + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgt_f32 (float32x2_t __a, float32x2_t __b) +{ + return (uint32x2_t) (__a > __b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgt_f64 (float64x1_t __a, float64x1_t __b) +{ + return (uint64x1_t) (__a > __b); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgt_s8 (int8x8_t __a, int8x8_t __b) +{ + return (uint8x8_t) (__a > __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgt_s16 (int16x4_t __a, int16x4_t __b) +{ + return (uint16x4_t) (__a > __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgt_s32 (int32x2_t __a, int32x2_t __b) +{ + return (uint32x2_t) (__a > __b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgt_s64 (int64x1_t __a, int64x1_t __b) +{ + return (uint64x1_t) (__a > __b); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgt_u8 (uint8x8_t __a, uint8x8_t __b) +{ + return (__a > __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgt_u16 (uint16x4_t __a, uint16x4_t __b) +{ + return (__a > __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgt_u32 (uint32x2_t __a, uint32x2_t __b) +{ + return (__a > __b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgt_u64 (uint64x1_t __a, uint64x1_t __b) +{ + return (__a > __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgtq_f32 (float32x4_t __a, float32x4_t __b) +{ + return (uint32x4_t) (__a > __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgtq_f64 (float64x2_t __a, float64x2_t __b) +{ + return (uint64x2_t) (__a > __b); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgtq_s8 (int8x16_t __a, int8x16_t __b) +{ + return (uint8x16_t) (__a > __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgtq_s16 (int16x8_t __a, int16x8_t __b) +{ + return (uint16x8_t) (__a > __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgtq_s32 (int32x4_t __a, int32x4_t __b) +{ + return (uint32x4_t) (__a > __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgtq_s64 (int64x2_t __a, int64x2_t __b) +{ + return (uint64x2_t) (__a > __b); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgtq_u8 (uint8x16_t __a, uint8x16_t __b) +{ + return (__a > __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgtq_u16 (uint16x8_t __a, uint16x8_t __b) +{ + return (__a > __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgtq_u32 (uint32x4_t __a, uint32x4_t __b) +{ + return (__a > __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgtq_u64 (uint64x2_t __a, uint64x2_t __b) +{ + return (__a > __b); +} + +/* vcgt - scalar. */ + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgts_f32 (float32_t __a, float32_t __b) +{ + return __a > __b ? -1 : 0; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgtd_s64 (int64_t __a, int64_t __b) +{ + return __a > __b ? -1ll : 0ll; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgtd_u64 (uint64_t __a, uint64_t __b) +{ + return __a > __b ? -1ll : 0ll; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgtd_f64 (float64_t __a, float64_t __b) +{ + return __a > __b ? -1ll : 0ll; +} + +/* vcgtz - vector. */ + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgtz_f32 (float32x2_t __a) +{ + return (uint32x2_t) (__a > 0.0f); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgtz_f64 (float64x1_t __a) +{ + return (uint64x1_t) (__a > (float64x1_t) {0.0}); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgtz_s8 (int8x8_t __a) +{ + return (uint8x8_t) (__a > 0); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgtz_s16 (int16x4_t __a) +{ + return (uint16x4_t) (__a > 0); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgtz_s32 (int32x2_t __a) +{ + return (uint32x2_t) (__a > 0); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgtz_s64 (int64x1_t __a) +{ + return (uint64x1_t) (__a > __AARCH64_INT64_C (0)); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgtzq_f32 (float32x4_t __a) +{ + return (uint32x4_t) (__a > 0.0f); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgtzq_f64 (float64x2_t __a) +{ + return (uint64x2_t) (__a > 0.0); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgtzq_s8 (int8x16_t __a) +{ + return (uint8x16_t) (__a > 0); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgtzq_s16 (int16x8_t __a) +{ + return (uint16x8_t) (__a > 0); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgtzq_s32 (int32x4_t __a) +{ + return (uint32x4_t) (__a > 0); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgtzq_s64 (int64x2_t __a) +{ + return (uint64x2_t) (__a > __AARCH64_INT64_C (0)); +} + +/* vcgtz - scalar. */ + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgtzs_f32 (float32_t __a) +{ + return __a > 0.0f ? -1 : 0; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgtzd_s64 (int64_t __a) +{ + return __a > 0 ? -1ll : 0ll; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgtzd_f64 (float64_t __a) +{ + return __a > 0.0 ? -1ll : 0ll; +} + +/* vcle - vector. */ + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcle_f32 (float32x2_t __a, float32x2_t __b) +{ + return (uint32x2_t) (__a <= __b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcle_f64 (float64x1_t __a, float64x1_t __b) +{ + return (uint64x1_t) (__a <= __b); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcle_s8 (int8x8_t __a, int8x8_t __b) +{ + return (uint8x8_t) (__a <= __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcle_s16 (int16x4_t __a, int16x4_t __b) +{ + return (uint16x4_t) (__a <= __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcle_s32 (int32x2_t __a, int32x2_t __b) +{ + return (uint32x2_t) (__a <= __b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcle_s64 (int64x1_t __a, int64x1_t __b) +{ + return (uint64x1_t) (__a <= __b); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcle_u8 (uint8x8_t __a, uint8x8_t __b) +{ + return (__a <= __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcle_u16 (uint16x4_t __a, uint16x4_t __b) +{ + return (__a <= __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcle_u32 (uint32x2_t __a, uint32x2_t __b) +{ + return (__a <= __b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcle_u64 (uint64x1_t __a, uint64x1_t __b) +{ + return (__a <= __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcleq_f32 (float32x4_t __a, float32x4_t __b) +{ + return (uint32x4_t) (__a <= __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcleq_f64 (float64x2_t __a, float64x2_t __b) +{ + return (uint64x2_t) (__a <= __b); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcleq_s8 (int8x16_t __a, int8x16_t __b) +{ + return (uint8x16_t) (__a <= __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcleq_s16 (int16x8_t __a, int16x8_t __b) +{ + return (uint16x8_t) (__a <= __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcleq_s32 (int32x4_t __a, int32x4_t __b) +{ + return (uint32x4_t) (__a <= __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcleq_s64 (int64x2_t __a, int64x2_t __b) +{ + return (uint64x2_t) (__a <= __b); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcleq_u8 (uint8x16_t __a, uint8x16_t __b) +{ + return (__a <= __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcleq_u16 (uint16x8_t __a, uint16x8_t __b) +{ + return (__a <= __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcleq_u32 (uint32x4_t __a, uint32x4_t __b) +{ + return (__a <= __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcleq_u64 (uint64x2_t __a, uint64x2_t __b) +{ + return (__a <= __b); +} + +/* vcle - scalar. */ + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcles_f32 (float32_t __a, float32_t __b) +{ + return __a <= __b ? -1 : 0; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcled_s64 (int64_t __a, int64_t __b) +{ + return __a <= __b ? -1ll : 0ll; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcled_u64 (uint64_t __a, uint64_t __b) +{ + return __a <= __b ? -1ll : 0ll; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcled_f64 (float64_t __a, float64_t __b) +{ + return __a <= __b ? -1ll : 0ll; +} + +/* vclez - vector. */ + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclez_f32 (float32x2_t __a) +{ + return (uint32x2_t) (__a <= 0.0f); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclez_f64 (float64x1_t __a) +{ + return (uint64x1_t) (__a <= (float64x1_t) {0.0}); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclez_s8 (int8x8_t __a) +{ + return (uint8x8_t) (__a <= 0); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclez_s16 (int16x4_t __a) +{ + return (uint16x4_t) (__a <= 0); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclez_s32 (int32x2_t __a) +{ + return (uint32x2_t) (__a <= 0); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclez_s64 (int64x1_t __a) +{ + return (uint64x1_t) (__a <= __AARCH64_INT64_C (0)); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclezq_f32 (float32x4_t __a) +{ + return (uint32x4_t) (__a <= 0.0f); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclezq_f64 (float64x2_t __a) +{ + return (uint64x2_t) (__a <= 0.0); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclezq_s8 (int8x16_t __a) +{ + return (uint8x16_t) (__a <= 0); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclezq_s16 (int16x8_t __a) +{ + return (uint16x8_t) (__a <= 0); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclezq_s32 (int32x4_t __a) +{ + return (uint32x4_t) (__a <= 0); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclezq_s64 (int64x2_t __a) +{ + return (uint64x2_t) (__a <= __AARCH64_INT64_C (0)); +} + +/* vclez - scalar. */ + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclezs_f32 (float32_t __a) +{ + return __a <= 0.0f ? -1 : 0; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclezd_s64 (int64_t __a) +{ + return __a <= 0 ? -1ll : 0ll; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclezd_f64 (float64_t __a) +{ + return __a <= 0.0 ? -1ll : 0ll; +} + +/* vclt - vector. */ + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclt_f32 (float32x2_t __a, float32x2_t __b) +{ + return (uint32x2_t) (__a < __b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclt_f64 (float64x1_t __a, float64x1_t __b) +{ + return (uint64x1_t) (__a < __b); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclt_s8 (int8x8_t __a, int8x8_t __b) +{ + return (uint8x8_t) (__a < __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclt_s16 (int16x4_t __a, int16x4_t __b) +{ + return (uint16x4_t) (__a < __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclt_s32 (int32x2_t __a, int32x2_t __b) +{ + return (uint32x2_t) (__a < __b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclt_s64 (int64x1_t __a, int64x1_t __b) +{ + return (uint64x1_t) (__a < __b); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclt_u8 (uint8x8_t __a, uint8x8_t __b) +{ + return (__a < __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclt_u16 (uint16x4_t __a, uint16x4_t __b) +{ + return (__a < __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclt_u32 (uint32x2_t __a, uint32x2_t __b) +{ + return (__a < __b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclt_u64 (uint64x1_t __a, uint64x1_t __b) +{ + return (__a < __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcltq_f32 (float32x4_t __a, float32x4_t __b) +{ + return (uint32x4_t) (__a < __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcltq_f64 (float64x2_t __a, float64x2_t __b) +{ + return (uint64x2_t) (__a < __b); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcltq_s8 (int8x16_t __a, int8x16_t __b) +{ + return (uint8x16_t) (__a < __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcltq_s16 (int16x8_t __a, int16x8_t __b) +{ + return (uint16x8_t) (__a < __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcltq_s32 (int32x4_t __a, int32x4_t __b) +{ + return (uint32x4_t) (__a < __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcltq_s64 (int64x2_t __a, int64x2_t __b) +{ + return (uint64x2_t) (__a < __b); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcltq_u8 (uint8x16_t __a, uint8x16_t __b) +{ + return (__a < __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcltq_u16 (uint16x8_t __a, uint16x8_t __b) +{ + return (__a < __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcltq_u32 (uint32x4_t __a, uint32x4_t __b) +{ + return (__a < __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcltq_u64 (uint64x2_t __a, uint64x2_t __b) +{ + return (__a < __b); +} + +/* vclt - scalar. */ + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclts_f32 (float32_t __a, float32_t __b) +{ + return __a < __b ? -1 : 0; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcltd_s64 (int64_t __a, int64_t __b) +{ + return __a < __b ? -1ll : 0ll; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcltd_u64 (uint64_t __a, uint64_t __b) +{ + return __a < __b ? -1ll : 0ll; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcltd_f64 (float64_t __a, float64_t __b) +{ + return __a < __b ? -1ll : 0ll; +} + +/* vcltz - vector. */ + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcltz_f32 (float32x2_t __a) +{ + return (uint32x2_t) (__a < 0.0f); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcltz_f64 (float64x1_t __a) +{ + return (uint64x1_t) (__a < (float64x1_t) {0.0}); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcltz_s8 (int8x8_t __a) +{ + return (uint8x8_t) (__a < 0); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcltz_s16 (int16x4_t __a) +{ + return (uint16x4_t) (__a < 0); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcltz_s32 (int32x2_t __a) +{ + return (uint32x2_t) (__a < 0); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcltz_s64 (int64x1_t __a) +{ + return (uint64x1_t) (__a < __AARCH64_INT64_C (0)); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcltzq_f32 (float32x4_t __a) +{ + return (uint32x4_t) (__a < 0.0f); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcltzq_f64 (float64x2_t __a) +{ + return (uint64x2_t) (__a < 0.0); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcltzq_s8 (int8x16_t __a) +{ + return (uint8x16_t) (__a < 0); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcltzq_s16 (int16x8_t __a) +{ + return (uint16x8_t) (__a < 0); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcltzq_s32 (int32x4_t __a) +{ + return (uint32x4_t) (__a < 0); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcltzq_s64 (int64x2_t __a) +{ + return (uint64x2_t) (__a < __AARCH64_INT64_C (0)); +} + +/* vcltz - scalar. */ + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcltzs_f32 (float32_t __a) +{ + return __a < 0.0f ? -1 : 0; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcltzd_s64 (int64_t __a) +{ + return __a < 0 ? -1ll : 0ll; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcltzd_f64 (float64_t __a) +{ + return __a < 0.0 ? -1ll : 0ll; +} + +/* vcls. */ + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcls_s8 (int8x8_t __a) +{ + return __builtin_aarch64_clrsbv8qi (__a); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcls_s16 (int16x4_t __a) +{ + return __builtin_aarch64_clrsbv4hi (__a); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcls_s32 (int32x2_t __a) +{ + return __builtin_aarch64_clrsbv2si (__a); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclsq_s8 (int8x16_t __a) +{ + return __builtin_aarch64_clrsbv16qi (__a); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclsq_s16 (int16x8_t __a) +{ + return __builtin_aarch64_clrsbv8hi (__a); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclsq_s32 (int32x4_t __a) +{ + return __builtin_aarch64_clrsbv4si (__a); +} + +/* vclz. */ + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclz_s8 (int8x8_t __a) +{ + return __builtin_aarch64_clzv8qi (__a); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclz_s16 (int16x4_t __a) +{ + return __builtin_aarch64_clzv4hi (__a); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclz_s32 (int32x2_t __a) +{ + return __builtin_aarch64_clzv2si (__a); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclz_u8 (uint8x8_t __a) +{ + return (uint8x8_t)__builtin_aarch64_clzv8qi ((int8x8_t)__a); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclz_u16 (uint16x4_t __a) +{ + return (uint16x4_t)__builtin_aarch64_clzv4hi ((int16x4_t)__a); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclz_u32 (uint32x2_t __a) +{ + return (uint32x2_t)__builtin_aarch64_clzv2si ((int32x2_t)__a); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclzq_s8 (int8x16_t __a) +{ + return __builtin_aarch64_clzv16qi (__a); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclzq_s16 (int16x8_t __a) +{ + return __builtin_aarch64_clzv8hi (__a); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclzq_s32 (int32x4_t __a) +{ + return __builtin_aarch64_clzv4si (__a); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclzq_u8 (uint8x16_t __a) +{ + return (uint8x16_t)__builtin_aarch64_clzv16qi ((int8x16_t)__a); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclzq_u16 (uint16x8_t __a) +{ + return (uint16x8_t)__builtin_aarch64_clzv8hi ((int16x8_t)__a); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclzq_u32 (uint32x4_t __a) +{ + return (uint32x4_t)__builtin_aarch64_clzv4si ((int32x4_t)__a); +} + +/* vcnt. */ + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcnt_p8 (poly8x8_t __a) +{ + return (poly8x8_t) __builtin_aarch64_popcountv8qi ((int8x8_t) __a); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcnt_s8 (int8x8_t __a) +{ + return __builtin_aarch64_popcountv8qi (__a); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcnt_u8 (uint8x8_t __a) +{ + return (uint8x8_t) __builtin_aarch64_popcountv8qi ((int8x8_t) __a); +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcntq_p8 (poly8x16_t __a) +{ + return (poly8x16_t) __builtin_aarch64_popcountv16qi ((int8x16_t) __a); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcntq_s8 (int8x16_t __a) +{ + return __builtin_aarch64_popcountv16qi (__a); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcntq_u8 (uint8x16_t __a) +{ + return (uint8x16_t) __builtin_aarch64_popcountv16qi ((int8x16_t) __a); +} + +/* vcopy_lane. */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopy_lane_f32 (float32x2_t __a, const int __lane1, + float32x2_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopy_lane_f64 (float64x1_t __a, const int __lane1, + float64x1_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopy_lane_p8 (poly8x8_t __a, const int __lane1, + poly8x8_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopy_lane_p16 (poly16x4_t __a, const int __lane1, + poly16x4_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline poly64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopy_lane_p64 (poly64x1_t __a, const int __lane1, + poly64x1_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopy_lane_s8 (int8x8_t __a, const int __lane1, + int8x8_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopy_lane_s16 (int16x4_t __a, const int __lane1, + int16x4_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopy_lane_s32 (int32x2_t __a, const int __lane1, + int32x2_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopy_lane_s64 (int64x1_t __a, const int __lane1, + int64x1_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopy_lane_u8 (uint8x8_t __a, const int __lane1, + uint8x8_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopy_lane_u16 (uint16x4_t __a, const int __lane1, + uint16x4_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopy_lane_u32 (uint32x2_t __a, const int __lane1, + uint32x2_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopy_lane_u64 (uint64x1_t __a, const int __lane1, + uint64x1_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +/* vcopy_laneq. */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopy_laneq_f32 (float32x2_t __a, const int __lane1, + float32x4_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopy_laneq_f64 (float64x1_t __a, const int __lane1, + float64x2_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopy_laneq_p8 (poly8x8_t __a, const int __lane1, + poly8x16_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopy_laneq_p16 (poly16x4_t __a, const int __lane1, + poly16x8_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline poly64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopy_laneq_p64 (poly64x1_t __a, const int __lane1, + poly64x2_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopy_laneq_s8 (int8x8_t __a, const int __lane1, + int8x16_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopy_laneq_s16 (int16x4_t __a, const int __lane1, + int16x8_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopy_laneq_s32 (int32x2_t __a, const int __lane1, + int32x4_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopy_laneq_s64 (int64x1_t __a, const int __lane1, + int64x2_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopy_laneq_u8 (uint8x8_t __a, const int __lane1, + uint8x16_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopy_laneq_u16 (uint16x4_t __a, const int __lane1, + uint16x8_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopy_laneq_u32 (uint32x2_t __a, const int __lane1, + uint32x4_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopy_laneq_u64 (uint64x1_t __a, const int __lane1, + uint64x2_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +/* vcopyq_lane. */ + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopyq_lane_f32 (float32x4_t __a, const int __lane1, + float32x2_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopyq_lane_f64 (float64x2_t __a, const int __lane1, + float64x1_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopyq_lane_p8 (poly8x16_t __a, const int __lane1, + poly8x8_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopyq_lane_p16 (poly16x8_t __a, const int __lane1, + poly16x4_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline poly64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopyq_lane_p64 (poly64x2_t __a, const int __lane1, + poly64x1_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopyq_lane_s8 (int8x16_t __a, const int __lane1, + int8x8_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopyq_lane_s16 (int16x8_t __a, const int __lane1, + int16x4_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopyq_lane_s32 (int32x4_t __a, const int __lane1, + int32x2_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopyq_lane_s64 (int64x2_t __a, const int __lane1, + int64x1_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopyq_lane_u8 (uint8x16_t __a, const int __lane1, + uint8x8_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopyq_lane_u16 (uint16x8_t __a, const int __lane1, + uint16x4_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopyq_lane_u32 (uint32x4_t __a, const int __lane1, + uint32x2_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopyq_lane_u64 (uint64x2_t __a, const int __lane1, + uint64x1_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +/* vcopyq_laneq. */ + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopyq_laneq_f32 (float32x4_t __a, const int __lane1, + float32x4_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopyq_laneq_f64 (float64x2_t __a, const int __lane1, + float64x2_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopyq_laneq_p8 (poly8x16_t __a, const int __lane1, + poly8x16_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopyq_laneq_p16 (poly16x8_t __a, const int __lane1, + poly16x8_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline poly64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopyq_laneq_p64 (poly64x2_t __a, const int __lane1, + poly64x2_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopyq_laneq_s8 (int8x16_t __a, const int __lane1, + int8x16_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopyq_laneq_s16 (int16x8_t __a, const int __lane1, + int16x8_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopyq_laneq_s32 (int32x4_t __a, const int __lane1, + int32x4_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopyq_laneq_s64 (int64x2_t __a, const int __lane1, + int64x2_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopyq_laneq_u8 (uint8x16_t __a, const int __lane1, + uint8x16_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopyq_laneq_u16 (uint16x8_t __a, const int __lane1, + uint16x8_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopyq_laneq_u32 (uint32x4_t __a, const int __lane1, + uint32x4_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcopyq_laneq_u64 (uint64x2_t __a, const int __lane1, + uint64x2_t __b, const int __lane2) +{ + return __aarch64_vset_lane_any (__aarch64_vget_lane_any (__b, __lane2), + __a, __lane1); +} + +/* vcvt (double -> float). */ + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_f16_f32 (float32x4_t __a) +{ + return __builtin_aarch64_float_truncate_lo_v4hf (__a); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_high_f16_f32 (float16x4_t __a, float32x4_t __b) +{ + return __builtin_aarch64_float_truncate_hi_v8hf (__a, __b); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_f32_f64 (float64x2_t __a) +{ + return __builtin_aarch64_float_truncate_lo_v2sf (__a); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_high_f32_f64 (float32x2_t __a, float64x2_t __b) +{ + return __builtin_aarch64_float_truncate_hi_v4sf (__a, __b); +} + +/* vcvt (float -> double). */ + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_f32_f16 (float16x4_t __a) +{ + return __builtin_aarch64_float_extend_lo_v4sf (__a); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_f64_f32 (float32x2_t __a) +{ + + return __builtin_aarch64_float_extend_lo_v2df (__a); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_high_f32_f16 (float16x8_t __a) +{ + return __builtin_aarch64_vec_unpacks_hi_v8hf (__a); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_high_f64_f32 (float32x4_t __a) +{ + return __builtin_aarch64_vec_unpacks_hi_v4sf (__a); +} + +/* vcvt (fixed-point -> float). */ + +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtd_n_f64_s64 (int64_t __a, const int __b) +{ + return __builtin_aarch64_scvtfdi (__a, __b); +} + +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtd_n_f64_u64 (uint64_t __a, const int __b) +{ + return __builtin_aarch64_ucvtfdi_sus (__a, __b); +} + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvts_n_f32_s32 (int32_t __a, const int __b) +{ + return __builtin_aarch64_scvtfsi (__a, __b); +} + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvts_n_f32_u32 (uint32_t __a, const int __b) +{ + return __builtin_aarch64_ucvtfsi_sus (__a, __b); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_n_f32_s32 (int32x2_t __a, const int __b) +{ + return __builtin_aarch64_scvtfv2si (__a, __b); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_n_f32_u32 (uint32x2_t __a, const int __b) +{ + return __builtin_aarch64_ucvtfv2si_sus (__a, __b); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_n_f64_s64 (int64x1_t __a, const int __b) +{ + return (float64x1_t) + { __builtin_aarch64_scvtfdi (vget_lane_s64 (__a, 0), __b) }; +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_n_f64_u64 (uint64x1_t __a, const int __b) +{ + return (float64x1_t) + { __builtin_aarch64_ucvtfdi_sus (vget_lane_u64 (__a, 0), __b) }; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtq_n_f32_s32 (int32x4_t __a, const int __b) +{ + return __builtin_aarch64_scvtfv4si (__a, __b); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtq_n_f32_u32 (uint32x4_t __a, const int __b) +{ + return __builtin_aarch64_ucvtfv4si_sus (__a, __b); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtq_n_f64_s64 (int64x2_t __a, const int __b) +{ + return __builtin_aarch64_scvtfv2di (__a, __b); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtq_n_f64_u64 (uint64x2_t __a, const int __b) +{ + return __builtin_aarch64_ucvtfv2di_sus (__a, __b); +} + +/* vcvt (float -> fixed-point). */ + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtd_n_s64_f64 (float64_t __a, const int __b) +{ + return __builtin_aarch64_fcvtzsdf (__a, __b); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtd_n_u64_f64 (float64_t __a, const int __b) +{ + return __builtin_aarch64_fcvtzudf_uss (__a, __b); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvts_n_s32_f32 (float32_t __a, const int __b) +{ + return __builtin_aarch64_fcvtzssf (__a, __b); +} + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvts_n_u32_f32 (float32_t __a, const int __b) +{ + return __builtin_aarch64_fcvtzusf_uss (__a, __b); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_n_s32_f32 (float32x2_t __a, const int __b) +{ + return __builtin_aarch64_fcvtzsv2sf (__a, __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_n_u32_f32 (float32x2_t __a, const int __b) +{ + return __builtin_aarch64_fcvtzuv2sf_uss (__a, __b); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_n_s64_f64 (float64x1_t __a, const int __b) +{ + return (int64x1_t) + { __builtin_aarch64_fcvtzsdf (vget_lane_f64 (__a, 0), __b) }; +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_n_u64_f64 (float64x1_t __a, const int __b) +{ + return (uint64x1_t) + { __builtin_aarch64_fcvtzudf_uss (vget_lane_f64 (__a, 0), __b) }; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtq_n_s32_f32 (float32x4_t __a, const int __b) +{ + return __builtin_aarch64_fcvtzsv4sf (__a, __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtq_n_u32_f32 (float32x4_t __a, const int __b) +{ + return __builtin_aarch64_fcvtzuv4sf_uss (__a, __b); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtq_n_s64_f64 (float64x2_t __a, const int __b) +{ + return __builtin_aarch64_fcvtzsv2df (__a, __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtq_n_u64_f64 (float64x2_t __a, const int __b) +{ + return __builtin_aarch64_fcvtzuv2df_uss (__a, __b); +} + +/* vcvt (int -> float) */ + +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtd_f64_s64 (int64_t __a) +{ + return (float64_t) __a; +} + +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtd_f64_u64 (uint64_t __a) +{ + return (float64_t) __a; +} + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvts_f32_s32 (int32_t __a) +{ + return (float32_t) __a; +} + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvts_f32_u32 (uint32_t __a) +{ + return (float32_t) __a; +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_f32_s32 (int32x2_t __a) +{ + return __builtin_aarch64_floatv2siv2sf (__a); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_f32_u32 (uint32x2_t __a) +{ + return __builtin_aarch64_floatunsv2siv2sf ((int32x2_t) __a); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_f64_s64 (int64x1_t __a) +{ + return (float64x1_t) { vget_lane_s64 (__a, 0) }; +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_f64_u64 (uint64x1_t __a) +{ + return (float64x1_t) { vget_lane_u64 (__a, 0) }; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtq_f32_s32 (int32x4_t __a) +{ + return __builtin_aarch64_floatv4siv4sf (__a); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtq_f32_u32 (uint32x4_t __a) +{ + return __builtin_aarch64_floatunsv4siv4sf ((int32x4_t) __a); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtq_f64_s64 (int64x2_t __a) +{ + return __builtin_aarch64_floatv2div2df (__a); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtq_f64_u64 (uint64x2_t __a) +{ + return __builtin_aarch64_floatunsv2div2df ((int64x2_t) __a); +} + +/* vcvt (float -> int) */ + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtd_s64_f64 (float64_t __a) +{ + return (int64_t) __a; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtd_u64_f64 (float64_t __a) +{ + return (uint64_t) __a; +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvts_s32_f32 (float32_t __a) +{ + return (int32_t) __a; +} + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvts_u32_f32 (float32_t __a) +{ + return (uint32_t) __a; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_s32_f32 (float32x2_t __a) +{ + return __builtin_aarch64_lbtruncv2sfv2si (__a); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_u32_f32 (float32x2_t __a) +{ + return __builtin_aarch64_lbtruncuv2sfv2si_us (__a); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtq_s32_f32 (float32x4_t __a) +{ + return __builtin_aarch64_lbtruncv4sfv4si (__a); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtq_u32_f32 (float32x4_t __a) +{ + return __builtin_aarch64_lbtruncuv4sfv4si_us (__a); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_s64_f64 (float64x1_t __a) +{ + return (int64x1_t) {vcvtd_s64_f64 (__a[0])}; +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_u64_f64 (float64x1_t __a) +{ + return (uint64x1_t) {vcvtd_u64_f64 (__a[0])}; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtq_s64_f64 (float64x2_t __a) +{ + return __builtin_aarch64_lbtruncv2dfv2di (__a); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtq_u64_f64 (float64x2_t __a) +{ + return __builtin_aarch64_lbtruncuv2dfv2di_us (__a); +} + +/* vcvta */ + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtad_s64_f64 (float64_t __a) +{ + return __builtin_aarch64_lrounddfdi (__a); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtad_u64_f64 (float64_t __a) +{ + return __builtin_aarch64_lroundudfdi_us (__a); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtas_s32_f32 (float32_t __a) +{ + return __builtin_aarch64_lroundsfsi (__a); +} + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtas_u32_f32 (float32_t __a) +{ + return __builtin_aarch64_lroundusfsi_us (__a); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvta_s32_f32 (float32x2_t __a) +{ + return __builtin_aarch64_lroundv2sfv2si (__a); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvta_u32_f32 (float32x2_t __a) +{ + return __builtin_aarch64_lrounduv2sfv2si_us (__a); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtaq_s32_f32 (float32x4_t __a) +{ + return __builtin_aarch64_lroundv4sfv4si (__a); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtaq_u32_f32 (float32x4_t __a) +{ + return __builtin_aarch64_lrounduv4sfv4si_us (__a); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvta_s64_f64 (float64x1_t __a) +{ + return (int64x1_t) {vcvtad_s64_f64 (__a[0])}; +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvta_u64_f64 (float64x1_t __a) +{ + return (uint64x1_t) {vcvtad_u64_f64 (__a[0])}; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtaq_s64_f64 (float64x2_t __a) +{ + return __builtin_aarch64_lroundv2dfv2di (__a); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtaq_u64_f64 (float64x2_t __a) +{ + return __builtin_aarch64_lrounduv2dfv2di_us (__a); +} + +/* vcvtm */ + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtmd_s64_f64 (float64_t __a) +{ + return __builtin_llfloor (__a); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtmd_u64_f64 (float64_t __a) +{ + return __builtin_aarch64_lfloorudfdi_us (__a); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtms_s32_f32 (float32_t __a) +{ + return __builtin_ifloorf (__a); +} + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtms_u32_f32 (float32_t __a) +{ + return __builtin_aarch64_lfloorusfsi_us (__a); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtm_s32_f32 (float32x2_t __a) +{ + return __builtin_aarch64_lfloorv2sfv2si (__a); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtm_u32_f32 (float32x2_t __a) +{ + return __builtin_aarch64_lflooruv2sfv2si_us (__a); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtmq_s32_f32 (float32x4_t __a) +{ + return __builtin_aarch64_lfloorv4sfv4si (__a); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtmq_u32_f32 (float32x4_t __a) +{ + return __builtin_aarch64_lflooruv4sfv4si_us (__a); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtm_s64_f64 (float64x1_t __a) +{ + return (int64x1_t) {vcvtmd_s64_f64 (__a[0])}; +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtm_u64_f64 (float64x1_t __a) +{ + return (uint64x1_t) {vcvtmd_u64_f64 (__a[0])}; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtmq_s64_f64 (float64x2_t __a) +{ + return __builtin_aarch64_lfloorv2dfv2di (__a); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtmq_u64_f64 (float64x2_t __a) +{ + return __builtin_aarch64_lflooruv2dfv2di_us (__a); +} + +/* vcvtn */ + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtnd_s64_f64 (float64_t __a) +{ + return __builtin_aarch64_lfrintndfdi (__a); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtnd_u64_f64 (float64_t __a) +{ + return __builtin_aarch64_lfrintnudfdi_us (__a); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtns_s32_f32 (float32_t __a) +{ + return __builtin_aarch64_lfrintnsfsi (__a); +} + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtns_u32_f32 (float32_t __a) +{ + return __builtin_aarch64_lfrintnusfsi_us (__a); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtn_s32_f32 (float32x2_t __a) +{ + return __builtin_aarch64_lfrintnv2sfv2si (__a); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtn_u32_f32 (float32x2_t __a) +{ + return __builtin_aarch64_lfrintnuv2sfv2si_us (__a); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtnq_s32_f32 (float32x4_t __a) +{ + return __builtin_aarch64_lfrintnv4sfv4si (__a); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtnq_u32_f32 (float32x4_t __a) +{ + return __builtin_aarch64_lfrintnuv4sfv4si_us (__a); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtn_s64_f64 (float64x1_t __a) +{ + return (int64x1_t) {vcvtnd_s64_f64 (__a[0])}; +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtn_u64_f64 (float64x1_t __a) +{ + return (uint64x1_t) {vcvtnd_u64_f64 (__a[0])}; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtnq_s64_f64 (float64x2_t __a) +{ + return __builtin_aarch64_lfrintnv2dfv2di (__a); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtnq_u64_f64 (float64x2_t __a) +{ + return __builtin_aarch64_lfrintnuv2dfv2di_us (__a); +} + +/* vcvtp */ + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtpd_s64_f64 (float64_t __a) +{ + return __builtin_llceil (__a); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtpd_u64_f64 (float64_t __a) +{ + return __builtin_aarch64_lceiludfdi_us (__a); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtps_s32_f32 (float32_t __a) +{ + return __builtin_iceilf (__a); +} + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtps_u32_f32 (float32_t __a) +{ + return __builtin_aarch64_lceilusfsi_us (__a); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtp_s32_f32 (float32x2_t __a) +{ + return __builtin_aarch64_lceilv2sfv2si (__a); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtp_u32_f32 (float32x2_t __a) +{ + return __builtin_aarch64_lceiluv2sfv2si_us (__a); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtpq_s32_f32 (float32x4_t __a) +{ + return __builtin_aarch64_lceilv4sfv4si (__a); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtpq_u32_f32 (float32x4_t __a) +{ + return __builtin_aarch64_lceiluv4sfv4si_us (__a); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtp_s64_f64 (float64x1_t __a) +{ + return (int64x1_t) {vcvtpd_s64_f64 (__a[0])}; +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtp_u64_f64 (float64x1_t __a) +{ + return (uint64x1_t) {vcvtpd_u64_f64 (__a[0])}; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtpq_s64_f64 (float64x2_t __a) +{ + return __builtin_aarch64_lceilv2dfv2di (__a); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtpq_u64_f64 (float64x2_t __a) +{ + return __builtin_aarch64_lceiluv2dfv2di_us (__a); +} + +/* vdup_n */ + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_n_f16 (float16_t __a) +{ + return (float16x4_t) {__a, __a, __a, __a}; +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_n_f32 (float32_t __a) +{ + return (float32x2_t) {__a, __a}; +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_n_f64 (float64_t __a) +{ + return (float64x1_t) {__a}; +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_n_p8 (poly8_t __a) +{ + return (poly8x8_t) {__a, __a, __a, __a, __a, __a, __a, __a}; +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_n_p16 (poly16_t __a) +{ + return (poly16x4_t) {__a, __a, __a, __a}; +} + +__extension__ extern __inline poly64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_n_p64 (poly64_t __a) +{ + return (poly64x1_t) {__a}; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_n_s8 (int8_t __a) +{ + return (int8x8_t) {__a, __a, __a, __a, __a, __a, __a, __a}; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_n_s16 (int16_t __a) +{ + return (int16x4_t) {__a, __a, __a, __a}; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_n_s32 (int32_t __a) +{ + return (int32x2_t) {__a, __a}; +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_n_s64 (int64_t __a) +{ + return (int64x1_t) {__a}; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_n_u8 (uint8_t __a) +{ + return (uint8x8_t) {__a, __a, __a, __a, __a, __a, __a, __a}; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_n_u16 (uint16_t __a) +{ + return (uint16x4_t) {__a, __a, __a, __a}; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_n_u32 (uint32_t __a) +{ + return (uint32x2_t) {__a, __a}; +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_n_u64 (uint64_t __a) +{ + return (uint64x1_t) {__a}; +} + +/* vdupq_n */ + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_n_f16 (float16_t __a) +{ + return (float16x8_t) {__a, __a, __a, __a, __a, __a, __a, __a}; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_n_f32 (float32_t __a) +{ + return (float32x4_t) {__a, __a, __a, __a}; +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_n_f64 (float64_t __a) +{ + return (float64x2_t) {__a, __a}; +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_n_p8 (uint32_t __a) +{ + return (poly8x16_t) {__a, __a, __a, __a, __a, __a, __a, __a, + __a, __a, __a, __a, __a, __a, __a, __a}; +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_n_p16 (uint32_t __a) +{ + return (poly16x8_t) {__a, __a, __a, __a, __a, __a, __a, __a}; +} + +__extension__ extern __inline poly64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_n_p64 (uint64_t __a) +{ + return (poly64x2_t) {__a, __a}; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_n_s8 (int32_t __a) +{ + return (int8x16_t) {__a, __a, __a, __a, __a, __a, __a, __a, + __a, __a, __a, __a, __a, __a, __a, __a}; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_n_s16 (int32_t __a) +{ + return (int16x8_t) {__a, __a, __a, __a, __a, __a, __a, __a}; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_n_s32 (int32_t __a) +{ + return (int32x4_t) {__a, __a, __a, __a}; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_n_s64 (int64_t __a) +{ + return (int64x2_t) {__a, __a}; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_n_u8 (uint32_t __a) +{ + return (uint8x16_t) {__a, __a, __a, __a, __a, __a, __a, __a, + __a, __a, __a, __a, __a, __a, __a, __a}; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_n_u16 (uint32_t __a) +{ + return (uint16x8_t) {__a, __a, __a, __a, __a, __a, __a, __a}; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_n_u32 (uint32_t __a) +{ + return (uint32x4_t) {__a, __a, __a, __a}; +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_n_u64 (uint64_t __a) +{ + return (uint64x2_t) {__a, __a}; +} + +/* vdup_lane */ + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_lane_f16 (float16x4_t __a, const int __b) +{ + return __aarch64_vdup_lane_f16 (__a, __b); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_lane_f32 (float32x2_t __a, const int __b) +{ + return __aarch64_vdup_lane_f32 (__a, __b); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_lane_f64 (float64x1_t __a, const int __b) +{ + return __aarch64_vdup_lane_f64 (__a, __b); +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_lane_p8 (poly8x8_t __a, const int __b) +{ + return __aarch64_vdup_lane_p8 (__a, __b); +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_lane_p16 (poly16x4_t __a, const int __b) +{ + return __aarch64_vdup_lane_p16 (__a, __b); +} + +__extension__ extern __inline poly64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_lane_p64 (poly64x1_t __a, const int __b) +{ + return __aarch64_vdup_lane_p64 (__a, __b); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_lane_s8 (int8x8_t __a, const int __b) +{ + return __aarch64_vdup_lane_s8 (__a, __b); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_lane_s16 (int16x4_t __a, const int __b) +{ + return __aarch64_vdup_lane_s16 (__a, __b); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_lane_s32 (int32x2_t __a, const int __b) +{ + return __aarch64_vdup_lane_s32 (__a, __b); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_lane_s64 (int64x1_t __a, const int __b) +{ + return __aarch64_vdup_lane_s64 (__a, __b); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_lane_u8 (uint8x8_t __a, const int __b) +{ + return __aarch64_vdup_lane_u8 (__a, __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_lane_u16 (uint16x4_t __a, const int __b) +{ + return __aarch64_vdup_lane_u16 (__a, __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_lane_u32 (uint32x2_t __a, const int __b) +{ + return __aarch64_vdup_lane_u32 (__a, __b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_lane_u64 (uint64x1_t __a, const int __b) +{ + return __aarch64_vdup_lane_u64 (__a, __b); +} + +/* vdup_laneq */ + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_laneq_f16 (float16x8_t __a, const int __b) +{ + return __aarch64_vdup_laneq_f16 (__a, __b); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_laneq_f32 (float32x4_t __a, const int __b) +{ + return __aarch64_vdup_laneq_f32 (__a, __b); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_laneq_f64 (float64x2_t __a, const int __b) +{ + return __aarch64_vdup_laneq_f64 (__a, __b); +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_laneq_p8 (poly8x16_t __a, const int __b) +{ + return __aarch64_vdup_laneq_p8 (__a, __b); +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_laneq_p16 (poly16x8_t __a, const int __b) +{ + return __aarch64_vdup_laneq_p16 (__a, __b); +} + +__extension__ extern __inline poly64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_laneq_p64 (poly64x2_t __a, const int __b) +{ + return __aarch64_vdup_laneq_p64 (__a, __b); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_laneq_s8 (int8x16_t __a, const int __b) +{ + return __aarch64_vdup_laneq_s8 (__a, __b); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_laneq_s16 (int16x8_t __a, const int __b) +{ + return __aarch64_vdup_laneq_s16 (__a, __b); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_laneq_s32 (int32x4_t __a, const int __b) +{ + return __aarch64_vdup_laneq_s32 (__a, __b); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_laneq_s64 (int64x2_t __a, const int __b) +{ + return __aarch64_vdup_laneq_s64 (__a, __b); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_laneq_u8 (uint8x16_t __a, const int __b) +{ + return __aarch64_vdup_laneq_u8 (__a, __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_laneq_u16 (uint16x8_t __a, const int __b) +{ + return __aarch64_vdup_laneq_u16 (__a, __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_laneq_u32 (uint32x4_t __a, const int __b) +{ + return __aarch64_vdup_laneq_u32 (__a, __b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdup_laneq_u64 (uint64x2_t __a, const int __b) +{ + return __aarch64_vdup_laneq_u64 (__a, __b); +} + +/* vdupq_lane */ + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_lane_f16 (float16x4_t __a, const int __b) +{ + return __aarch64_vdupq_lane_f16 (__a, __b); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_lane_f32 (float32x2_t __a, const int __b) +{ + return __aarch64_vdupq_lane_f32 (__a, __b); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_lane_f64 (float64x1_t __a, const int __b) +{ + return __aarch64_vdupq_lane_f64 (__a, __b); +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_lane_p8 (poly8x8_t __a, const int __b) +{ + return __aarch64_vdupq_lane_p8 (__a, __b); +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_lane_p16 (poly16x4_t __a, const int __b) +{ + return __aarch64_vdupq_lane_p16 (__a, __b); +} + +__extension__ extern __inline poly64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_lane_p64 (poly64x1_t __a, const int __b) +{ + return __aarch64_vdupq_lane_p64 (__a, __b); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_lane_s8 (int8x8_t __a, const int __b) +{ + return __aarch64_vdupq_lane_s8 (__a, __b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_lane_s16 (int16x4_t __a, const int __b) +{ + return __aarch64_vdupq_lane_s16 (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_lane_s32 (int32x2_t __a, const int __b) +{ + return __aarch64_vdupq_lane_s32 (__a, __b); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_lane_s64 (int64x1_t __a, const int __b) +{ + return __aarch64_vdupq_lane_s64 (__a, __b); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_lane_u8 (uint8x8_t __a, const int __b) +{ + return __aarch64_vdupq_lane_u8 (__a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_lane_u16 (uint16x4_t __a, const int __b) +{ + return __aarch64_vdupq_lane_u16 (__a, __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_lane_u32 (uint32x2_t __a, const int __b) +{ + return __aarch64_vdupq_lane_u32 (__a, __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_lane_u64 (uint64x1_t __a, const int __b) +{ + return __aarch64_vdupq_lane_u64 (__a, __b); +} + +/* vdupq_laneq */ + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_laneq_f16 (float16x8_t __a, const int __b) +{ + return __aarch64_vdupq_laneq_f16 (__a, __b); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_laneq_f32 (float32x4_t __a, const int __b) +{ + return __aarch64_vdupq_laneq_f32 (__a, __b); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_laneq_f64 (float64x2_t __a, const int __b) +{ + return __aarch64_vdupq_laneq_f64 (__a, __b); +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_laneq_p8 (poly8x16_t __a, const int __b) +{ + return __aarch64_vdupq_laneq_p8 (__a, __b); +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_laneq_p16 (poly16x8_t __a, const int __b) +{ + return __aarch64_vdupq_laneq_p16 (__a, __b); +} + +__extension__ extern __inline poly64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_laneq_p64 (poly64x2_t __a, const int __b) +{ + return __aarch64_vdupq_laneq_p64 (__a, __b); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_laneq_s8 (int8x16_t __a, const int __b) +{ + return __aarch64_vdupq_laneq_s8 (__a, __b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_laneq_s16 (int16x8_t __a, const int __b) +{ + return __aarch64_vdupq_laneq_s16 (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_laneq_s32 (int32x4_t __a, const int __b) +{ + return __aarch64_vdupq_laneq_s32 (__a, __b); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_laneq_s64 (int64x2_t __a, const int __b) +{ + return __aarch64_vdupq_laneq_s64 (__a, __b); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_laneq_u8 (uint8x16_t __a, const int __b) +{ + return __aarch64_vdupq_laneq_u8 (__a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_laneq_u16 (uint16x8_t __a, const int __b) +{ + return __aarch64_vdupq_laneq_u16 (__a, __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_laneq_u32 (uint32x4_t __a, const int __b) +{ + return __aarch64_vdupq_laneq_u32 (__a, __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupq_laneq_u64 (uint64x2_t __a, const int __b) +{ + return __aarch64_vdupq_laneq_u64 (__a, __b); +} + +/* vdupb_lane */ +__extension__ extern __inline poly8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupb_lane_p8 (poly8x8_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline int8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupb_lane_s8 (int8x8_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline uint8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupb_lane_u8 (uint8x8_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +/* vduph_lane */ + +__extension__ extern __inline float16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vduph_lane_f16 (float16x4_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline poly16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vduph_lane_p16 (poly16x4_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vduph_lane_s16 (int16x4_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline uint16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vduph_lane_u16 (uint16x4_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +/* vdups_lane */ + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdups_lane_f32 (float32x2_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdups_lane_s32 (int32x2_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdups_lane_u32 (uint32x2_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +/* vdupd_lane */ +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupd_lane_f64 (float64x1_t __a, const int __b) +{ + __AARCH64_LANE_CHECK (__a, __b); + return __a[0]; +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupd_lane_s64 (int64x1_t __a, const int __b) +{ + __AARCH64_LANE_CHECK (__a, __b); + return __a[0]; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupd_lane_u64 (uint64x1_t __a, const int __b) +{ + __AARCH64_LANE_CHECK (__a, __b); + return __a[0]; +} + +/* vdupb_laneq */ +__extension__ extern __inline poly8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupb_laneq_p8 (poly8x16_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline int8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupb_laneq_s8 (int8x16_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline uint8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupb_laneq_u8 (uint8x16_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +/* vduph_laneq */ + +__extension__ extern __inline float16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vduph_laneq_f16 (float16x8_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline poly16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vduph_laneq_p16 (poly16x8_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vduph_laneq_s16 (int16x8_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline uint16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vduph_laneq_u16 (uint16x8_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +/* vdups_laneq */ + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdups_laneq_f32 (float32x4_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdups_laneq_s32 (int32x4_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdups_laneq_u32 (uint32x4_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +/* vdupd_laneq */ +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupd_laneq_f64 (float64x2_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupd_laneq_s64 (int64x2_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdupd_laneq_u64 (uint64x2_t __a, const int __b) +{ + return __aarch64_vget_lane_any (__a, __b); +} + +/* vext */ + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vext_f16 (float16x4_t __a, float16x4_t __b, __const int __c) +{ + __AARCH64_LANE_CHECK (__a, __c); +#ifdef __AARCH64EB__ + return __builtin_shuffle (__b, __a, + (uint16x4_t) {4 - __c, 5 - __c, 6 - __c, 7 - __c}); +#else + return __builtin_shuffle (__a, __b, + (uint16x4_t) {__c, __c + 1, __c + 2, __c + 3}); +#endif +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vext_f32 (float32x2_t __a, float32x2_t __b, __const int __c) +{ + __AARCH64_LANE_CHECK (__a, __c); +#ifdef __AARCH64EB__ + return __builtin_shuffle (__b, __a, (uint32x2_t) {2-__c, 3-__c}); +#else + return __builtin_shuffle (__a, __b, (uint32x2_t) {__c, __c+1}); +#endif +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vext_f64 (float64x1_t __a, float64x1_t __b, __const int __c) +{ + __AARCH64_LANE_CHECK (__a, __c); + /* The only possible index to the assembler instruction returns element 0. */ + return __a; +} +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vext_p8 (poly8x8_t __a, poly8x8_t __b, __const int __c) +{ + __AARCH64_LANE_CHECK (__a, __c); +#ifdef __AARCH64EB__ + return __builtin_shuffle (__b, __a, (uint8x8_t) + {8-__c, 9-__c, 10-__c, 11-__c, 12-__c, 13-__c, 14-__c, 15-__c}); +#else + return __builtin_shuffle (__a, __b, + (uint8x8_t) {__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7}); +#endif +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vext_p16 (poly16x4_t __a, poly16x4_t __b, __const int __c) +{ + __AARCH64_LANE_CHECK (__a, __c); +#ifdef __AARCH64EB__ + return __builtin_shuffle (__b, __a, + (uint16x4_t) {4-__c, 5-__c, 6-__c, 7-__c}); +#else + return __builtin_shuffle (__a, __b, (uint16x4_t) {__c, __c+1, __c+2, __c+3}); +#endif +} + +__extension__ extern __inline poly64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vext_p64 (poly64x1_t __a, poly64x1_t __b, __const int __c) +{ + __AARCH64_LANE_CHECK (__a, __c); + /* The only possible index to the assembler instruction returns element 0. */ + return __a; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vext_s8 (int8x8_t __a, int8x8_t __b, __const int __c) +{ + __AARCH64_LANE_CHECK (__a, __c); +#ifdef __AARCH64EB__ + return __builtin_shuffle (__b, __a, (uint8x8_t) + {8-__c, 9-__c, 10-__c, 11-__c, 12-__c, 13-__c, 14-__c, 15-__c}); +#else + return __builtin_shuffle (__a, __b, + (uint8x8_t) {__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7}); +#endif +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vext_s16 (int16x4_t __a, int16x4_t __b, __const int __c) +{ + __AARCH64_LANE_CHECK (__a, __c); +#ifdef __AARCH64EB__ + return __builtin_shuffle (__b, __a, + (uint16x4_t) {4-__c, 5-__c, 6-__c, 7-__c}); +#else + return __builtin_shuffle (__a, __b, (uint16x4_t) {__c, __c+1, __c+2, __c+3}); +#endif +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vext_s32 (int32x2_t __a, int32x2_t __b, __const int __c) +{ + __AARCH64_LANE_CHECK (__a, __c); +#ifdef __AARCH64EB__ + return __builtin_shuffle (__b, __a, (uint32x2_t) {2-__c, 3-__c}); +#else + return __builtin_shuffle (__a, __b, (uint32x2_t) {__c, __c+1}); +#endif +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vext_s64 (int64x1_t __a, int64x1_t __b, __const int __c) +{ + __AARCH64_LANE_CHECK (__a, __c); + /* The only possible index to the assembler instruction returns element 0. */ + return __a; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vext_u8 (uint8x8_t __a, uint8x8_t __b, __const int __c) +{ + __AARCH64_LANE_CHECK (__a, __c); +#ifdef __AARCH64EB__ + return __builtin_shuffle (__b, __a, (uint8x8_t) + {8-__c, 9-__c, 10-__c, 11-__c, 12-__c, 13-__c, 14-__c, 15-__c}); +#else + return __builtin_shuffle (__a, __b, + (uint8x8_t) {__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7}); +#endif +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vext_u16 (uint16x4_t __a, uint16x4_t __b, __const int __c) +{ + __AARCH64_LANE_CHECK (__a, __c); +#ifdef __AARCH64EB__ + return __builtin_shuffle (__b, __a, + (uint16x4_t) {4-__c, 5-__c, 6-__c, 7-__c}); +#else + return __builtin_shuffle (__a, __b, (uint16x4_t) {__c, __c+1, __c+2, __c+3}); +#endif +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vext_u32 (uint32x2_t __a, uint32x2_t __b, __const int __c) +{ + __AARCH64_LANE_CHECK (__a, __c); +#ifdef __AARCH64EB__ + return __builtin_shuffle (__b, __a, (uint32x2_t) {2-__c, 3-__c}); +#else + return __builtin_shuffle (__a, __b, (uint32x2_t) {__c, __c+1}); +#endif +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vext_u64 (uint64x1_t __a, uint64x1_t __b, __const int __c) +{ + __AARCH64_LANE_CHECK (__a, __c); + /* The only possible index to the assembler instruction returns element 0. */ + return __a; +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vextq_f16 (float16x8_t __a, float16x8_t __b, __const int __c) +{ + __AARCH64_LANE_CHECK (__a, __c); +#ifdef __AARCH64EB__ + return __builtin_shuffle (__b, __a, + (uint16x8_t) {8 - __c, 9 - __c, 10 - __c, 11 - __c, + 12 - __c, 13 - __c, 14 - __c, + 15 - __c}); +#else + return __builtin_shuffle (__a, __b, + (uint16x8_t) {__c, __c + 1, __c + 2, __c + 3, + __c + 4, __c + 5, __c + 6, __c + 7}); +#endif +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vextq_f32 (float32x4_t __a, float32x4_t __b, __const int __c) +{ + __AARCH64_LANE_CHECK (__a, __c); +#ifdef __AARCH64EB__ + return __builtin_shuffle (__b, __a, + (uint32x4_t) {4-__c, 5-__c, 6-__c, 7-__c}); +#else + return __builtin_shuffle (__a, __b, (uint32x4_t) {__c, __c+1, __c+2, __c+3}); +#endif +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vextq_f64 (float64x2_t __a, float64x2_t __b, __const int __c) +{ + __AARCH64_LANE_CHECK (__a, __c); +#ifdef __AARCH64EB__ + return __builtin_shuffle (__b, __a, (uint64x2_t) {2-__c, 3-__c}); +#else + return __builtin_shuffle (__a, __b, (uint64x2_t) {__c, __c+1}); +#endif +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vextq_p8 (poly8x16_t __a, poly8x16_t __b, __const int __c) +{ + __AARCH64_LANE_CHECK (__a, __c); +#ifdef __AARCH64EB__ + return __builtin_shuffle (__b, __a, (uint8x16_t) + {16-__c, 17-__c, 18-__c, 19-__c, 20-__c, 21-__c, 22-__c, 23-__c, + 24-__c, 25-__c, 26-__c, 27-__c, 28-__c, 29-__c, 30-__c, 31-__c}); +#else + return __builtin_shuffle (__a, __b, (uint8x16_t) + {__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7, + __c+8, __c+9, __c+10, __c+11, __c+12, __c+13, __c+14, __c+15}); +#endif +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vextq_p16 (poly16x8_t __a, poly16x8_t __b, __const int __c) +{ + __AARCH64_LANE_CHECK (__a, __c); +#ifdef __AARCH64EB__ + return __builtin_shuffle (__b, __a, (uint16x8_t) + {8-__c, 9-__c, 10-__c, 11-__c, 12-__c, 13-__c, 14-__c, 15-__c}); +#else + return __builtin_shuffle (__a, __b, + (uint16x8_t) {__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7}); +#endif +} + +__extension__ extern __inline poly64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vextq_p64 (poly64x2_t __a, poly64x2_t __b, __const int __c) +{ + __AARCH64_LANE_CHECK (__a, __c); +#ifdef __AARCH64EB__ + return __builtin_shuffle (__b, __a, (uint64x2_t) {2-__c, 3-__c}); +#else + return __builtin_shuffle (__a, __b, (uint64x2_t) {__c, __c+1}); +#endif +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vextq_s8 (int8x16_t __a, int8x16_t __b, __const int __c) +{ + __AARCH64_LANE_CHECK (__a, __c); +#ifdef __AARCH64EB__ + return __builtin_shuffle (__b, __a, (uint8x16_t) + {16-__c, 17-__c, 18-__c, 19-__c, 20-__c, 21-__c, 22-__c, 23-__c, + 24-__c, 25-__c, 26-__c, 27-__c, 28-__c, 29-__c, 30-__c, 31-__c}); +#else + return __builtin_shuffle (__a, __b, (uint8x16_t) + {__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7, + __c+8, __c+9, __c+10, __c+11, __c+12, __c+13, __c+14, __c+15}); +#endif +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vextq_s16 (int16x8_t __a, int16x8_t __b, __const int __c) +{ + __AARCH64_LANE_CHECK (__a, __c); +#ifdef __AARCH64EB__ + return __builtin_shuffle (__b, __a, (uint16x8_t) + {8-__c, 9-__c, 10-__c, 11-__c, 12-__c, 13-__c, 14-__c, 15-__c}); +#else + return __builtin_shuffle (__a, __b, + (uint16x8_t) {__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7}); +#endif +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vextq_s32 (int32x4_t __a, int32x4_t __b, __const int __c) +{ + __AARCH64_LANE_CHECK (__a, __c); +#ifdef __AARCH64EB__ + return __builtin_shuffle (__b, __a, + (uint32x4_t) {4-__c, 5-__c, 6-__c, 7-__c}); +#else + return __builtin_shuffle (__a, __b, (uint32x4_t) {__c, __c+1, __c+2, __c+3}); +#endif +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vextq_s64 (int64x2_t __a, int64x2_t __b, __const int __c) +{ + __AARCH64_LANE_CHECK (__a, __c); +#ifdef __AARCH64EB__ + return __builtin_shuffle (__b, __a, (uint64x2_t) {2-__c, 3-__c}); +#else + return __builtin_shuffle (__a, __b, (uint64x2_t) {__c, __c+1}); +#endif +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vextq_u8 (uint8x16_t __a, uint8x16_t __b, __const int __c) +{ + __AARCH64_LANE_CHECK (__a, __c); +#ifdef __AARCH64EB__ + return __builtin_shuffle (__b, __a, (uint8x16_t) + {16-__c, 17-__c, 18-__c, 19-__c, 20-__c, 21-__c, 22-__c, 23-__c, + 24-__c, 25-__c, 26-__c, 27-__c, 28-__c, 29-__c, 30-__c, 31-__c}); +#else + return __builtin_shuffle (__a, __b, (uint8x16_t) + {__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7, + __c+8, __c+9, __c+10, __c+11, __c+12, __c+13, __c+14, __c+15}); +#endif +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vextq_u16 (uint16x8_t __a, uint16x8_t __b, __const int __c) +{ + __AARCH64_LANE_CHECK (__a, __c); +#ifdef __AARCH64EB__ + return __builtin_shuffle (__b, __a, (uint16x8_t) + {8-__c, 9-__c, 10-__c, 11-__c, 12-__c, 13-__c, 14-__c, 15-__c}); +#else + return __builtin_shuffle (__a, __b, + (uint16x8_t) {__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7}); +#endif +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vextq_u32 (uint32x4_t __a, uint32x4_t __b, __const int __c) +{ + __AARCH64_LANE_CHECK (__a, __c); +#ifdef __AARCH64EB__ + return __builtin_shuffle (__b, __a, + (uint32x4_t) {4-__c, 5-__c, 6-__c, 7-__c}); +#else + return __builtin_shuffle (__a, __b, (uint32x4_t) {__c, __c+1, __c+2, __c+3}); +#endif +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vextq_u64 (uint64x2_t __a, uint64x2_t __b, __const int __c) +{ + __AARCH64_LANE_CHECK (__a, __c); +#ifdef __AARCH64EB__ + return __builtin_shuffle (__b, __a, (uint64x2_t) {2-__c, 3-__c}); +#else + return __builtin_shuffle (__a, __b, (uint64x2_t) {__c, __c+1}); +#endif +} + +/* vfma */ + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfma_f64 (float64x1_t __a, float64x1_t __b, float64x1_t __c) +{ + return (float64x1_t) {__builtin_fma (__b[0], __c[0], __a[0])}; +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfma_f32 (float32x2_t __a, float32x2_t __b, float32x2_t __c) +{ + return __builtin_aarch64_fmav2sf (__b, __c, __a); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmaq_f32 (float32x4_t __a, float32x4_t __b, float32x4_t __c) +{ + return __builtin_aarch64_fmav4sf (__b, __c, __a); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmaq_f64 (float64x2_t __a, float64x2_t __b, float64x2_t __c) +{ + return __builtin_aarch64_fmav2df (__b, __c, __a); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfma_n_f32 (float32x2_t __a, float32x2_t __b, float32_t __c) +{ + return __builtin_aarch64_fmav2sf (__b, vdup_n_f32 (__c), __a); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfma_n_f64 (float64x1_t __a, float64x1_t __b, float64_t __c) +{ + return (float64x1_t) {__b[0] * __c + __a[0]}; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmaq_n_f32 (float32x4_t __a, float32x4_t __b, float32_t __c) +{ + return __builtin_aarch64_fmav4sf (__b, vdupq_n_f32 (__c), __a); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmaq_n_f64 (float64x2_t __a, float64x2_t __b, float64_t __c) +{ + return __builtin_aarch64_fmav2df (__b, vdupq_n_f64 (__c), __a); +} + +/* vfma_lane */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfma_lane_f32 (float32x2_t __a, float32x2_t __b, + float32x2_t __c, const int __lane) +{ + return __builtin_aarch64_fmav2sf (__b, + __aarch64_vdup_lane_f32 (__c, __lane), + __a); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfma_lane_f64 (float64x1_t __a, float64x1_t __b, + float64x1_t __c, const int __lane) +{ + return (float64x1_t) {__builtin_fma (__b[0], __c[0], __a[0])}; +} + +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmad_lane_f64 (float64_t __a, float64_t __b, + float64x1_t __c, const int __lane) +{ + return __builtin_fma (__b, __c[0], __a); +} + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmas_lane_f32 (float32_t __a, float32_t __b, + float32x2_t __c, const int __lane) +{ + return __builtin_fmaf (__b, __aarch64_vget_lane_any (__c, __lane), __a); +} + +/* vfma_laneq */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfma_laneq_f32 (float32x2_t __a, float32x2_t __b, + float32x4_t __c, const int __lane) +{ + return __builtin_aarch64_fmav2sf (__b, + __aarch64_vdup_laneq_f32 (__c, __lane), + __a); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfma_laneq_f64 (float64x1_t __a, float64x1_t __b, + float64x2_t __c, const int __lane) +{ + float64_t __c0 = __aarch64_vget_lane_any (__c, __lane); + return (float64x1_t) {__builtin_fma (__b[0], __c0, __a[0])}; +} + +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmad_laneq_f64 (float64_t __a, float64_t __b, + float64x2_t __c, const int __lane) +{ + return __builtin_fma (__b, __aarch64_vget_lane_any (__c, __lane), __a); +} + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmas_laneq_f32 (float32_t __a, float32_t __b, + float32x4_t __c, const int __lane) +{ + return __builtin_fmaf (__b, __aarch64_vget_lane_any (__c, __lane), __a); +} + +/* vfmaq_lane */ + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmaq_lane_f32 (float32x4_t __a, float32x4_t __b, + float32x2_t __c, const int __lane) +{ + return __builtin_aarch64_fmav4sf (__b, + __aarch64_vdupq_lane_f32 (__c, __lane), + __a); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmaq_lane_f64 (float64x2_t __a, float64x2_t __b, + float64x1_t __c, const int __lane) +{ + return __builtin_aarch64_fmav2df (__b, vdupq_n_f64 (__c[0]), __a); +} + +/* vfmaq_laneq */ + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmaq_laneq_f32 (float32x4_t __a, float32x4_t __b, + float32x4_t __c, const int __lane) +{ + return __builtin_aarch64_fmav4sf (__b, + __aarch64_vdupq_laneq_f32 (__c, __lane), + __a); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmaq_laneq_f64 (float64x2_t __a, float64x2_t __b, + float64x2_t __c, const int __lane) +{ + return __builtin_aarch64_fmav2df (__b, + __aarch64_vdupq_laneq_f64 (__c, __lane), + __a); +} + +/* vfms */ + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfms_f64 (float64x1_t __a, float64x1_t __b, float64x1_t __c) +{ + return (float64x1_t) {__builtin_fma (-__b[0], __c[0], __a[0])}; +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfms_f32 (float32x2_t __a, float32x2_t __b, float32x2_t __c) +{ + return __builtin_aarch64_fmav2sf (-__b, __c, __a); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmsq_f32 (float32x4_t __a, float32x4_t __b, float32x4_t __c) +{ + return __builtin_aarch64_fmav4sf (-__b, __c, __a); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmsq_f64 (float64x2_t __a, float64x2_t __b, float64x2_t __c) +{ + return __builtin_aarch64_fmav2df (-__b, __c, __a); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfms_n_f32 (float32x2_t __a, float32x2_t __b, float32_t __c) +{ + return __builtin_aarch64_fmav2sf (-__b, vdup_n_f32 (__c), __a); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfms_n_f64 (float64x1_t __a, float64x1_t __b, float64_t __c) +{ + return (float64x1_t) {-__b[0] * __c + __a[0]}; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmsq_n_f32 (float32x4_t __a, float32x4_t __b, float32_t __c) +{ + return __builtin_aarch64_fmav4sf (-__b, vdupq_n_f32 (__c), __a); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmsq_n_f64 (float64x2_t __a, float64x2_t __b, float64_t __c) +{ + return __builtin_aarch64_fmav2df (-__b, vdupq_n_f64 (__c), __a); +} + +/* vfms_lane */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfms_lane_f32 (float32x2_t __a, float32x2_t __b, + float32x2_t __c, const int __lane) +{ + return __builtin_aarch64_fmav2sf (-__b, + __aarch64_vdup_lane_f32 (__c, __lane), + __a); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfms_lane_f64 (float64x1_t __a, float64x1_t __b, + float64x1_t __c, const int __lane) +{ + return (float64x1_t) {__builtin_fma (-__b[0], __c[0], __a[0])}; +} + +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmsd_lane_f64 (float64_t __a, float64_t __b, + float64x1_t __c, const int __lane) +{ + return __builtin_fma (-__b, __c[0], __a); +} + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmss_lane_f32 (float32_t __a, float32_t __b, + float32x2_t __c, const int __lane) +{ + return __builtin_fmaf (-__b, __aarch64_vget_lane_any (__c, __lane), __a); +} + +/* vfms_laneq */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfms_laneq_f32 (float32x2_t __a, float32x2_t __b, + float32x4_t __c, const int __lane) +{ + return __builtin_aarch64_fmav2sf (-__b, + __aarch64_vdup_laneq_f32 (__c, __lane), + __a); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfms_laneq_f64 (float64x1_t __a, float64x1_t __b, + float64x2_t __c, const int __lane) +{ + float64_t __c0 = __aarch64_vget_lane_any (__c, __lane); + return (float64x1_t) {__builtin_fma (-__b[0], __c0, __a[0])}; +} + +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmsd_laneq_f64 (float64_t __a, float64_t __b, + float64x2_t __c, const int __lane) +{ + return __builtin_fma (-__b, __aarch64_vget_lane_any (__c, __lane), __a); +} + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmss_laneq_f32 (float32_t __a, float32_t __b, + float32x4_t __c, const int __lane) +{ + return __builtin_fmaf (-__b, __aarch64_vget_lane_any (__c, __lane), __a); +} + +/* vfmsq_lane */ + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmsq_lane_f32 (float32x4_t __a, float32x4_t __b, + float32x2_t __c, const int __lane) +{ + return __builtin_aarch64_fmav4sf (-__b, + __aarch64_vdupq_lane_f32 (__c, __lane), + __a); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmsq_lane_f64 (float64x2_t __a, float64x2_t __b, + float64x1_t __c, const int __lane) +{ + return __builtin_aarch64_fmav2df (-__b, vdupq_n_f64 (__c[0]), __a); +} + +/* vfmsq_laneq */ + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmsq_laneq_f32 (float32x4_t __a, float32x4_t __b, + float32x4_t __c, const int __lane) +{ + return __builtin_aarch64_fmav4sf (-__b, + __aarch64_vdupq_laneq_f32 (__c, __lane), + __a); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmsq_laneq_f64 (float64x2_t __a, float64x2_t __b, + float64x2_t __c, const int __lane) +{ + return __builtin_aarch64_fmav2df (-__b, + __aarch64_vdupq_laneq_f64 (__c, __lane), + __a); +} + +/* vld1 */ + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_f16 (const float16_t *__a) +{ + return __builtin_aarch64_ld1v4hf (__a); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_f32 (const float32_t *a) +{ + return __builtin_aarch64_ld1v2sf ((const __builtin_aarch64_simd_sf *) a); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_f64 (const float64_t *a) +{ + return (float64x1_t) {*a}; +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_p8 (const poly8_t *a) +{ + return (poly8x8_t) + __builtin_aarch64_ld1v8qi ((const __builtin_aarch64_simd_qi *) a); +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_p16 (const poly16_t *a) +{ + return (poly16x4_t) + __builtin_aarch64_ld1v4hi ((const __builtin_aarch64_simd_hi *) a); +} + +__extension__ extern __inline poly64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_p64 (const poly64_t *a) +{ + return (poly64x1_t) {*a}; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_s8 (const int8_t *a) +{ + return __builtin_aarch64_ld1v8qi ((const __builtin_aarch64_simd_qi *) a); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_s16 (const int16_t *a) +{ + return __builtin_aarch64_ld1v4hi ((const __builtin_aarch64_simd_hi *) a); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_s32 (const int32_t *a) +{ + return __builtin_aarch64_ld1v2si ((const __builtin_aarch64_simd_si *) a); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_s64 (const int64_t *a) +{ + return (int64x1_t) {*a}; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_u8 (const uint8_t *a) +{ + return (uint8x8_t) + __builtin_aarch64_ld1v8qi ((const __builtin_aarch64_simd_qi *) a); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_u16 (const uint16_t *a) +{ + return (uint16x4_t) + __builtin_aarch64_ld1v4hi ((const __builtin_aarch64_simd_hi *) a); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_u32 (const uint32_t *a) +{ + return (uint32x2_t) + __builtin_aarch64_ld1v2si ((const __builtin_aarch64_simd_si *) a); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_u64 (const uint64_t *a) +{ + return (uint64x1_t) {*a}; +} + +/* vld1x3 */ + +__extension__ extern __inline uint8x8x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_u8_x3 (const uint8_t *__a) +{ + uint8x8x3_t __i; + __builtin_aarch64_simd_ci __o; + __o = (__builtin_aarch64_simd_ci)__builtin_aarch64_ld1x3v8qi ((const __builtin_aarch64_simd_qi *) __a); + __i.val[0] = (uint8x8_t) __builtin_aarch64_get_dregciv8qi (__o, 0); + __i.val[1] = (uint8x8_t) __builtin_aarch64_get_dregciv8qi (__o, 1); + __i.val[2] = (uint8x8_t) __builtin_aarch64_get_dregciv8qi (__o, 2); + return __i; +} + +__extension__ extern __inline int8x8x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_s8_x3 (const uint8_t *__a) +{ + int8x8x3_t __i; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld1x3v8qi ((const __builtin_aarch64_simd_qi *) __a); + __i.val[0] = (int8x8_t) __builtin_aarch64_get_dregciv8qi (__o, 0); + __i.val[1] = (int8x8_t) __builtin_aarch64_get_dregciv8qi (__o, 1); + __i.val[2] = (int8x8_t) __builtin_aarch64_get_dregciv8qi (__o, 2); + return __i; +} + +__extension__ extern __inline uint16x4x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_u16_x3 (const uint16_t *__a) +{ + uint16x4x3_t __i; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld1x3v4hi ((const __builtin_aarch64_simd_hi *) __a); + __i.val[0] = (uint16x4_t) __builtin_aarch64_get_dregciv4hi (__o, 0); + __i.val[1] = (uint16x4_t) __builtin_aarch64_get_dregciv4hi (__o, 1); + __i.val[2] = (uint16x4_t) __builtin_aarch64_get_dregciv4hi (__o, 2); + return __i; +} + +__extension__ extern __inline int16x4x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_s16_x3 (const int16_t *__a) +{ + int16x4x3_t __i; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld1x3v4hi ((const __builtin_aarch64_simd_hi *) __a); + __i.val[0] = (int16x4_t) __builtin_aarch64_get_dregciv4hi (__o, 0); + __i.val[1] = (int16x4_t) __builtin_aarch64_get_dregciv4hi (__o, 1); + __i.val[2] = (int16x4_t) __builtin_aarch64_get_dregciv4hi (__o, 2); + return __i; +} + +__extension__ extern __inline uint32x2x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_u32_x3 (const uint32_t *__a) +{ + uint32x2x3_t __i; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld1x3v2si ((const __builtin_aarch64_simd_si *) __a); + __i.val[0] = (uint32x2_t) __builtin_aarch64_get_dregciv2si (__o, 0); + __i.val[1] = (uint32x2_t) __builtin_aarch64_get_dregciv2si (__o, 1); + __i.val[2] = (uint32x2_t) __builtin_aarch64_get_dregciv2si (__o, 2); + return __i; +} + +__extension__ extern __inline int32x2x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_s32_x3 (const uint32_t *__a) +{ + int32x2x3_t __i; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld1x3v2si ((const __builtin_aarch64_simd_si *) __a); + __i.val[0] = (int32x2_t) __builtin_aarch64_get_dregciv2si (__o, 0); + __i.val[1] = (int32x2_t) __builtin_aarch64_get_dregciv2si (__o, 1); + __i.val[2] = (int32x2_t) __builtin_aarch64_get_dregciv2si (__o, 2); + return __i; +} + +__extension__ extern __inline uint64x1x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_u64_x3 (const uint64_t *__a) +{ + uint64x1x3_t __i; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld1x3di ((const __builtin_aarch64_simd_di *) __a); + __i.val[0] = (uint64x1_t) __builtin_aarch64_get_dregcidi (__o, 0); + __i.val[1] = (uint64x1_t) __builtin_aarch64_get_dregcidi (__o, 1); + __i.val[2] = (uint64x1_t) __builtin_aarch64_get_dregcidi (__o, 2); + return __i; +} + +__extension__ extern __inline int64x1x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_s64_x3 (const int64_t *__a) +{ + int64x1x3_t __i; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld1x3di ((const __builtin_aarch64_simd_di *) __a); + __i.val[0] = (int64x1_t) __builtin_aarch64_get_dregcidi (__o, 0); + __i.val[1] = (int64x1_t) __builtin_aarch64_get_dregcidi (__o, 1); + __i.val[2] = (int64x1_t) __builtin_aarch64_get_dregcidi (__o, 2); + + return __i; +} + +__extension__ extern __inline float16x4x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_f16_x3 (const float16_t *__a) +{ + float16x4x3_t __i; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld1x3v4hf ((const __builtin_aarch64_simd_hf *) __a); + __i.val[0] = (float16x4_t) __builtin_aarch64_get_dregciv4hf (__o, 0); + __i.val[1] = (float16x4_t) __builtin_aarch64_get_dregciv4hf (__o, 1); + __i.val[2] = (float16x4_t) __builtin_aarch64_get_dregciv4hf (__o, 2); + return __i; +} + +__extension__ extern __inline float32x2x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_f32_x3 (const float32_t *__a) +{ + float32x2x3_t __i; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld1x3v2sf ((const __builtin_aarch64_simd_sf *) __a); + __i.val[0] = (float32x2_t) __builtin_aarch64_get_dregciv2sf (__o, 0); + __i.val[1] = (float32x2_t) __builtin_aarch64_get_dregciv2sf (__o, 1); + __i.val[2] = (float32x2_t) __builtin_aarch64_get_dregciv2sf (__o, 2); + return __i; +} + +__extension__ extern __inline float64x1x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_f64_x3 (const float64_t *__a) +{ + float64x1x3_t __i; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld1x3df ((const __builtin_aarch64_simd_df *) __a); + __i.val[0] = (float64x1_t) __builtin_aarch64_get_dregcidi (__o, 0); + __i.val[1] = (float64x1_t) __builtin_aarch64_get_dregcidi (__o, 1); + __i.val[2] = (float64x1_t) __builtin_aarch64_get_dregcidi (__o, 2); + return __i; +} + +__extension__ extern __inline poly8x8x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_p8_x3 (const poly8_t *__a) +{ + poly8x8x3_t __i; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld1x3v8qi ((const __builtin_aarch64_simd_qi *) __a); + __i.val[0] = (poly8x8_t) __builtin_aarch64_get_dregciv8qi (__o, 0); + __i.val[1] = (poly8x8_t) __builtin_aarch64_get_dregciv8qi (__o, 1); + __i.val[2] = (poly8x8_t) __builtin_aarch64_get_dregciv8qi (__o, 2); + return __i; +} + +__extension__ extern __inline poly16x4x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_p16_x3 (const poly16_t *__a) +{ + poly16x4x3_t __i; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld1x3v4hi ((const __builtin_aarch64_simd_hi *) __a); + __i.val[0] = (poly16x4_t) __builtin_aarch64_get_dregciv4hi (__o, 0); + __i.val[1] = (poly16x4_t) __builtin_aarch64_get_dregciv4hi (__o, 1); + __i.val[2] = (poly16x4_t) __builtin_aarch64_get_dregciv4hi (__o, 2); + return __i; +} + +__extension__ extern __inline poly64x1x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_p64_x3 (const poly64_t *__a) +{ + poly64x1x3_t __i; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld1x3di ((const __builtin_aarch64_simd_di *) __a); + __i.val[0] = (poly64x1_t) __builtin_aarch64_get_dregcidi (__o, 0); + __i.val[1] = (poly64x1_t) __builtin_aarch64_get_dregcidi (__o, 1); + __i.val[2] = (poly64x1_t) __builtin_aarch64_get_dregcidi (__o, 2); + +return __i; +} + +__extension__ extern __inline uint8x16x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_u8_x3 (const uint8_t *__a) +{ + uint8x16x3_t __i; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld1x3v16qi ((const __builtin_aarch64_simd_qi *) __a); + __i.val[0] = (uint8x16_t) __builtin_aarch64_get_qregciv16qi (__o, 0); + __i.val[1] = (uint8x16_t) __builtin_aarch64_get_qregciv16qi (__o, 1); + __i.val[2] = (uint8x16_t) __builtin_aarch64_get_qregciv16qi (__o, 2); + return __i; +} + +__extension__ extern __inline int8x16x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_s8_x3 (const int8_t *__a) +{ + int8x16x3_t __i; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld1x3v16qi ((const __builtin_aarch64_simd_qi *) __a); + __i.val[0] = (int8x16_t) __builtin_aarch64_get_qregciv16qi (__o, 0); + __i.val[1] = (int8x16_t) __builtin_aarch64_get_qregciv16qi (__o, 1); + __i.val[2] = (int8x16_t) __builtin_aarch64_get_qregciv16qi (__o, 2); + return __i; +} + +__extension__ extern __inline uint16x8x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_u16_x3 (const uint16_t *__a) +{ + uint16x8x3_t __i; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld1x3v8hi ((const __builtin_aarch64_simd_hi *) __a); + __i.val[0] = (uint16x8_t) __builtin_aarch64_get_qregciv8hi (__o, 0); + __i.val[1] = (uint16x8_t) __builtin_aarch64_get_qregciv8hi (__o, 1); + __i.val[2] = (uint16x8_t) __builtin_aarch64_get_qregciv8hi (__o, 2); + return __i; +} + +__extension__ extern __inline int16x8x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_s16_x3 (const int16_t *__a) +{ + int16x8x3_t __i; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld1x3v8hi ((const __builtin_aarch64_simd_hi *) __a); + __i.val[0] = (int16x8_t) __builtin_aarch64_get_qregciv8hi (__o, 0); + __i.val[1] = (int16x8_t) __builtin_aarch64_get_qregciv8hi (__o, 1); + __i.val[2] = (int16x8_t) __builtin_aarch64_get_qregciv8hi (__o, 2); + return __i; +} + +__extension__ extern __inline uint32x4x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_u32_x3 (const uint32_t *__a) +{ + uint32x4x3_t __i; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld1x3v4si ((const __builtin_aarch64_simd_si *) __a); + __i.val[0] = (uint32x4_t) __builtin_aarch64_get_qregciv4si (__o, 0); + __i.val[1] = (uint32x4_t) __builtin_aarch64_get_qregciv4si (__o, 1); + __i.val[2] = (uint32x4_t) __builtin_aarch64_get_qregciv4si (__o, 2); + return __i; +} + +__extension__ extern __inline int32x4x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_s32_x3 (const int32_t *__a) +{ + int32x4x3_t __i; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld1x3v4si ((const __builtin_aarch64_simd_si *) __a); + __i.val[0] = (int32x4_t) __builtin_aarch64_get_qregciv4si (__o, 0); + __i.val[1] = (int32x4_t) __builtin_aarch64_get_qregciv4si (__o, 1); + __i.val[2] = (int32x4_t) __builtin_aarch64_get_qregciv4si (__o, 2); + return __i; +} + +__extension__ extern __inline uint64x2x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_u64_x3 (const uint64_t *__a) +{ + uint64x2x3_t __i; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld1x3v2di ((const __builtin_aarch64_simd_di *) __a); + __i.val[0] = (uint64x2_t) __builtin_aarch64_get_qregciv2di (__o, 0); + __i.val[1] = (uint64x2_t) __builtin_aarch64_get_qregciv2di (__o, 1); + __i.val[2] = (uint64x2_t) __builtin_aarch64_get_qregciv2di (__o, 2); + return __i; +} + +__extension__ extern __inline int64x2x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_s64_x3 (const int64_t *__a) +{ + int64x2x3_t __i; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld1x3v2di ((const __builtin_aarch64_simd_di *) __a); + __i.val[0] = (int64x2_t) __builtin_aarch64_get_qregciv2di (__o, 0); + __i.val[1] = (int64x2_t) __builtin_aarch64_get_qregciv2di (__o, 1); + __i.val[2] = (int64x2_t) __builtin_aarch64_get_qregciv2di (__o, 2); + return __i; +} + +__extension__ extern __inline float16x8x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_f16_x3 (const float16_t *__a) +{ + float16x8x3_t __i; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld1x3v8hf ((const __builtin_aarch64_simd_hf *) __a); + __i.val[0] = (float16x8_t) __builtin_aarch64_get_qregciv8hf (__o, 0); + __i.val[1] = (float16x8_t) __builtin_aarch64_get_qregciv8hf (__o, 1); + __i.val[2] = (float16x8_t) __builtin_aarch64_get_qregciv8hf (__o, 2); + return __i; +} + +__extension__ extern __inline float32x4x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_f32_x3 (const float32_t *__a) +{ + float32x4x3_t __i; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld1x3v4sf ((const __builtin_aarch64_simd_sf *) __a); + __i.val[0] = (float32x4_t) __builtin_aarch64_get_qregciv4sf (__o, 0); + __i.val[1] = (float32x4_t) __builtin_aarch64_get_qregciv4sf (__o, 1); + __i.val[2] = (float32x4_t) __builtin_aarch64_get_qregciv4sf (__o, 2); + return __i; +} + +__extension__ extern __inline float64x2x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_f64_x3 (const float64_t *__a) +{ + float64x2x3_t __i; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld1x3v2df ((const __builtin_aarch64_simd_df *) __a); + __i.val[0] = (float64x2_t) __builtin_aarch64_get_qregciv2df (__o, 0); + __i.val[1] = (float64x2_t) __builtin_aarch64_get_qregciv2df (__o, 1); + __i.val[2] = (float64x2_t) __builtin_aarch64_get_qregciv2df (__o, 2); + return __i; +} + +__extension__ extern __inline poly8x16x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_p8_x3 (const poly8_t *__a) +{ + poly8x16x3_t __i; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld1x3v16qi ((const __builtin_aarch64_simd_qi *) __a); + __i.val[0] = (poly8x16_t) __builtin_aarch64_get_qregciv16qi (__o, 0); + __i.val[1] = (poly8x16_t) __builtin_aarch64_get_qregciv16qi (__o, 1); + __i.val[2] = (poly8x16_t) __builtin_aarch64_get_qregciv16qi (__o, 2); + return __i; +} + +__extension__ extern __inline poly16x8x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_p16_x3 (const poly16_t *__a) +{ + poly16x8x3_t __i; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld1x3v8hi ((const __builtin_aarch64_simd_hi *) __a); + __i.val[0] = (poly16x8_t) __builtin_aarch64_get_qregciv8hi (__o, 0); + __i.val[1] = (poly16x8_t) __builtin_aarch64_get_qregciv8hi (__o, 1); + __i.val[2] = (poly16x8_t) __builtin_aarch64_get_qregciv8hi (__o, 2); + return __i; +} + +__extension__ extern __inline poly64x2x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_p64_x3 (const poly64_t *__a) +{ + poly64x2x3_t __i; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld1x3v2di ((const __builtin_aarch64_simd_di *) __a); + __i.val[0] = (poly64x2_t) __builtin_aarch64_get_qregciv2di (__o, 0); + __i.val[1] = (poly64x2_t) __builtin_aarch64_get_qregciv2di (__o, 1); + __i.val[2] = (poly64x2_t) __builtin_aarch64_get_qregciv2di (__o, 2); + return __i; +} + +/* vld1q */ + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_f16 (const float16_t *__a) +{ + return __builtin_aarch64_ld1v8hf (__a); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_f32 (const float32_t *a) +{ + return __builtin_aarch64_ld1v4sf ((const __builtin_aarch64_simd_sf *) a); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_f64 (const float64_t *a) +{ + return __builtin_aarch64_ld1v2df ((const __builtin_aarch64_simd_df *) a); +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_p8 (const poly8_t *a) +{ + return (poly8x16_t) + __builtin_aarch64_ld1v16qi ((const __builtin_aarch64_simd_qi *) a); +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_p16 (const poly16_t *a) +{ + return (poly16x8_t) + __builtin_aarch64_ld1v8hi ((const __builtin_aarch64_simd_hi *) a); +} + +__extension__ extern __inline poly64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_p64 (const poly64_t *a) +{ + return (poly64x2_t) + __builtin_aarch64_ld1v2di ((const __builtin_aarch64_simd_di *) a); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_s8 (const int8_t *a) +{ + return __builtin_aarch64_ld1v16qi ((const __builtin_aarch64_simd_qi *) a); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_s16 (const int16_t *a) +{ + return __builtin_aarch64_ld1v8hi ((const __builtin_aarch64_simd_hi *) a); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_s32 (const int32_t *a) +{ + return __builtin_aarch64_ld1v4si ((const __builtin_aarch64_simd_si *) a); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_s64 (const int64_t *a) +{ + return __builtin_aarch64_ld1v2di ((const __builtin_aarch64_simd_di *) a); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_u8 (const uint8_t *a) +{ + return (uint8x16_t) + __builtin_aarch64_ld1v16qi ((const __builtin_aarch64_simd_qi *) a); +} + +__extension__ extern __inline uint8x8x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_u8_x2 (const uint8_t *__a) +{ + uint8x8x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld1x2v8qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (uint8x8_t) __builtin_aarch64_get_dregoiv8qi (__o, 0); + ret.val[1] = (uint8x8_t) __builtin_aarch64_get_dregoiv8qi (__o, 1); + return ret; +} + +__extension__ extern __inline int8x8x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_s8_x2 (const int8_t *__a) +{ + int8x8x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld1x2v8qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (int8x8_t) __builtin_aarch64_get_dregoiv8qi (__o, 0); + ret.val[1] = (int8x8_t) __builtin_aarch64_get_dregoiv8qi (__o, 1); + return ret; +} + +__extension__ extern __inline uint16x4x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_u16_x2 (const uint16_t *__a) +{ + uint16x4x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld1x2v4hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (uint16x4_t) __builtin_aarch64_get_dregoiv4hi (__o, 0); + ret.val[1] = (uint16x4_t) __builtin_aarch64_get_dregoiv4hi (__o, 1); + return ret; +} + +__extension__ extern __inline int16x4x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_s16_x2 (const int16_t *__a) +{ + int16x4x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld1x2v4hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (int16x4_t) __builtin_aarch64_get_dregoiv4hi (__o, 0); + ret.val[1] = (int16x4_t) __builtin_aarch64_get_dregoiv4hi (__o, 1); + return ret; +} + +__extension__ extern __inline uint32x2x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_u32_x2 (const uint32_t *__a) +{ + uint32x2x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld1x2v2si ((const __builtin_aarch64_simd_si *) __a); + ret.val[0] = (uint32x2_t) __builtin_aarch64_get_dregoiv2si (__o, 0); + ret.val[1] = (uint32x2_t) __builtin_aarch64_get_dregoiv2si (__o, 1); + return ret; +} + +__extension__ extern __inline int32x2x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_s32_x2 (const int32_t *__a) +{ + int32x2x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld1x2v2si ((const __builtin_aarch64_simd_si *) __a); + ret.val[0] = (int32x2_t) __builtin_aarch64_get_dregoiv2si (__o, 0); + ret.val[1] = (int32x2_t) __builtin_aarch64_get_dregoiv2si (__o, 1); + return ret; +} + +__extension__ extern __inline uint64x1x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_u64_x2 (const uint64_t *__a) +{ + uint64x1x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld1x2di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (uint64x1_t) __builtin_aarch64_get_dregoidi (__o, 0); + ret.val[1] = (uint64x1_t) __builtin_aarch64_get_dregoidi (__o, 1); + return ret; +} + +__extension__ extern __inline int64x1x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_s64_x2 (const int64_t *__a) +{ + int64x1x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld1x2di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (int64x1_t) __builtin_aarch64_get_dregoidi (__o, 0); + ret.val[1] = (int64x1_t) __builtin_aarch64_get_dregoidi (__o, 1); + return ret; +} + +__extension__ extern __inline float16x4x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_f16_x2 (const float16_t *__a) +{ + float16x4x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld1x2v4hf ((const __builtin_aarch64_simd_hf *) __a); + ret.val[0] = (float16x4_t) __builtin_aarch64_get_dregoiv4hf (__o, 0); + ret.val[1] = (float16x4_t) __builtin_aarch64_get_dregoiv4hf (__o, 1); + return ret; +} + +__extension__ extern __inline float32x2x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_f32_x2 (const float32_t *__a) +{ + float32x2x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld1x2v2sf ((const __builtin_aarch64_simd_sf *) __a); + ret.val[0] = (float32x2_t) __builtin_aarch64_get_dregoiv2sf (__o, 0); + ret.val[1] = (float32x2_t) __builtin_aarch64_get_dregoiv2sf (__o, 1); + return ret; +} + +__extension__ extern __inline float64x1x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_f64_x2 (const float64_t *__a) +{ + float64x1x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld1x2df ((const __builtin_aarch64_simd_df *) __a); + ret.val[0] = (float64x1_t) {__builtin_aarch64_get_dregoidf (__o, 0)}; + ret.val[1] = (float64x1_t) {__builtin_aarch64_get_dregoidf (__o, 1)}; + return ret; +} + +__extension__ extern __inline poly8x8x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_p8_x2 (const poly8_t *__a) +{ + poly8x8x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld1x2v8qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (poly8x8_t) __builtin_aarch64_get_dregoiv8qi (__o, 0); + ret.val[1] = (poly8x8_t) __builtin_aarch64_get_dregoiv8qi (__o, 1); + return ret; +} + +__extension__ extern __inline poly16x4x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_p16_x2 (const poly16_t *__a) +{ + poly16x4x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld1x2v4hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (poly16x4_t) __builtin_aarch64_get_dregoiv4hi (__o, 0); + ret.val[1] = (poly16x4_t) __builtin_aarch64_get_dregoiv4hi (__o, 1); + return ret; +} + +__extension__ extern __inline poly64x1x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_p64_x2 (const poly64_t *__a) +{ + poly64x1x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld1x2di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (poly64x1_t) __builtin_aarch64_get_dregoidi (__o, 0); + ret.val[1] = (poly64x1_t) __builtin_aarch64_get_dregoidi (__o, 1); + return ret; +} + +__extension__ extern __inline uint8x16x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_u8_x2 (const uint8_t *__a) +{ + uint8x16x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld1x2v16qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (uint8x16_t) __builtin_aarch64_get_qregoiv16qi (__o, 0); + ret.val[1] = (uint8x16_t) __builtin_aarch64_get_qregoiv16qi (__o, 1); + return ret; +} + +__extension__ extern __inline int8x16x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_s8_x2 (const int8_t *__a) +{ + int8x16x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld1x2v16qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (int8x16_t) __builtin_aarch64_get_qregoiv16qi (__o, 0); + ret.val[1] = (int8x16_t) __builtin_aarch64_get_qregoiv16qi (__o, 1); + return ret; +} + +__extension__ extern __inline uint16x8x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_u16_x2 (const uint16_t *__a) +{ + uint16x8x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld1x2v8hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (uint16x8_t) __builtin_aarch64_get_qregoiv8hi (__o, 0); + ret.val[1] = (uint16x8_t) __builtin_aarch64_get_qregoiv8hi (__o, 1); + return ret; +} + +__extension__ extern __inline int16x8x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_s16_x2 (const int16_t *__a) +{ + int16x8x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld1x2v8hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (int16x8_t) __builtin_aarch64_get_qregoiv8hi (__o, 0); + ret.val[1] = (int16x8_t) __builtin_aarch64_get_qregoiv8hi (__o, 1); + return ret; +} + +__extension__ extern __inline uint32x4x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_u32_x2 (const uint32_t *__a) +{ + uint32x4x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld1x2v4si ((const __builtin_aarch64_simd_si *) __a); + ret.val[0] = (uint32x4_t) __builtin_aarch64_get_qregoiv4si (__o, 0); + ret.val[1] = (uint32x4_t) __builtin_aarch64_get_qregoiv4si (__o, 1); + return ret; +} + +__extension__ extern __inline int32x4x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_s32_x2 (const int32_t *__a) +{ + int32x4x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld1x2v4si ((const __builtin_aarch64_simd_si *) __a); + ret.val[0] = (int32x4_t) __builtin_aarch64_get_qregoiv4si (__o, 0); + ret.val[1] = (int32x4_t) __builtin_aarch64_get_qregoiv4si (__o, 1); + return ret; +} + +__extension__ extern __inline uint64x2x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_u64_x2 (const uint64_t *__a) +{ + uint64x2x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld1x2v2di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (uint64x2_t) __builtin_aarch64_get_qregoiv2di (__o, 0); + ret.val[1] = (uint64x2_t) __builtin_aarch64_get_qregoiv2di (__o, 1); + return ret; +} + +__extension__ extern __inline int64x2x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_s64_x2 (const int64_t *__a) +{ + int64x2x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld1x2v2di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (int64x2_t) __builtin_aarch64_get_qregoiv2di (__o, 0); + ret.val[1] = (int64x2_t) __builtin_aarch64_get_qregoiv2di (__o, 1); + return ret; +} + +__extension__ extern __inline float16x8x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_f16_x2 (const float16_t *__a) +{ + float16x8x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld1x2v8hf ((const __builtin_aarch64_simd_hf *) __a); + ret.val[0] = (float16x8_t) __builtin_aarch64_get_qregoiv8hf (__o, 0); + ret.val[1] = (float16x8_t) __builtin_aarch64_get_qregoiv8hf (__o, 1); + return ret; +} + +__extension__ extern __inline float32x4x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_f32_x2 (const float32_t *__a) +{ + float32x4x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld1x2v4sf ((const __builtin_aarch64_simd_sf *) __a); + ret.val[0] = (float32x4_t) __builtin_aarch64_get_qregoiv4sf (__o, 0); + ret.val[1] = (float32x4_t) __builtin_aarch64_get_qregoiv4sf (__o, 1); + return ret; +} + +__extension__ extern __inline float64x2x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_f64_x2 (const float64_t *__a) +{ + float64x2x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld1x2v2df ((const __builtin_aarch64_simd_df *) __a); + ret.val[0] = (float64x2_t) __builtin_aarch64_get_qregoiv2df (__o, 0); + ret.val[1] = (float64x2_t) __builtin_aarch64_get_qregoiv2df (__o, 1); + return ret; +} + +__extension__ extern __inline poly8x16x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_p8_x2 (const poly8_t *__a) +{ + poly8x16x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld1x2v16qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (poly8x16_t) __builtin_aarch64_get_qregoiv16qi (__o, 0); + ret.val[1] = (poly8x16_t) __builtin_aarch64_get_qregoiv16qi (__o, 1); + return ret; +} + +__extension__ extern __inline poly16x8x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_p16_x2 (const poly16_t *__a) +{ + poly16x8x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld1x2v8hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (poly16x8_t) __builtin_aarch64_get_qregoiv8hi (__o, 0); + ret.val[1] = (poly16x8_t) __builtin_aarch64_get_qregoiv8hi (__o, 1); + return ret; +} + +__extension__ extern __inline poly64x2x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_p64_x2 (const poly64_t *__a) +{ + poly64x2x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld1x2v2di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (poly64x2_t) __builtin_aarch64_get_qregoiv2di (__o, 0); + ret.val[1] = (poly64x2_t) __builtin_aarch64_get_qregoiv2di (__o, 1); + return ret; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_u16 (const uint16_t *a) +{ + return (uint16x8_t) + __builtin_aarch64_ld1v8hi ((const __builtin_aarch64_simd_hi *) a); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_u32 (const uint32_t *a) +{ + return (uint32x4_t) + __builtin_aarch64_ld1v4si ((const __builtin_aarch64_simd_si *) a); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_u64 (const uint64_t *a) +{ + return (uint64x2_t) + __builtin_aarch64_ld1v2di ((const __builtin_aarch64_simd_di *) a); +} + +/* vld1_dup */ + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_dup_f16 (const float16_t* __a) +{ + return vdup_n_f16 (*__a); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_dup_f32 (const float32_t* __a) +{ + return vdup_n_f32 (*__a); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_dup_f64 (const float64_t* __a) +{ + return vdup_n_f64 (*__a); +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_dup_p8 (const poly8_t* __a) +{ + return vdup_n_p8 (*__a); +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_dup_p16 (const poly16_t* __a) +{ + return vdup_n_p16 (*__a); +} + +__extension__ extern __inline poly64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_dup_p64 (const poly64_t* __a) +{ + return vdup_n_p64 (*__a); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_dup_s8 (const int8_t* __a) +{ + return vdup_n_s8 (*__a); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_dup_s16 (const int16_t* __a) +{ + return vdup_n_s16 (*__a); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_dup_s32 (const int32_t* __a) +{ + return vdup_n_s32 (*__a); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_dup_s64 (const int64_t* __a) +{ + return vdup_n_s64 (*__a); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_dup_u8 (const uint8_t* __a) +{ + return vdup_n_u8 (*__a); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_dup_u16 (const uint16_t* __a) +{ + return vdup_n_u16 (*__a); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_dup_u32 (const uint32_t* __a) +{ + return vdup_n_u32 (*__a); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_dup_u64 (const uint64_t* __a) +{ + return vdup_n_u64 (*__a); +} + +/* vld1q_dup */ + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_dup_f16 (const float16_t* __a) +{ + return vdupq_n_f16 (*__a); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_dup_f32 (const float32_t* __a) +{ + return vdupq_n_f32 (*__a); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_dup_f64 (const float64_t* __a) +{ + return vdupq_n_f64 (*__a); +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_dup_p8 (const poly8_t* __a) +{ + return vdupq_n_p8 (*__a); +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_dup_p16 (const poly16_t* __a) +{ + return vdupq_n_p16 (*__a); +} + +__extension__ extern __inline poly64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_dup_p64 (const poly64_t* __a) +{ + return vdupq_n_p64 (*__a); +} + + __extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_dup_s8 (const int8_t* __a) +{ + return vdupq_n_s8 (*__a); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_dup_s16 (const int16_t* __a) +{ + return vdupq_n_s16 (*__a); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_dup_s32 (const int32_t* __a) +{ + return vdupq_n_s32 (*__a); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_dup_s64 (const int64_t* __a) +{ + return vdupq_n_s64 (*__a); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_dup_u8 (const uint8_t* __a) +{ + return vdupq_n_u8 (*__a); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_dup_u16 (const uint16_t* __a) +{ + return vdupq_n_u16 (*__a); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_dup_u32 (const uint32_t* __a) +{ + return vdupq_n_u32 (*__a); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_dup_u64 (const uint64_t* __a) +{ + return vdupq_n_u64 (*__a); +} + +/* vld1_lane */ + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_lane_f16 (const float16_t *__src, float16x4_t __vec, const int __lane) +{ + return __aarch64_vset_lane_any (*__src, __vec, __lane); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_lane_f32 (const float32_t *__src, float32x2_t __vec, const int __lane) +{ + return __aarch64_vset_lane_any (*__src, __vec, __lane); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_lane_f64 (const float64_t *__src, float64x1_t __vec, const int __lane) +{ + return __aarch64_vset_lane_any (*__src, __vec, __lane); +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_lane_p8 (const poly8_t *__src, poly8x8_t __vec, const int __lane) +{ + return __aarch64_vset_lane_any (*__src, __vec, __lane); +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_lane_p16 (const poly16_t *__src, poly16x4_t __vec, const int __lane) +{ + return __aarch64_vset_lane_any (*__src, __vec, __lane); +} + +__extension__ extern __inline poly64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_lane_p64 (const poly64_t *__src, poly64x1_t __vec, const int __lane) +{ + return __aarch64_vset_lane_any (*__src, __vec, __lane); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_lane_s8 (const int8_t *__src, int8x8_t __vec, const int __lane) +{ + return __aarch64_vset_lane_any (*__src, __vec, __lane); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_lane_s16 (const int16_t *__src, int16x4_t __vec, const int __lane) +{ + return __aarch64_vset_lane_any (*__src, __vec, __lane); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_lane_s32 (const int32_t *__src, int32x2_t __vec, const int __lane) +{ + return __aarch64_vset_lane_any (*__src, __vec, __lane); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_lane_s64 (const int64_t *__src, int64x1_t __vec, const int __lane) +{ + return __aarch64_vset_lane_any (*__src, __vec, __lane); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_lane_u8 (const uint8_t *__src, uint8x8_t __vec, const int __lane) +{ + return __aarch64_vset_lane_any (*__src, __vec, __lane); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_lane_u16 (const uint16_t *__src, uint16x4_t __vec, const int __lane) +{ + return __aarch64_vset_lane_any (*__src, __vec, __lane); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_lane_u32 (const uint32_t *__src, uint32x2_t __vec, const int __lane) +{ + return __aarch64_vset_lane_any (*__src, __vec, __lane); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1_lane_u64 (const uint64_t *__src, uint64x1_t __vec, const int __lane) +{ + return __aarch64_vset_lane_any (*__src, __vec, __lane); +} + +/* vld1q_lane */ + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_lane_f16 (const float16_t *__src, float16x8_t __vec, const int __lane) +{ + return __aarch64_vset_lane_any (*__src, __vec, __lane); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_lane_f32 (const float32_t *__src, float32x4_t __vec, const int __lane) +{ + return __aarch64_vset_lane_any (*__src, __vec, __lane); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_lane_f64 (const float64_t *__src, float64x2_t __vec, const int __lane) +{ + return __aarch64_vset_lane_any (*__src, __vec, __lane); +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_lane_p8 (const poly8_t *__src, poly8x16_t __vec, const int __lane) +{ + return __aarch64_vset_lane_any (*__src, __vec, __lane); +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_lane_p16 (const poly16_t *__src, poly16x8_t __vec, const int __lane) +{ + return __aarch64_vset_lane_any (*__src, __vec, __lane); +} + +__extension__ extern __inline poly64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_lane_p64 (const poly64_t *__src, poly64x2_t __vec, const int __lane) +{ + return __aarch64_vset_lane_any (*__src, __vec, __lane); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_lane_s8 (const int8_t *__src, int8x16_t __vec, const int __lane) +{ + return __aarch64_vset_lane_any (*__src, __vec, __lane); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_lane_s16 (const int16_t *__src, int16x8_t __vec, const int __lane) +{ + return __aarch64_vset_lane_any (*__src, __vec, __lane); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_lane_s32 (const int32_t *__src, int32x4_t __vec, const int __lane) +{ + return __aarch64_vset_lane_any (*__src, __vec, __lane); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_lane_s64 (const int64_t *__src, int64x2_t __vec, const int __lane) +{ + return __aarch64_vset_lane_any (*__src, __vec, __lane); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_lane_u8 (const uint8_t *__src, uint8x16_t __vec, const int __lane) +{ + return __aarch64_vset_lane_any (*__src, __vec, __lane); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_lane_u16 (const uint16_t *__src, uint16x8_t __vec, const int __lane) +{ + return __aarch64_vset_lane_any (*__src, __vec, __lane); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_lane_u32 (const uint32_t *__src, uint32x4_t __vec, const int __lane) +{ + return __aarch64_vset_lane_any (*__src, __vec, __lane); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld1q_lane_u64 (const uint64_t *__src, uint64x2_t __vec, const int __lane) +{ + return __aarch64_vset_lane_any (*__src, __vec, __lane); +} + +/* vldn */ + +__extension__ extern __inline int64x1x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2_s64 (const int64_t * __a) +{ + int64x1x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (int64x1_t) __builtin_aarch64_get_dregoidi (__o, 0); + ret.val[1] = (int64x1_t) __builtin_aarch64_get_dregoidi (__o, 1); + return ret; +} + +__extension__ extern __inline uint64x1x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2_u64 (const uint64_t * __a) +{ + uint64x1x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (uint64x1_t) __builtin_aarch64_get_dregoidi (__o, 0); + ret.val[1] = (uint64x1_t) __builtin_aarch64_get_dregoidi (__o, 1); + return ret; +} + +__extension__ extern __inline float64x1x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2_f64 (const float64_t * __a) +{ + float64x1x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2df ((const __builtin_aarch64_simd_df *) __a); + ret.val[0] = (float64x1_t) {__builtin_aarch64_get_dregoidf (__o, 0)}; + ret.val[1] = (float64x1_t) {__builtin_aarch64_get_dregoidf (__o, 1)}; + return ret; +} + +__extension__ extern __inline int8x8x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2_s8 (const int8_t * __a) +{ + int8x8x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2v8qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (int8x8_t) __builtin_aarch64_get_dregoiv8qi (__o, 0); + ret.val[1] = (int8x8_t) __builtin_aarch64_get_dregoiv8qi (__o, 1); + return ret; +} + +__extension__ extern __inline poly8x8x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2_p8 (const poly8_t * __a) +{ + poly8x8x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2v8qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (poly8x8_t) __builtin_aarch64_get_dregoiv8qi (__o, 0); + ret.val[1] = (poly8x8_t) __builtin_aarch64_get_dregoiv8qi (__o, 1); + return ret; +} + +__extension__ extern __inline poly64x1x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2_p64 (const poly64_t * __a) +{ + poly64x1x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (poly64x1_t) __builtin_aarch64_get_dregoidi_pss (__o, 0); + ret.val[1] = (poly64x1_t) __builtin_aarch64_get_dregoidi_pss (__o, 1); + return ret; +} + +__extension__ extern __inline int16x4x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2_s16 (const int16_t * __a) +{ + int16x4x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2v4hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (int16x4_t) __builtin_aarch64_get_dregoiv4hi (__o, 0); + ret.val[1] = (int16x4_t) __builtin_aarch64_get_dregoiv4hi (__o, 1); + return ret; +} + +__extension__ extern __inline poly16x4x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2_p16 (const poly16_t * __a) +{ + poly16x4x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2v4hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (poly16x4_t) __builtin_aarch64_get_dregoiv4hi (__o, 0); + ret.val[1] = (poly16x4_t) __builtin_aarch64_get_dregoiv4hi (__o, 1); + return ret; +} + +__extension__ extern __inline int32x2x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2_s32 (const int32_t * __a) +{ + int32x2x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2v2si ((const __builtin_aarch64_simd_si *) __a); + ret.val[0] = (int32x2_t) __builtin_aarch64_get_dregoiv2si (__o, 0); + ret.val[1] = (int32x2_t) __builtin_aarch64_get_dregoiv2si (__o, 1); + return ret; +} + +__extension__ extern __inline uint8x8x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2_u8 (const uint8_t * __a) +{ + uint8x8x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2v8qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (uint8x8_t) __builtin_aarch64_get_dregoiv8qi (__o, 0); + ret.val[1] = (uint8x8_t) __builtin_aarch64_get_dregoiv8qi (__o, 1); + return ret; +} + +__extension__ extern __inline uint16x4x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2_u16 (const uint16_t * __a) +{ + uint16x4x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2v4hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (uint16x4_t) __builtin_aarch64_get_dregoiv4hi (__o, 0); + ret.val[1] = (uint16x4_t) __builtin_aarch64_get_dregoiv4hi (__o, 1); + return ret; +} + +__extension__ extern __inline uint32x2x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2_u32 (const uint32_t * __a) +{ + uint32x2x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2v2si ((const __builtin_aarch64_simd_si *) __a); + ret.val[0] = (uint32x2_t) __builtin_aarch64_get_dregoiv2si (__o, 0); + ret.val[1] = (uint32x2_t) __builtin_aarch64_get_dregoiv2si (__o, 1); + return ret; +} + +__extension__ extern __inline float16x4x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2_f16 (const float16_t * __a) +{ + float16x4x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2v4hf (__a); + ret.val[0] = __builtin_aarch64_get_dregoiv4hf (__o, 0); + ret.val[1] = __builtin_aarch64_get_dregoiv4hf (__o, 1); + return ret; +} + +__extension__ extern __inline float32x2x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2_f32 (const float32_t * __a) +{ + float32x2x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2v2sf ((const __builtin_aarch64_simd_sf *) __a); + ret.val[0] = (float32x2_t) __builtin_aarch64_get_dregoiv2sf (__o, 0); + ret.val[1] = (float32x2_t) __builtin_aarch64_get_dregoiv2sf (__o, 1); + return ret; +} + +__extension__ extern __inline int8x16x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2q_s8 (const int8_t * __a) +{ + int8x16x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2v16qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (int8x16_t) __builtin_aarch64_get_qregoiv16qi (__o, 0); + ret.val[1] = (int8x16_t) __builtin_aarch64_get_qregoiv16qi (__o, 1); + return ret; +} + +__extension__ extern __inline poly8x16x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2q_p8 (const poly8_t * __a) +{ + poly8x16x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2v16qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (poly8x16_t) __builtin_aarch64_get_qregoiv16qi (__o, 0); + ret.val[1] = (poly8x16_t) __builtin_aarch64_get_qregoiv16qi (__o, 1); + return ret; +} + +__extension__ extern __inline int16x8x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2q_s16 (const int16_t * __a) +{ + int16x8x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2v8hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (int16x8_t) __builtin_aarch64_get_qregoiv8hi (__o, 0); + ret.val[1] = (int16x8_t) __builtin_aarch64_get_qregoiv8hi (__o, 1); + return ret; +} + +__extension__ extern __inline poly16x8x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2q_p16 (const poly16_t * __a) +{ + poly16x8x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2v8hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (poly16x8_t) __builtin_aarch64_get_qregoiv8hi (__o, 0); + ret.val[1] = (poly16x8_t) __builtin_aarch64_get_qregoiv8hi (__o, 1); + return ret; +} + +__extension__ extern __inline poly64x2x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2q_p64 (const poly64_t * __a) +{ + poly64x2x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2v2di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (poly64x2_t) __builtin_aarch64_get_qregoiv2di_pss (__o, 0); + ret.val[1] = (poly64x2_t) __builtin_aarch64_get_qregoiv2di_pss (__o, 1); + return ret; +} + +__extension__ extern __inline int32x4x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2q_s32 (const int32_t * __a) +{ + int32x4x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2v4si ((const __builtin_aarch64_simd_si *) __a); + ret.val[0] = (int32x4_t) __builtin_aarch64_get_qregoiv4si (__o, 0); + ret.val[1] = (int32x4_t) __builtin_aarch64_get_qregoiv4si (__o, 1); + return ret; +} + +__extension__ extern __inline int64x2x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2q_s64 (const int64_t * __a) +{ + int64x2x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2v2di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (int64x2_t) __builtin_aarch64_get_qregoiv2di (__o, 0); + ret.val[1] = (int64x2_t) __builtin_aarch64_get_qregoiv2di (__o, 1); + return ret; +} + +__extension__ extern __inline uint8x16x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2q_u8 (const uint8_t * __a) +{ + uint8x16x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2v16qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (uint8x16_t) __builtin_aarch64_get_qregoiv16qi (__o, 0); + ret.val[1] = (uint8x16_t) __builtin_aarch64_get_qregoiv16qi (__o, 1); + return ret; +} + +__extension__ extern __inline uint16x8x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2q_u16 (const uint16_t * __a) +{ + uint16x8x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2v8hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (uint16x8_t) __builtin_aarch64_get_qregoiv8hi (__o, 0); + ret.val[1] = (uint16x8_t) __builtin_aarch64_get_qregoiv8hi (__o, 1); + return ret; +} + +__extension__ extern __inline uint32x4x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2q_u32 (const uint32_t * __a) +{ + uint32x4x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2v4si ((const __builtin_aarch64_simd_si *) __a); + ret.val[0] = (uint32x4_t) __builtin_aarch64_get_qregoiv4si (__o, 0); + ret.val[1] = (uint32x4_t) __builtin_aarch64_get_qregoiv4si (__o, 1); + return ret; +} + +__extension__ extern __inline uint64x2x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2q_u64 (const uint64_t * __a) +{ + uint64x2x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2v2di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (uint64x2_t) __builtin_aarch64_get_qregoiv2di (__o, 0); + ret.val[1] = (uint64x2_t) __builtin_aarch64_get_qregoiv2di (__o, 1); + return ret; +} + +__extension__ extern __inline float16x8x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2q_f16 (const float16_t * __a) +{ + float16x8x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2v8hf (__a); + ret.val[0] = __builtin_aarch64_get_qregoiv8hf (__o, 0); + ret.val[1] = __builtin_aarch64_get_qregoiv8hf (__o, 1); + return ret; +} + +__extension__ extern __inline float32x4x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2q_f32 (const float32_t * __a) +{ + float32x4x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2v4sf ((const __builtin_aarch64_simd_sf *) __a); + ret.val[0] = (float32x4_t) __builtin_aarch64_get_qregoiv4sf (__o, 0); + ret.val[1] = (float32x4_t) __builtin_aarch64_get_qregoiv4sf (__o, 1); + return ret; +} + +__extension__ extern __inline float64x2x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2q_f64 (const float64_t * __a) +{ + float64x2x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2v2df ((const __builtin_aarch64_simd_df *) __a); + ret.val[0] = (float64x2_t) __builtin_aarch64_get_qregoiv2df (__o, 0); + ret.val[1] = (float64x2_t) __builtin_aarch64_get_qregoiv2df (__o, 1); + return ret; +} + +__extension__ extern __inline int64x1x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3_s64 (const int64_t * __a) +{ + int64x1x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (int64x1_t) __builtin_aarch64_get_dregcidi (__o, 0); + ret.val[1] = (int64x1_t) __builtin_aarch64_get_dregcidi (__o, 1); + ret.val[2] = (int64x1_t) __builtin_aarch64_get_dregcidi (__o, 2); + return ret; +} + +__extension__ extern __inline uint64x1x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3_u64 (const uint64_t * __a) +{ + uint64x1x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (uint64x1_t) __builtin_aarch64_get_dregcidi (__o, 0); + ret.val[1] = (uint64x1_t) __builtin_aarch64_get_dregcidi (__o, 1); + ret.val[2] = (uint64x1_t) __builtin_aarch64_get_dregcidi (__o, 2); + return ret; +} + +__extension__ extern __inline float64x1x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3_f64 (const float64_t * __a) +{ + float64x1x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3df ((const __builtin_aarch64_simd_df *) __a); + ret.val[0] = (float64x1_t) {__builtin_aarch64_get_dregcidf (__o, 0)}; + ret.val[1] = (float64x1_t) {__builtin_aarch64_get_dregcidf (__o, 1)}; + ret.val[2] = (float64x1_t) {__builtin_aarch64_get_dregcidf (__o, 2)}; + return ret; +} + +__extension__ extern __inline int8x8x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3_s8 (const int8_t * __a) +{ + int8x8x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3v8qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (int8x8_t) __builtin_aarch64_get_dregciv8qi (__o, 0); + ret.val[1] = (int8x8_t) __builtin_aarch64_get_dregciv8qi (__o, 1); + ret.val[2] = (int8x8_t) __builtin_aarch64_get_dregciv8qi (__o, 2); + return ret; +} + +__extension__ extern __inline poly8x8x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3_p8 (const poly8_t * __a) +{ + poly8x8x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3v8qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (poly8x8_t) __builtin_aarch64_get_dregciv8qi (__o, 0); + ret.val[1] = (poly8x8_t) __builtin_aarch64_get_dregciv8qi (__o, 1); + ret.val[2] = (poly8x8_t) __builtin_aarch64_get_dregciv8qi (__o, 2); + return ret; +} + +__extension__ extern __inline int16x4x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3_s16 (const int16_t * __a) +{ + int16x4x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3v4hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (int16x4_t) __builtin_aarch64_get_dregciv4hi (__o, 0); + ret.val[1] = (int16x4_t) __builtin_aarch64_get_dregciv4hi (__o, 1); + ret.val[2] = (int16x4_t) __builtin_aarch64_get_dregciv4hi (__o, 2); + return ret; +} + +__extension__ extern __inline poly16x4x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3_p16 (const poly16_t * __a) +{ + poly16x4x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3v4hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (poly16x4_t) __builtin_aarch64_get_dregciv4hi (__o, 0); + ret.val[1] = (poly16x4_t) __builtin_aarch64_get_dregciv4hi (__o, 1); + ret.val[2] = (poly16x4_t) __builtin_aarch64_get_dregciv4hi (__o, 2); + return ret; +} + +__extension__ extern __inline int32x2x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3_s32 (const int32_t * __a) +{ + int32x2x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3v2si ((const __builtin_aarch64_simd_si *) __a); + ret.val[0] = (int32x2_t) __builtin_aarch64_get_dregciv2si (__o, 0); + ret.val[1] = (int32x2_t) __builtin_aarch64_get_dregciv2si (__o, 1); + ret.val[2] = (int32x2_t) __builtin_aarch64_get_dregciv2si (__o, 2); + return ret; +} + +__extension__ extern __inline uint8x8x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3_u8 (const uint8_t * __a) +{ + uint8x8x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3v8qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (uint8x8_t) __builtin_aarch64_get_dregciv8qi (__o, 0); + ret.val[1] = (uint8x8_t) __builtin_aarch64_get_dregciv8qi (__o, 1); + ret.val[2] = (uint8x8_t) __builtin_aarch64_get_dregciv8qi (__o, 2); + return ret; +} + +__extension__ extern __inline uint16x4x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3_u16 (const uint16_t * __a) +{ + uint16x4x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3v4hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (uint16x4_t) __builtin_aarch64_get_dregciv4hi (__o, 0); + ret.val[1] = (uint16x4_t) __builtin_aarch64_get_dregciv4hi (__o, 1); + ret.val[2] = (uint16x4_t) __builtin_aarch64_get_dregciv4hi (__o, 2); + return ret; +} + +__extension__ extern __inline uint32x2x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3_u32 (const uint32_t * __a) +{ + uint32x2x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3v2si ((const __builtin_aarch64_simd_si *) __a); + ret.val[0] = (uint32x2_t) __builtin_aarch64_get_dregciv2si (__o, 0); + ret.val[1] = (uint32x2_t) __builtin_aarch64_get_dregciv2si (__o, 1); + ret.val[2] = (uint32x2_t) __builtin_aarch64_get_dregciv2si (__o, 2); + return ret; +} + +__extension__ extern __inline float16x4x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3_f16 (const float16_t * __a) +{ + float16x4x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3v4hf (__a); + ret.val[0] = __builtin_aarch64_get_dregciv4hf (__o, 0); + ret.val[1] = __builtin_aarch64_get_dregciv4hf (__o, 1); + ret.val[2] = __builtin_aarch64_get_dregciv4hf (__o, 2); + return ret; +} + +__extension__ extern __inline float32x2x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3_f32 (const float32_t * __a) +{ + float32x2x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3v2sf ((const __builtin_aarch64_simd_sf *) __a); + ret.val[0] = (float32x2_t) __builtin_aarch64_get_dregciv2sf (__o, 0); + ret.val[1] = (float32x2_t) __builtin_aarch64_get_dregciv2sf (__o, 1); + ret.val[2] = (float32x2_t) __builtin_aarch64_get_dregciv2sf (__o, 2); + return ret; +} + +__extension__ extern __inline poly64x1x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3_p64 (const poly64_t * __a) +{ + poly64x1x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (poly64x1_t) __builtin_aarch64_get_dregcidi_pss (__o, 0); + ret.val[1] = (poly64x1_t) __builtin_aarch64_get_dregcidi_pss (__o, 1); + ret.val[2] = (poly64x1_t) __builtin_aarch64_get_dregcidi_pss (__o, 2); + return ret; +} + +__extension__ extern __inline int8x16x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3q_s8 (const int8_t * __a) +{ + int8x16x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3v16qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (int8x16_t) __builtin_aarch64_get_qregciv16qi (__o, 0); + ret.val[1] = (int8x16_t) __builtin_aarch64_get_qregciv16qi (__o, 1); + ret.val[2] = (int8x16_t) __builtin_aarch64_get_qregciv16qi (__o, 2); + return ret; +} + +__extension__ extern __inline poly8x16x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3q_p8 (const poly8_t * __a) +{ + poly8x16x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3v16qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (poly8x16_t) __builtin_aarch64_get_qregciv16qi (__o, 0); + ret.val[1] = (poly8x16_t) __builtin_aarch64_get_qregciv16qi (__o, 1); + ret.val[2] = (poly8x16_t) __builtin_aarch64_get_qregciv16qi (__o, 2); + return ret; +} + +__extension__ extern __inline int16x8x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3q_s16 (const int16_t * __a) +{ + int16x8x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3v8hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (int16x8_t) __builtin_aarch64_get_qregciv8hi (__o, 0); + ret.val[1] = (int16x8_t) __builtin_aarch64_get_qregciv8hi (__o, 1); + ret.val[2] = (int16x8_t) __builtin_aarch64_get_qregciv8hi (__o, 2); + return ret; +} + +__extension__ extern __inline poly16x8x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3q_p16 (const poly16_t * __a) +{ + poly16x8x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3v8hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (poly16x8_t) __builtin_aarch64_get_qregciv8hi (__o, 0); + ret.val[1] = (poly16x8_t) __builtin_aarch64_get_qregciv8hi (__o, 1); + ret.val[2] = (poly16x8_t) __builtin_aarch64_get_qregciv8hi (__o, 2); + return ret; +} + +__extension__ extern __inline int32x4x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3q_s32 (const int32_t * __a) +{ + int32x4x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3v4si ((const __builtin_aarch64_simd_si *) __a); + ret.val[0] = (int32x4_t) __builtin_aarch64_get_qregciv4si (__o, 0); + ret.val[1] = (int32x4_t) __builtin_aarch64_get_qregciv4si (__o, 1); + ret.val[2] = (int32x4_t) __builtin_aarch64_get_qregciv4si (__o, 2); + return ret; +} + +__extension__ extern __inline int64x2x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3q_s64 (const int64_t * __a) +{ + int64x2x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3v2di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (int64x2_t) __builtin_aarch64_get_qregciv2di (__o, 0); + ret.val[1] = (int64x2_t) __builtin_aarch64_get_qregciv2di (__o, 1); + ret.val[2] = (int64x2_t) __builtin_aarch64_get_qregciv2di (__o, 2); + return ret; +} + +__extension__ extern __inline uint8x16x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3q_u8 (const uint8_t * __a) +{ + uint8x16x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3v16qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (uint8x16_t) __builtin_aarch64_get_qregciv16qi (__o, 0); + ret.val[1] = (uint8x16_t) __builtin_aarch64_get_qregciv16qi (__o, 1); + ret.val[2] = (uint8x16_t) __builtin_aarch64_get_qregciv16qi (__o, 2); + return ret; +} + +__extension__ extern __inline uint16x8x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3q_u16 (const uint16_t * __a) +{ + uint16x8x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3v8hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (uint16x8_t) __builtin_aarch64_get_qregciv8hi (__o, 0); + ret.val[1] = (uint16x8_t) __builtin_aarch64_get_qregciv8hi (__o, 1); + ret.val[2] = (uint16x8_t) __builtin_aarch64_get_qregciv8hi (__o, 2); + return ret; +} + +__extension__ extern __inline uint32x4x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3q_u32 (const uint32_t * __a) +{ + uint32x4x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3v4si ((const __builtin_aarch64_simd_si *) __a); + ret.val[0] = (uint32x4_t) __builtin_aarch64_get_qregciv4si (__o, 0); + ret.val[1] = (uint32x4_t) __builtin_aarch64_get_qregciv4si (__o, 1); + ret.val[2] = (uint32x4_t) __builtin_aarch64_get_qregciv4si (__o, 2); + return ret; +} + +__extension__ extern __inline uint64x2x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3q_u64 (const uint64_t * __a) +{ + uint64x2x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3v2di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (uint64x2_t) __builtin_aarch64_get_qregciv2di (__o, 0); + ret.val[1] = (uint64x2_t) __builtin_aarch64_get_qregciv2di (__o, 1); + ret.val[2] = (uint64x2_t) __builtin_aarch64_get_qregciv2di (__o, 2); + return ret; +} + +__extension__ extern __inline float16x8x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3q_f16 (const float16_t * __a) +{ + float16x8x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3v8hf (__a); + ret.val[0] = __builtin_aarch64_get_qregciv8hf (__o, 0); + ret.val[1] = __builtin_aarch64_get_qregciv8hf (__o, 1); + ret.val[2] = __builtin_aarch64_get_qregciv8hf (__o, 2); + return ret; +} + +__extension__ extern __inline float32x4x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3q_f32 (const float32_t * __a) +{ + float32x4x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3v4sf ((const __builtin_aarch64_simd_sf *) __a); + ret.val[0] = (float32x4_t) __builtin_aarch64_get_qregciv4sf (__o, 0); + ret.val[1] = (float32x4_t) __builtin_aarch64_get_qregciv4sf (__o, 1); + ret.val[2] = (float32x4_t) __builtin_aarch64_get_qregciv4sf (__o, 2); + return ret; +} + +__extension__ extern __inline float64x2x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3q_f64 (const float64_t * __a) +{ + float64x2x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3v2df ((const __builtin_aarch64_simd_df *) __a); + ret.val[0] = (float64x2_t) __builtin_aarch64_get_qregciv2df (__o, 0); + ret.val[1] = (float64x2_t) __builtin_aarch64_get_qregciv2df (__o, 1); + ret.val[2] = (float64x2_t) __builtin_aarch64_get_qregciv2df (__o, 2); + return ret; +} + +__extension__ extern __inline poly64x2x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3q_p64 (const poly64_t * __a) +{ + poly64x2x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3v2di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (poly64x2_t) __builtin_aarch64_get_qregciv2di_pss (__o, 0); + ret.val[1] = (poly64x2_t) __builtin_aarch64_get_qregciv2di_pss (__o, 1); + ret.val[2] = (poly64x2_t) __builtin_aarch64_get_qregciv2di_pss (__o, 2); + return ret; +} + +__extension__ extern __inline int64x1x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4_s64 (const int64_t * __a) +{ + int64x1x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (int64x1_t) __builtin_aarch64_get_dregxidi (__o, 0); + ret.val[1] = (int64x1_t) __builtin_aarch64_get_dregxidi (__o, 1); + ret.val[2] = (int64x1_t) __builtin_aarch64_get_dregxidi (__o, 2); + ret.val[3] = (int64x1_t) __builtin_aarch64_get_dregxidi (__o, 3); + return ret; +} + +__extension__ extern __inline uint64x1x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4_u64 (const uint64_t * __a) +{ + uint64x1x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (uint64x1_t) __builtin_aarch64_get_dregxidi (__o, 0); + ret.val[1] = (uint64x1_t) __builtin_aarch64_get_dregxidi (__o, 1); + ret.val[2] = (uint64x1_t) __builtin_aarch64_get_dregxidi (__o, 2); + ret.val[3] = (uint64x1_t) __builtin_aarch64_get_dregxidi (__o, 3); + return ret; +} + +__extension__ extern __inline float64x1x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4_f64 (const float64_t * __a) +{ + float64x1x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4df ((const __builtin_aarch64_simd_df *) __a); + ret.val[0] = (float64x1_t) {__builtin_aarch64_get_dregxidf (__o, 0)}; + ret.val[1] = (float64x1_t) {__builtin_aarch64_get_dregxidf (__o, 1)}; + ret.val[2] = (float64x1_t) {__builtin_aarch64_get_dregxidf (__o, 2)}; + ret.val[3] = (float64x1_t) {__builtin_aarch64_get_dregxidf (__o, 3)}; + return ret; +} + +__extension__ extern __inline int8x8x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4_s8 (const int8_t * __a) +{ + int8x8x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4v8qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (int8x8_t) __builtin_aarch64_get_dregxiv8qi (__o, 0); + ret.val[1] = (int8x8_t) __builtin_aarch64_get_dregxiv8qi (__o, 1); + ret.val[2] = (int8x8_t) __builtin_aarch64_get_dregxiv8qi (__o, 2); + ret.val[3] = (int8x8_t) __builtin_aarch64_get_dregxiv8qi (__o, 3); + return ret; +} + +__extension__ extern __inline poly8x8x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4_p8 (const poly8_t * __a) +{ + poly8x8x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4v8qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (poly8x8_t) __builtin_aarch64_get_dregxiv8qi (__o, 0); + ret.val[1] = (poly8x8_t) __builtin_aarch64_get_dregxiv8qi (__o, 1); + ret.val[2] = (poly8x8_t) __builtin_aarch64_get_dregxiv8qi (__o, 2); + ret.val[3] = (poly8x8_t) __builtin_aarch64_get_dregxiv8qi (__o, 3); + return ret; +} + +__extension__ extern __inline int16x4x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4_s16 (const int16_t * __a) +{ + int16x4x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4v4hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (int16x4_t) __builtin_aarch64_get_dregxiv4hi (__o, 0); + ret.val[1] = (int16x4_t) __builtin_aarch64_get_dregxiv4hi (__o, 1); + ret.val[2] = (int16x4_t) __builtin_aarch64_get_dregxiv4hi (__o, 2); + ret.val[3] = (int16x4_t) __builtin_aarch64_get_dregxiv4hi (__o, 3); + return ret; +} + +__extension__ extern __inline poly16x4x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4_p16 (const poly16_t * __a) +{ + poly16x4x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4v4hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (poly16x4_t) __builtin_aarch64_get_dregxiv4hi (__o, 0); + ret.val[1] = (poly16x4_t) __builtin_aarch64_get_dregxiv4hi (__o, 1); + ret.val[2] = (poly16x4_t) __builtin_aarch64_get_dregxiv4hi (__o, 2); + ret.val[3] = (poly16x4_t) __builtin_aarch64_get_dregxiv4hi (__o, 3); + return ret; +} + +__extension__ extern __inline int32x2x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4_s32 (const int32_t * __a) +{ + int32x2x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4v2si ((const __builtin_aarch64_simd_si *) __a); + ret.val[0] = (int32x2_t) __builtin_aarch64_get_dregxiv2si (__o, 0); + ret.val[1] = (int32x2_t) __builtin_aarch64_get_dregxiv2si (__o, 1); + ret.val[2] = (int32x2_t) __builtin_aarch64_get_dregxiv2si (__o, 2); + ret.val[3] = (int32x2_t) __builtin_aarch64_get_dregxiv2si (__o, 3); + return ret; +} + +__extension__ extern __inline uint8x8x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4_u8 (const uint8_t * __a) +{ + uint8x8x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4v8qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (uint8x8_t) __builtin_aarch64_get_dregxiv8qi (__o, 0); + ret.val[1] = (uint8x8_t) __builtin_aarch64_get_dregxiv8qi (__o, 1); + ret.val[2] = (uint8x8_t) __builtin_aarch64_get_dregxiv8qi (__o, 2); + ret.val[3] = (uint8x8_t) __builtin_aarch64_get_dregxiv8qi (__o, 3); + return ret; +} + +__extension__ extern __inline uint16x4x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4_u16 (const uint16_t * __a) +{ + uint16x4x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4v4hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (uint16x4_t) __builtin_aarch64_get_dregxiv4hi (__o, 0); + ret.val[1] = (uint16x4_t) __builtin_aarch64_get_dregxiv4hi (__o, 1); + ret.val[2] = (uint16x4_t) __builtin_aarch64_get_dregxiv4hi (__o, 2); + ret.val[3] = (uint16x4_t) __builtin_aarch64_get_dregxiv4hi (__o, 3); + return ret; +} + +__extension__ extern __inline uint32x2x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4_u32 (const uint32_t * __a) +{ + uint32x2x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4v2si ((const __builtin_aarch64_simd_si *) __a); + ret.val[0] = (uint32x2_t) __builtin_aarch64_get_dregxiv2si (__o, 0); + ret.val[1] = (uint32x2_t) __builtin_aarch64_get_dregxiv2si (__o, 1); + ret.val[2] = (uint32x2_t) __builtin_aarch64_get_dregxiv2si (__o, 2); + ret.val[3] = (uint32x2_t) __builtin_aarch64_get_dregxiv2si (__o, 3); + return ret; +} + +__extension__ extern __inline float16x4x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4_f16 (const float16_t * __a) +{ + float16x4x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4v4hf (__a); + ret.val[0] = __builtin_aarch64_get_dregxiv4hf (__o, 0); + ret.val[1] = __builtin_aarch64_get_dregxiv4hf (__o, 1); + ret.val[2] = __builtin_aarch64_get_dregxiv4hf (__o, 2); + ret.val[3] = __builtin_aarch64_get_dregxiv4hf (__o, 3); + return ret; +} + +__extension__ extern __inline float32x2x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4_f32 (const float32_t * __a) +{ + float32x2x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4v2sf ((const __builtin_aarch64_simd_sf *) __a); + ret.val[0] = (float32x2_t) __builtin_aarch64_get_dregxiv2sf (__o, 0); + ret.val[1] = (float32x2_t) __builtin_aarch64_get_dregxiv2sf (__o, 1); + ret.val[2] = (float32x2_t) __builtin_aarch64_get_dregxiv2sf (__o, 2); + ret.val[3] = (float32x2_t) __builtin_aarch64_get_dregxiv2sf (__o, 3); + return ret; +} + +__extension__ extern __inline poly64x1x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4_p64 (const poly64_t * __a) +{ + poly64x1x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (poly64x1_t) __builtin_aarch64_get_dregxidi_pss (__o, 0); + ret.val[1] = (poly64x1_t) __builtin_aarch64_get_dregxidi_pss (__o, 1); + ret.val[2] = (poly64x1_t) __builtin_aarch64_get_dregxidi_pss (__o, 2); + ret.val[3] = (poly64x1_t) __builtin_aarch64_get_dregxidi_pss (__o, 3); + return ret; +} + +__extension__ extern __inline int8x16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4q_s8 (const int8_t * __a) +{ + int8x16x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4v16qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (int8x16_t) __builtin_aarch64_get_qregxiv16qi (__o, 0); + ret.val[1] = (int8x16_t) __builtin_aarch64_get_qregxiv16qi (__o, 1); + ret.val[2] = (int8x16_t) __builtin_aarch64_get_qregxiv16qi (__o, 2); + ret.val[3] = (int8x16_t) __builtin_aarch64_get_qregxiv16qi (__o, 3); + return ret; +} + +__extension__ extern __inline poly8x16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4q_p8 (const poly8_t * __a) +{ + poly8x16x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4v16qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (poly8x16_t) __builtin_aarch64_get_qregxiv16qi (__o, 0); + ret.val[1] = (poly8x16_t) __builtin_aarch64_get_qregxiv16qi (__o, 1); + ret.val[2] = (poly8x16_t) __builtin_aarch64_get_qregxiv16qi (__o, 2); + ret.val[3] = (poly8x16_t) __builtin_aarch64_get_qregxiv16qi (__o, 3); + return ret; +} + +__extension__ extern __inline int16x8x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4q_s16 (const int16_t * __a) +{ + int16x8x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4v8hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (int16x8_t) __builtin_aarch64_get_qregxiv8hi (__o, 0); + ret.val[1] = (int16x8_t) __builtin_aarch64_get_qregxiv8hi (__o, 1); + ret.val[2] = (int16x8_t) __builtin_aarch64_get_qregxiv8hi (__o, 2); + ret.val[3] = (int16x8_t) __builtin_aarch64_get_qregxiv8hi (__o, 3); + return ret; +} + +__extension__ extern __inline poly16x8x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4q_p16 (const poly16_t * __a) +{ + poly16x8x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4v8hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (poly16x8_t) __builtin_aarch64_get_qregxiv8hi (__o, 0); + ret.val[1] = (poly16x8_t) __builtin_aarch64_get_qregxiv8hi (__o, 1); + ret.val[2] = (poly16x8_t) __builtin_aarch64_get_qregxiv8hi (__o, 2); + ret.val[3] = (poly16x8_t) __builtin_aarch64_get_qregxiv8hi (__o, 3); + return ret; +} + +__extension__ extern __inline int32x4x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4q_s32 (const int32_t * __a) +{ + int32x4x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4v4si ((const __builtin_aarch64_simd_si *) __a); + ret.val[0] = (int32x4_t) __builtin_aarch64_get_qregxiv4si (__o, 0); + ret.val[1] = (int32x4_t) __builtin_aarch64_get_qregxiv4si (__o, 1); + ret.val[2] = (int32x4_t) __builtin_aarch64_get_qregxiv4si (__o, 2); + ret.val[3] = (int32x4_t) __builtin_aarch64_get_qregxiv4si (__o, 3); + return ret; +} + +__extension__ extern __inline int64x2x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4q_s64 (const int64_t * __a) +{ + int64x2x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4v2di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (int64x2_t) __builtin_aarch64_get_qregxiv2di (__o, 0); + ret.val[1] = (int64x2_t) __builtin_aarch64_get_qregxiv2di (__o, 1); + ret.val[2] = (int64x2_t) __builtin_aarch64_get_qregxiv2di (__o, 2); + ret.val[3] = (int64x2_t) __builtin_aarch64_get_qregxiv2di (__o, 3); + return ret; +} + +__extension__ extern __inline uint8x16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4q_u8 (const uint8_t * __a) +{ + uint8x16x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4v16qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (uint8x16_t) __builtin_aarch64_get_qregxiv16qi (__o, 0); + ret.val[1] = (uint8x16_t) __builtin_aarch64_get_qregxiv16qi (__o, 1); + ret.val[2] = (uint8x16_t) __builtin_aarch64_get_qregxiv16qi (__o, 2); + ret.val[3] = (uint8x16_t) __builtin_aarch64_get_qregxiv16qi (__o, 3); + return ret; +} + +__extension__ extern __inline uint16x8x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4q_u16 (const uint16_t * __a) +{ + uint16x8x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4v8hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (uint16x8_t) __builtin_aarch64_get_qregxiv8hi (__o, 0); + ret.val[1] = (uint16x8_t) __builtin_aarch64_get_qregxiv8hi (__o, 1); + ret.val[2] = (uint16x8_t) __builtin_aarch64_get_qregxiv8hi (__o, 2); + ret.val[3] = (uint16x8_t) __builtin_aarch64_get_qregxiv8hi (__o, 3); + return ret; +} + +__extension__ extern __inline uint32x4x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4q_u32 (const uint32_t * __a) +{ + uint32x4x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4v4si ((const __builtin_aarch64_simd_si *) __a); + ret.val[0] = (uint32x4_t) __builtin_aarch64_get_qregxiv4si (__o, 0); + ret.val[1] = (uint32x4_t) __builtin_aarch64_get_qregxiv4si (__o, 1); + ret.val[2] = (uint32x4_t) __builtin_aarch64_get_qregxiv4si (__o, 2); + ret.val[3] = (uint32x4_t) __builtin_aarch64_get_qregxiv4si (__o, 3); + return ret; +} + +__extension__ extern __inline uint64x2x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4q_u64 (const uint64_t * __a) +{ + uint64x2x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4v2di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (uint64x2_t) __builtin_aarch64_get_qregxiv2di (__o, 0); + ret.val[1] = (uint64x2_t) __builtin_aarch64_get_qregxiv2di (__o, 1); + ret.val[2] = (uint64x2_t) __builtin_aarch64_get_qregxiv2di (__o, 2); + ret.val[3] = (uint64x2_t) __builtin_aarch64_get_qregxiv2di (__o, 3); + return ret; +} + +__extension__ extern __inline float16x8x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4q_f16 (const float16_t * __a) +{ + float16x8x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4v8hf (__a); + ret.val[0] = __builtin_aarch64_get_qregxiv8hf (__o, 0); + ret.val[1] = __builtin_aarch64_get_qregxiv8hf (__o, 1); + ret.val[2] = __builtin_aarch64_get_qregxiv8hf (__o, 2); + ret.val[3] = __builtin_aarch64_get_qregxiv8hf (__o, 3); + return ret; +} + +__extension__ extern __inline float32x4x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4q_f32 (const float32_t * __a) +{ + float32x4x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4v4sf ((const __builtin_aarch64_simd_sf *) __a); + ret.val[0] = (float32x4_t) __builtin_aarch64_get_qregxiv4sf (__o, 0); + ret.val[1] = (float32x4_t) __builtin_aarch64_get_qregxiv4sf (__o, 1); + ret.val[2] = (float32x4_t) __builtin_aarch64_get_qregxiv4sf (__o, 2); + ret.val[3] = (float32x4_t) __builtin_aarch64_get_qregxiv4sf (__o, 3); + return ret; +} + +__extension__ extern __inline float64x2x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4q_f64 (const float64_t * __a) +{ + float64x2x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4v2df ((const __builtin_aarch64_simd_df *) __a); + ret.val[0] = (float64x2_t) __builtin_aarch64_get_qregxiv2df (__o, 0); + ret.val[1] = (float64x2_t) __builtin_aarch64_get_qregxiv2df (__o, 1); + ret.val[2] = (float64x2_t) __builtin_aarch64_get_qregxiv2df (__o, 2); + ret.val[3] = (float64x2_t) __builtin_aarch64_get_qregxiv2df (__o, 3); + return ret; +} + +__extension__ extern __inline poly64x2x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4q_p64 (const poly64_t * __a) +{ + poly64x2x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4v2di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (poly64x2_t) __builtin_aarch64_get_qregxiv2di_pss (__o, 0); + ret.val[1] = (poly64x2_t) __builtin_aarch64_get_qregxiv2di_pss (__o, 1); + ret.val[2] = (poly64x2_t) __builtin_aarch64_get_qregxiv2di_pss (__o, 2); + ret.val[3] = (poly64x2_t) __builtin_aarch64_get_qregxiv2di_pss (__o, 3); + return ret; +} + +/* vldn_dup */ + +__extension__ extern __inline int8x8x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2_dup_s8 (const int8_t * __a) +{ + int8x8x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2rv8qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (int8x8_t) __builtin_aarch64_get_dregoiv8qi (__o, 0); + ret.val[1] = (int8x8_t) __builtin_aarch64_get_dregoiv8qi (__o, 1); + return ret; +} + +__extension__ extern __inline int16x4x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2_dup_s16 (const int16_t * __a) +{ + int16x4x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2rv4hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (int16x4_t) __builtin_aarch64_get_dregoiv4hi (__o, 0); + ret.val[1] = (int16x4_t) __builtin_aarch64_get_dregoiv4hi (__o, 1); + return ret; +} + +__extension__ extern __inline int32x2x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2_dup_s32 (const int32_t * __a) +{ + int32x2x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2rv2si ((const __builtin_aarch64_simd_si *) __a); + ret.val[0] = (int32x2_t) __builtin_aarch64_get_dregoiv2si (__o, 0); + ret.val[1] = (int32x2_t) __builtin_aarch64_get_dregoiv2si (__o, 1); + return ret; +} + +__extension__ extern __inline float16x4x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2_dup_f16 (const float16_t * __a) +{ + float16x4x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2rv4hf ((const __builtin_aarch64_simd_hf *) __a); + ret.val[0] = __builtin_aarch64_get_dregoiv4hf (__o, 0); + ret.val[1] = (float16x4_t) __builtin_aarch64_get_dregoiv4hf (__o, 1); + return ret; +} + +__extension__ extern __inline float32x2x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2_dup_f32 (const float32_t * __a) +{ + float32x2x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2rv2sf ((const __builtin_aarch64_simd_sf *) __a); + ret.val[0] = (float32x2_t) __builtin_aarch64_get_dregoiv2sf (__o, 0); + ret.val[1] = (float32x2_t) __builtin_aarch64_get_dregoiv2sf (__o, 1); + return ret; +} + +__extension__ extern __inline float64x1x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2_dup_f64 (const float64_t * __a) +{ + float64x1x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2rdf ((const __builtin_aarch64_simd_df *) __a); + ret.val[0] = (float64x1_t) {__builtin_aarch64_get_dregoidf (__o, 0)}; + ret.val[1] = (float64x1_t) {__builtin_aarch64_get_dregoidf (__o, 1)}; + return ret; +} + +__extension__ extern __inline uint8x8x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2_dup_u8 (const uint8_t * __a) +{ + uint8x8x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2rv8qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (uint8x8_t) __builtin_aarch64_get_dregoiv8qi (__o, 0); + ret.val[1] = (uint8x8_t) __builtin_aarch64_get_dregoiv8qi (__o, 1); + return ret; +} + +__extension__ extern __inline uint16x4x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2_dup_u16 (const uint16_t * __a) +{ + uint16x4x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2rv4hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (uint16x4_t) __builtin_aarch64_get_dregoiv4hi (__o, 0); + ret.val[1] = (uint16x4_t) __builtin_aarch64_get_dregoiv4hi (__o, 1); + return ret; +} + +__extension__ extern __inline uint32x2x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2_dup_u32 (const uint32_t * __a) +{ + uint32x2x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2rv2si ((const __builtin_aarch64_simd_si *) __a); + ret.val[0] = (uint32x2_t) __builtin_aarch64_get_dregoiv2si (__o, 0); + ret.val[1] = (uint32x2_t) __builtin_aarch64_get_dregoiv2si (__o, 1); + return ret; +} + +__extension__ extern __inline poly8x8x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2_dup_p8 (const poly8_t * __a) +{ + poly8x8x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2rv8qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (poly8x8_t) __builtin_aarch64_get_dregoiv8qi (__o, 0); + ret.val[1] = (poly8x8_t) __builtin_aarch64_get_dregoiv8qi (__o, 1); + return ret; +} + +__extension__ extern __inline poly16x4x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2_dup_p16 (const poly16_t * __a) +{ + poly16x4x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2rv4hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (poly16x4_t) __builtin_aarch64_get_dregoiv4hi (__o, 0); + ret.val[1] = (poly16x4_t) __builtin_aarch64_get_dregoiv4hi (__o, 1); + return ret; +} + +__extension__ extern __inline poly64x1x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2_dup_p64 (const poly64_t * __a) +{ + poly64x1x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2rv2di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (poly64x1_t) __builtin_aarch64_get_dregoidi_pss (__o, 0); + ret.val[1] = (poly64x1_t) __builtin_aarch64_get_dregoidi_pss (__o, 1); + return ret; +} + + +__extension__ extern __inline int64x1x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2_dup_s64 (const int64_t * __a) +{ + int64x1x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2rdi ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (int64x1_t) __builtin_aarch64_get_dregoidi (__o, 0); + ret.val[1] = (int64x1_t) __builtin_aarch64_get_dregoidi (__o, 1); + return ret; +} + +__extension__ extern __inline uint64x1x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2_dup_u64 (const uint64_t * __a) +{ + uint64x1x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2rdi ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (uint64x1_t) __builtin_aarch64_get_dregoidi (__o, 0); + ret.val[1] = (uint64x1_t) __builtin_aarch64_get_dregoidi (__o, 1); + return ret; +} + +__extension__ extern __inline int8x16x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2q_dup_s8 (const int8_t * __a) +{ + int8x16x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2rv16qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (int8x16_t) __builtin_aarch64_get_qregoiv16qi (__o, 0); + ret.val[1] = (int8x16_t) __builtin_aarch64_get_qregoiv16qi (__o, 1); + return ret; +} + +__extension__ extern __inline poly8x16x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2q_dup_p8 (const poly8_t * __a) +{ + poly8x16x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2rv16qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (poly8x16_t) __builtin_aarch64_get_qregoiv16qi (__o, 0); + ret.val[1] = (poly8x16_t) __builtin_aarch64_get_qregoiv16qi (__o, 1); + return ret; +} + +__extension__ extern __inline int16x8x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2q_dup_s16 (const int16_t * __a) +{ + int16x8x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2rv8hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (int16x8_t) __builtin_aarch64_get_qregoiv8hi (__o, 0); + ret.val[1] = (int16x8_t) __builtin_aarch64_get_qregoiv8hi (__o, 1); + return ret; +} + +__extension__ extern __inline poly16x8x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2q_dup_p16 (const poly16_t * __a) +{ + poly16x8x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2rv8hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (poly16x8_t) __builtin_aarch64_get_qregoiv8hi (__o, 0); + ret.val[1] = (poly16x8_t) __builtin_aarch64_get_qregoiv8hi (__o, 1); + return ret; +} + +__extension__ extern __inline int32x4x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2q_dup_s32 (const int32_t * __a) +{ + int32x4x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2rv4si ((const __builtin_aarch64_simd_si *) __a); + ret.val[0] = (int32x4_t) __builtin_aarch64_get_qregoiv4si (__o, 0); + ret.val[1] = (int32x4_t) __builtin_aarch64_get_qregoiv4si (__o, 1); + return ret; +} + +__extension__ extern __inline int64x2x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2q_dup_s64 (const int64_t * __a) +{ + int64x2x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2rv2di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (int64x2_t) __builtin_aarch64_get_qregoiv2di (__o, 0); + ret.val[1] = (int64x2_t) __builtin_aarch64_get_qregoiv2di (__o, 1); + return ret; +} + +__extension__ extern __inline uint8x16x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2q_dup_u8 (const uint8_t * __a) +{ + uint8x16x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2rv16qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (uint8x16_t) __builtin_aarch64_get_qregoiv16qi (__o, 0); + ret.val[1] = (uint8x16_t) __builtin_aarch64_get_qregoiv16qi (__o, 1); + return ret; +} + +__extension__ extern __inline uint16x8x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2q_dup_u16 (const uint16_t * __a) +{ + uint16x8x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2rv8hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (uint16x8_t) __builtin_aarch64_get_qregoiv8hi (__o, 0); + ret.val[1] = (uint16x8_t) __builtin_aarch64_get_qregoiv8hi (__o, 1); + return ret; +} + +__extension__ extern __inline uint32x4x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2q_dup_u32 (const uint32_t * __a) +{ + uint32x4x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2rv4si ((const __builtin_aarch64_simd_si *) __a); + ret.val[0] = (uint32x4_t) __builtin_aarch64_get_qregoiv4si (__o, 0); + ret.val[1] = (uint32x4_t) __builtin_aarch64_get_qregoiv4si (__o, 1); + return ret; +} + +__extension__ extern __inline uint64x2x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2q_dup_u64 (const uint64_t * __a) +{ + uint64x2x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2rv2di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (uint64x2_t) __builtin_aarch64_get_qregoiv2di (__o, 0); + ret.val[1] = (uint64x2_t) __builtin_aarch64_get_qregoiv2di (__o, 1); + return ret; +} + +__extension__ extern __inline float16x8x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2q_dup_f16 (const float16_t * __a) +{ + float16x8x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2rv8hf ((const __builtin_aarch64_simd_hf *) __a); + ret.val[0] = (float16x8_t) __builtin_aarch64_get_qregoiv8hf (__o, 0); + ret.val[1] = __builtin_aarch64_get_qregoiv8hf (__o, 1); + return ret; +} + +__extension__ extern __inline float32x4x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2q_dup_f32 (const float32_t * __a) +{ + float32x4x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2rv4sf ((const __builtin_aarch64_simd_sf *) __a); + ret.val[0] = (float32x4_t) __builtin_aarch64_get_qregoiv4sf (__o, 0); + ret.val[1] = (float32x4_t) __builtin_aarch64_get_qregoiv4sf (__o, 1); + return ret; +} + +__extension__ extern __inline float64x2x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2q_dup_f64 (const float64_t * __a) +{ + float64x2x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2rv2df ((const __builtin_aarch64_simd_df *) __a); + ret.val[0] = (float64x2_t) __builtin_aarch64_get_qregoiv2df (__o, 0); + ret.val[1] = (float64x2_t) __builtin_aarch64_get_qregoiv2df (__o, 1); + return ret; +} + +__extension__ extern __inline poly64x2x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld2q_dup_p64 (const poly64_t * __a) +{ + poly64x2x2_t ret; + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_ld2rv2di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (poly64x2_t) __builtin_aarch64_get_qregoiv2di_pss (__o, 0); + ret.val[1] = (poly64x2_t) __builtin_aarch64_get_qregoiv2di_pss (__o, 1); + return ret; +} + +__extension__ extern __inline int64x1x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3_dup_s64 (const int64_t * __a) +{ + int64x1x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3rdi ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (int64x1_t) __builtin_aarch64_get_dregcidi (__o, 0); + ret.val[1] = (int64x1_t) __builtin_aarch64_get_dregcidi (__o, 1); + ret.val[2] = (int64x1_t) __builtin_aarch64_get_dregcidi (__o, 2); + return ret; +} + +__extension__ extern __inline uint64x1x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3_dup_u64 (const uint64_t * __a) +{ + uint64x1x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3rdi ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (uint64x1_t) __builtin_aarch64_get_dregcidi (__o, 0); + ret.val[1] = (uint64x1_t) __builtin_aarch64_get_dregcidi (__o, 1); + ret.val[2] = (uint64x1_t) __builtin_aarch64_get_dregcidi (__o, 2); + return ret; +} + +__extension__ extern __inline float64x1x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3_dup_f64 (const float64_t * __a) +{ + float64x1x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3rdf ((const __builtin_aarch64_simd_df *) __a); + ret.val[0] = (float64x1_t) {__builtin_aarch64_get_dregcidf (__o, 0)}; + ret.val[1] = (float64x1_t) {__builtin_aarch64_get_dregcidf (__o, 1)}; + ret.val[2] = (float64x1_t) {__builtin_aarch64_get_dregcidf (__o, 2)}; + return ret; +} + +__extension__ extern __inline int8x8x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3_dup_s8 (const int8_t * __a) +{ + int8x8x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3rv8qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (int8x8_t) __builtin_aarch64_get_dregciv8qi (__o, 0); + ret.val[1] = (int8x8_t) __builtin_aarch64_get_dregciv8qi (__o, 1); + ret.val[2] = (int8x8_t) __builtin_aarch64_get_dregciv8qi (__o, 2); + return ret; +} + +__extension__ extern __inline poly8x8x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3_dup_p8 (const poly8_t * __a) +{ + poly8x8x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3rv8qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (poly8x8_t) __builtin_aarch64_get_dregciv8qi (__o, 0); + ret.val[1] = (poly8x8_t) __builtin_aarch64_get_dregciv8qi (__o, 1); + ret.val[2] = (poly8x8_t) __builtin_aarch64_get_dregciv8qi (__o, 2); + return ret; +} + +__extension__ extern __inline int16x4x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3_dup_s16 (const int16_t * __a) +{ + int16x4x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3rv4hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (int16x4_t) __builtin_aarch64_get_dregciv4hi (__o, 0); + ret.val[1] = (int16x4_t) __builtin_aarch64_get_dregciv4hi (__o, 1); + ret.val[2] = (int16x4_t) __builtin_aarch64_get_dregciv4hi (__o, 2); + return ret; +} + +__extension__ extern __inline poly16x4x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3_dup_p16 (const poly16_t * __a) +{ + poly16x4x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3rv4hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (poly16x4_t) __builtin_aarch64_get_dregciv4hi (__o, 0); + ret.val[1] = (poly16x4_t) __builtin_aarch64_get_dregciv4hi (__o, 1); + ret.val[2] = (poly16x4_t) __builtin_aarch64_get_dregciv4hi (__o, 2); + return ret; +} + +__extension__ extern __inline int32x2x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3_dup_s32 (const int32_t * __a) +{ + int32x2x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3rv2si ((const __builtin_aarch64_simd_si *) __a); + ret.val[0] = (int32x2_t) __builtin_aarch64_get_dregciv2si (__o, 0); + ret.val[1] = (int32x2_t) __builtin_aarch64_get_dregciv2si (__o, 1); + ret.val[2] = (int32x2_t) __builtin_aarch64_get_dregciv2si (__o, 2); + return ret; +} + +__extension__ extern __inline uint8x8x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3_dup_u8 (const uint8_t * __a) +{ + uint8x8x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3rv8qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (uint8x8_t) __builtin_aarch64_get_dregciv8qi (__o, 0); + ret.val[1] = (uint8x8_t) __builtin_aarch64_get_dregciv8qi (__o, 1); + ret.val[2] = (uint8x8_t) __builtin_aarch64_get_dregciv8qi (__o, 2); + return ret; +} + +__extension__ extern __inline uint16x4x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3_dup_u16 (const uint16_t * __a) +{ + uint16x4x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3rv4hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (uint16x4_t) __builtin_aarch64_get_dregciv4hi (__o, 0); + ret.val[1] = (uint16x4_t) __builtin_aarch64_get_dregciv4hi (__o, 1); + ret.val[2] = (uint16x4_t) __builtin_aarch64_get_dregciv4hi (__o, 2); + return ret; +} + +__extension__ extern __inline uint32x2x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3_dup_u32 (const uint32_t * __a) +{ + uint32x2x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3rv2si ((const __builtin_aarch64_simd_si *) __a); + ret.val[0] = (uint32x2_t) __builtin_aarch64_get_dregciv2si (__o, 0); + ret.val[1] = (uint32x2_t) __builtin_aarch64_get_dregciv2si (__o, 1); + ret.val[2] = (uint32x2_t) __builtin_aarch64_get_dregciv2si (__o, 2); + return ret; +} + +__extension__ extern __inline float16x4x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3_dup_f16 (const float16_t * __a) +{ + float16x4x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3rv4hf ((const __builtin_aarch64_simd_hf *) __a); + ret.val[0] = (float16x4_t) __builtin_aarch64_get_dregciv4hf (__o, 0); + ret.val[1] = (float16x4_t) __builtin_aarch64_get_dregciv4hf (__o, 1); + ret.val[2] = (float16x4_t) __builtin_aarch64_get_dregciv4hf (__o, 2); + return ret; +} + +__extension__ extern __inline float32x2x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3_dup_f32 (const float32_t * __a) +{ + float32x2x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3rv2sf ((const __builtin_aarch64_simd_sf *) __a); + ret.val[0] = (float32x2_t) __builtin_aarch64_get_dregciv2sf (__o, 0); + ret.val[1] = (float32x2_t) __builtin_aarch64_get_dregciv2sf (__o, 1); + ret.val[2] = (float32x2_t) __builtin_aarch64_get_dregciv2sf (__o, 2); + return ret; +} + +__extension__ extern __inline poly64x1x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3_dup_p64 (const poly64_t * __a) +{ + poly64x1x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3rv2di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (poly64x1_t) __builtin_aarch64_get_dregcidi_pss (__o, 0); + ret.val[1] = (poly64x1_t) __builtin_aarch64_get_dregcidi_pss (__o, 1); + ret.val[2] = (poly64x1_t) __builtin_aarch64_get_dregcidi_pss (__o, 2); + return ret; +} + +__extension__ extern __inline int8x16x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3q_dup_s8 (const int8_t * __a) +{ + int8x16x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3rv16qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (int8x16_t) __builtin_aarch64_get_qregciv16qi (__o, 0); + ret.val[1] = (int8x16_t) __builtin_aarch64_get_qregciv16qi (__o, 1); + ret.val[2] = (int8x16_t) __builtin_aarch64_get_qregciv16qi (__o, 2); + return ret; +} + +__extension__ extern __inline poly8x16x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3q_dup_p8 (const poly8_t * __a) +{ + poly8x16x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3rv16qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (poly8x16_t) __builtin_aarch64_get_qregciv16qi (__o, 0); + ret.val[1] = (poly8x16_t) __builtin_aarch64_get_qregciv16qi (__o, 1); + ret.val[2] = (poly8x16_t) __builtin_aarch64_get_qregciv16qi (__o, 2); + return ret; +} + +__extension__ extern __inline int16x8x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3q_dup_s16 (const int16_t * __a) +{ + int16x8x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3rv8hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (int16x8_t) __builtin_aarch64_get_qregciv8hi (__o, 0); + ret.val[1] = (int16x8_t) __builtin_aarch64_get_qregciv8hi (__o, 1); + ret.val[2] = (int16x8_t) __builtin_aarch64_get_qregciv8hi (__o, 2); + return ret; +} + +__extension__ extern __inline poly16x8x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3q_dup_p16 (const poly16_t * __a) +{ + poly16x8x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3rv8hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (poly16x8_t) __builtin_aarch64_get_qregciv8hi (__o, 0); + ret.val[1] = (poly16x8_t) __builtin_aarch64_get_qregciv8hi (__o, 1); + ret.val[2] = (poly16x8_t) __builtin_aarch64_get_qregciv8hi (__o, 2); + return ret; +} + +__extension__ extern __inline int32x4x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3q_dup_s32 (const int32_t * __a) +{ + int32x4x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3rv4si ((const __builtin_aarch64_simd_si *) __a); + ret.val[0] = (int32x4_t) __builtin_aarch64_get_qregciv4si (__o, 0); + ret.val[1] = (int32x4_t) __builtin_aarch64_get_qregciv4si (__o, 1); + ret.val[2] = (int32x4_t) __builtin_aarch64_get_qregciv4si (__o, 2); + return ret; +} + +__extension__ extern __inline int64x2x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3q_dup_s64 (const int64_t * __a) +{ + int64x2x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3rv2di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (int64x2_t) __builtin_aarch64_get_qregciv2di (__o, 0); + ret.val[1] = (int64x2_t) __builtin_aarch64_get_qregciv2di (__o, 1); + ret.val[2] = (int64x2_t) __builtin_aarch64_get_qregciv2di (__o, 2); + return ret; +} + +__extension__ extern __inline uint8x16x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3q_dup_u8 (const uint8_t * __a) +{ + uint8x16x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3rv16qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (uint8x16_t) __builtin_aarch64_get_qregciv16qi (__o, 0); + ret.val[1] = (uint8x16_t) __builtin_aarch64_get_qregciv16qi (__o, 1); + ret.val[2] = (uint8x16_t) __builtin_aarch64_get_qregciv16qi (__o, 2); + return ret; +} + +__extension__ extern __inline uint16x8x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3q_dup_u16 (const uint16_t * __a) +{ + uint16x8x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3rv8hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (uint16x8_t) __builtin_aarch64_get_qregciv8hi (__o, 0); + ret.val[1] = (uint16x8_t) __builtin_aarch64_get_qregciv8hi (__o, 1); + ret.val[2] = (uint16x8_t) __builtin_aarch64_get_qregciv8hi (__o, 2); + return ret; +} + +__extension__ extern __inline uint32x4x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3q_dup_u32 (const uint32_t * __a) +{ + uint32x4x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3rv4si ((const __builtin_aarch64_simd_si *) __a); + ret.val[0] = (uint32x4_t) __builtin_aarch64_get_qregciv4si (__o, 0); + ret.val[1] = (uint32x4_t) __builtin_aarch64_get_qregciv4si (__o, 1); + ret.val[2] = (uint32x4_t) __builtin_aarch64_get_qregciv4si (__o, 2); + return ret; +} + +__extension__ extern __inline uint64x2x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3q_dup_u64 (const uint64_t * __a) +{ + uint64x2x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3rv2di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (uint64x2_t) __builtin_aarch64_get_qregciv2di (__o, 0); + ret.val[1] = (uint64x2_t) __builtin_aarch64_get_qregciv2di (__o, 1); + ret.val[2] = (uint64x2_t) __builtin_aarch64_get_qregciv2di (__o, 2); + return ret; +} + +__extension__ extern __inline float16x8x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3q_dup_f16 (const float16_t * __a) +{ + float16x8x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3rv8hf ((const __builtin_aarch64_simd_hf *) __a); + ret.val[0] = (float16x8_t) __builtin_aarch64_get_qregciv8hf (__o, 0); + ret.val[1] = (float16x8_t) __builtin_aarch64_get_qregciv8hf (__o, 1); + ret.val[2] = (float16x8_t) __builtin_aarch64_get_qregciv8hf (__o, 2); + return ret; +} + +__extension__ extern __inline float32x4x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3q_dup_f32 (const float32_t * __a) +{ + float32x4x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3rv4sf ((const __builtin_aarch64_simd_sf *) __a); + ret.val[0] = (float32x4_t) __builtin_aarch64_get_qregciv4sf (__o, 0); + ret.val[1] = (float32x4_t) __builtin_aarch64_get_qregciv4sf (__o, 1); + ret.val[2] = (float32x4_t) __builtin_aarch64_get_qregciv4sf (__o, 2); + return ret; +} + +__extension__ extern __inline float64x2x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3q_dup_f64 (const float64_t * __a) +{ + float64x2x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3rv2df ((const __builtin_aarch64_simd_df *) __a); + ret.val[0] = (float64x2_t) __builtin_aarch64_get_qregciv2df (__o, 0); + ret.val[1] = (float64x2_t) __builtin_aarch64_get_qregciv2df (__o, 1); + ret.val[2] = (float64x2_t) __builtin_aarch64_get_qregciv2df (__o, 2); + return ret; +} + +__extension__ extern __inline poly64x2x3_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld3q_dup_p64 (const poly64_t * __a) +{ + poly64x2x3_t ret; + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_ld3rv2di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (poly64x2_t) __builtin_aarch64_get_qregciv2di_pss (__o, 0); + ret.val[1] = (poly64x2_t) __builtin_aarch64_get_qregciv2di_pss (__o, 1); + ret.val[2] = (poly64x2_t) __builtin_aarch64_get_qregciv2di_pss (__o, 2); + return ret; +} + +__extension__ extern __inline int64x1x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4_dup_s64 (const int64_t * __a) +{ + int64x1x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4rdi ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (int64x1_t) __builtin_aarch64_get_dregxidi (__o, 0); + ret.val[1] = (int64x1_t) __builtin_aarch64_get_dregxidi (__o, 1); + ret.val[2] = (int64x1_t) __builtin_aarch64_get_dregxidi (__o, 2); + ret.val[3] = (int64x1_t) __builtin_aarch64_get_dregxidi (__o, 3); + return ret; +} + +__extension__ extern __inline uint64x1x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4_dup_u64 (const uint64_t * __a) +{ + uint64x1x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4rdi ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (uint64x1_t) __builtin_aarch64_get_dregxidi (__o, 0); + ret.val[1] = (uint64x1_t) __builtin_aarch64_get_dregxidi (__o, 1); + ret.val[2] = (uint64x1_t) __builtin_aarch64_get_dregxidi (__o, 2); + ret.val[3] = (uint64x1_t) __builtin_aarch64_get_dregxidi (__o, 3); + return ret; +} + +__extension__ extern __inline float64x1x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4_dup_f64 (const float64_t * __a) +{ + float64x1x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4rdf ((const __builtin_aarch64_simd_df *) __a); + ret.val[0] = (float64x1_t) {__builtin_aarch64_get_dregxidf (__o, 0)}; + ret.val[1] = (float64x1_t) {__builtin_aarch64_get_dregxidf (__o, 1)}; + ret.val[2] = (float64x1_t) {__builtin_aarch64_get_dregxidf (__o, 2)}; + ret.val[3] = (float64x1_t) {__builtin_aarch64_get_dregxidf (__o, 3)}; + return ret; +} + +__extension__ extern __inline int8x8x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4_dup_s8 (const int8_t * __a) +{ + int8x8x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4rv8qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (int8x8_t) __builtin_aarch64_get_dregxiv8qi (__o, 0); + ret.val[1] = (int8x8_t) __builtin_aarch64_get_dregxiv8qi (__o, 1); + ret.val[2] = (int8x8_t) __builtin_aarch64_get_dregxiv8qi (__o, 2); + ret.val[3] = (int8x8_t) __builtin_aarch64_get_dregxiv8qi (__o, 3); + return ret; +} + +__extension__ extern __inline poly8x8x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4_dup_p8 (const poly8_t * __a) +{ + poly8x8x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4rv8qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (poly8x8_t) __builtin_aarch64_get_dregxiv8qi (__o, 0); + ret.val[1] = (poly8x8_t) __builtin_aarch64_get_dregxiv8qi (__o, 1); + ret.val[2] = (poly8x8_t) __builtin_aarch64_get_dregxiv8qi (__o, 2); + ret.val[3] = (poly8x8_t) __builtin_aarch64_get_dregxiv8qi (__o, 3); + return ret; +} + +__extension__ extern __inline int16x4x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4_dup_s16 (const int16_t * __a) +{ + int16x4x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4rv4hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (int16x4_t) __builtin_aarch64_get_dregxiv4hi (__o, 0); + ret.val[1] = (int16x4_t) __builtin_aarch64_get_dregxiv4hi (__o, 1); + ret.val[2] = (int16x4_t) __builtin_aarch64_get_dregxiv4hi (__o, 2); + ret.val[3] = (int16x4_t) __builtin_aarch64_get_dregxiv4hi (__o, 3); + return ret; +} + +__extension__ extern __inline poly16x4x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4_dup_p16 (const poly16_t * __a) +{ + poly16x4x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4rv4hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (poly16x4_t) __builtin_aarch64_get_dregxiv4hi (__o, 0); + ret.val[1] = (poly16x4_t) __builtin_aarch64_get_dregxiv4hi (__o, 1); + ret.val[2] = (poly16x4_t) __builtin_aarch64_get_dregxiv4hi (__o, 2); + ret.val[3] = (poly16x4_t) __builtin_aarch64_get_dregxiv4hi (__o, 3); + return ret; +} + +__extension__ extern __inline int32x2x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4_dup_s32 (const int32_t * __a) +{ + int32x2x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4rv2si ((const __builtin_aarch64_simd_si *) __a); + ret.val[0] = (int32x2_t) __builtin_aarch64_get_dregxiv2si (__o, 0); + ret.val[1] = (int32x2_t) __builtin_aarch64_get_dregxiv2si (__o, 1); + ret.val[2] = (int32x2_t) __builtin_aarch64_get_dregxiv2si (__o, 2); + ret.val[3] = (int32x2_t) __builtin_aarch64_get_dregxiv2si (__o, 3); + return ret; +} + +__extension__ extern __inline uint8x8x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4_dup_u8 (const uint8_t * __a) +{ + uint8x8x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4rv8qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (uint8x8_t) __builtin_aarch64_get_dregxiv8qi (__o, 0); + ret.val[1] = (uint8x8_t) __builtin_aarch64_get_dregxiv8qi (__o, 1); + ret.val[2] = (uint8x8_t) __builtin_aarch64_get_dregxiv8qi (__o, 2); + ret.val[3] = (uint8x8_t) __builtin_aarch64_get_dregxiv8qi (__o, 3); + return ret; +} + +__extension__ extern __inline uint16x4x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4_dup_u16 (const uint16_t * __a) +{ + uint16x4x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4rv4hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (uint16x4_t) __builtin_aarch64_get_dregxiv4hi (__o, 0); + ret.val[1] = (uint16x4_t) __builtin_aarch64_get_dregxiv4hi (__o, 1); + ret.val[2] = (uint16x4_t) __builtin_aarch64_get_dregxiv4hi (__o, 2); + ret.val[3] = (uint16x4_t) __builtin_aarch64_get_dregxiv4hi (__o, 3); + return ret; +} + +__extension__ extern __inline uint32x2x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4_dup_u32 (const uint32_t * __a) +{ + uint32x2x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4rv2si ((const __builtin_aarch64_simd_si *) __a); + ret.val[0] = (uint32x2_t) __builtin_aarch64_get_dregxiv2si (__o, 0); + ret.val[1] = (uint32x2_t) __builtin_aarch64_get_dregxiv2si (__o, 1); + ret.val[2] = (uint32x2_t) __builtin_aarch64_get_dregxiv2si (__o, 2); + ret.val[3] = (uint32x2_t) __builtin_aarch64_get_dregxiv2si (__o, 3); + return ret; +} + +__extension__ extern __inline float16x4x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4_dup_f16 (const float16_t * __a) +{ + float16x4x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4rv4hf ((const __builtin_aarch64_simd_hf *) __a); + ret.val[0] = (float16x4_t) __builtin_aarch64_get_dregxiv4hf (__o, 0); + ret.val[1] = (float16x4_t) __builtin_aarch64_get_dregxiv4hf (__o, 1); + ret.val[2] = (float16x4_t) __builtin_aarch64_get_dregxiv4hf (__o, 2); + ret.val[3] = (float16x4_t) __builtin_aarch64_get_dregxiv4hf (__o, 3); + return ret; +} + +__extension__ extern __inline float32x2x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4_dup_f32 (const float32_t * __a) +{ + float32x2x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4rv2sf ((const __builtin_aarch64_simd_sf *) __a); + ret.val[0] = (float32x2_t) __builtin_aarch64_get_dregxiv2sf (__o, 0); + ret.val[1] = (float32x2_t) __builtin_aarch64_get_dregxiv2sf (__o, 1); + ret.val[2] = (float32x2_t) __builtin_aarch64_get_dregxiv2sf (__o, 2); + ret.val[3] = (float32x2_t) __builtin_aarch64_get_dregxiv2sf (__o, 3); + return ret; +} + +__extension__ extern __inline poly64x1x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4_dup_p64 (const poly64_t * __a) +{ + poly64x1x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4rv2di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (poly64x1_t) __builtin_aarch64_get_dregxidi_pss (__o, 0); + ret.val[1] = (poly64x1_t) __builtin_aarch64_get_dregxidi_pss (__o, 1); + ret.val[2] = (poly64x1_t) __builtin_aarch64_get_dregxidi_pss (__o, 2); + ret.val[3] = (poly64x1_t) __builtin_aarch64_get_dregxidi_pss (__o, 3); + return ret; +} + +__extension__ extern __inline int8x16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4q_dup_s8 (const int8_t * __a) +{ + int8x16x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4rv16qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (int8x16_t) __builtin_aarch64_get_qregxiv16qi (__o, 0); + ret.val[1] = (int8x16_t) __builtin_aarch64_get_qregxiv16qi (__o, 1); + ret.val[2] = (int8x16_t) __builtin_aarch64_get_qregxiv16qi (__o, 2); + ret.val[3] = (int8x16_t) __builtin_aarch64_get_qregxiv16qi (__o, 3); + return ret; +} + +__extension__ extern __inline poly8x16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4q_dup_p8 (const poly8_t * __a) +{ + poly8x16x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4rv16qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (poly8x16_t) __builtin_aarch64_get_qregxiv16qi (__o, 0); + ret.val[1] = (poly8x16_t) __builtin_aarch64_get_qregxiv16qi (__o, 1); + ret.val[2] = (poly8x16_t) __builtin_aarch64_get_qregxiv16qi (__o, 2); + ret.val[3] = (poly8x16_t) __builtin_aarch64_get_qregxiv16qi (__o, 3); + return ret; +} + +__extension__ extern __inline int16x8x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4q_dup_s16 (const int16_t * __a) +{ + int16x8x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4rv8hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (int16x8_t) __builtin_aarch64_get_qregxiv8hi (__o, 0); + ret.val[1] = (int16x8_t) __builtin_aarch64_get_qregxiv8hi (__o, 1); + ret.val[2] = (int16x8_t) __builtin_aarch64_get_qregxiv8hi (__o, 2); + ret.val[3] = (int16x8_t) __builtin_aarch64_get_qregxiv8hi (__o, 3); + return ret; +} + +__extension__ extern __inline poly16x8x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4q_dup_p16 (const poly16_t * __a) +{ + poly16x8x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4rv8hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (poly16x8_t) __builtin_aarch64_get_qregxiv8hi (__o, 0); + ret.val[1] = (poly16x8_t) __builtin_aarch64_get_qregxiv8hi (__o, 1); + ret.val[2] = (poly16x8_t) __builtin_aarch64_get_qregxiv8hi (__o, 2); + ret.val[3] = (poly16x8_t) __builtin_aarch64_get_qregxiv8hi (__o, 3); + return ret; +} + +__extension__ extern __inline int32x4x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4q_dup_s32 (const int32_t * __a) +{ + int32x4x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4rv4si ((const __builtin_aarch64_simd_si *) __a); + ret.val[0] = (int32x4_t) __builtin_aarch64_get_qregxiv4si (__o, 0); + ret.val[1] = (int32x4_t) __builtin_aarch64_get_qregxiv4si (__o, 1); + ret.val[2] = (int32x4_t) __builtin_aarch64_get_qregxiv4si (__o, 2); + ret.val[3] = (int32x4_t) __builtin_aarch64_get_qregxiv4si (__o, 3); + return ret; +} + +__extension__ extern __inline int64x2x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4q_dup_s64 (const int64_t * __a) +{ + int64x2x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4rv2di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (int64x2_t) __builtin_aarch64_get_qregxiv2di (__o, 0); + ret.val[1] = (int64x2_t) __builtin_aarch64_get_qregxiv2di (__o, 1); + ret.val[2] = (int64x2_t) __builtin_aarch64_get_qregxiv2di (__o, 2); + ret.val[3] = (int64x2_t) __builtin_aarch64_get_qregxiv2di (__o, 3); + return ret; +} + +__extension__ extern __inline uint8x16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4q_dup_u8 (const uint8_t * __a) +{ + uint8x16x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4rv16qi ((const __builtin_aarch64_simd_qi *) __a); + ret.val[0] = (uint8x16_t) __builtin_aarch64_get_qregxiv16qi (__o, 0); + ret.val[1] = (uint8x16_t) __builtin_aarch64_get_qregxiv16qi (__o, 1); + ret.val[2] = (uint8x16_t) __builtin_aarch64_get_qregxiv16qi (__o, 2); + ret.val[3] = (uint8x16_t) __builtin_aarch64_get_qregxiv16qi (__o, 3); + return ret; +} + +__extension__ extern __inline uint16x8x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4q_dup_u16 (const uint16_t * __a) +{ + uint16x8x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4rv8hi ((const __builtin_aarch64_simd_hi *) __a); + ret.val[0] = (uint16x8_t) __builtin_aarch64_get_qregxiv8hi (__o, 0); + ret.val[1] = (uint16x8_t) __builtin_aarch64_get_qregxiv8hi (__o, 1); + ret.val[2] = (uint16x8_t) __builtin_aarch64_get_qregxiv8hi (__o, 2); + ret.val[3] = (uint16x8_t) __builtin_aarch64_get_qregxiv8hi (__o, 3); + return ret; +} + +__extension__ extern __inline uint32x4x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4q_dup_u32 (const uint32_t * __a) +{ + uint32x4x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4rv4si ((const __builtin_aarch64_simd_si *) __a); + ret.val[0] = (uint32x4_t) __builtin_aarch64_get_qregxiv4si (__o, 0); + ret.val[1] = (uint32x4_t) __builtin_aarch64_get_qregxiv4si (__o, 1); + ret.val[2] = (uint32x4_t) __builtin_aarch64_get_qregxiv4si (__o, 2); + ret.val[3] = (uint32x4_t) __builtin_aarch64_get_qregxiv4si (__o, 3); + return ret; +} + +__extension__ extern __inline uint64x2x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4q_dup_u64 (const uint64_t * __a) +{ + uint64x2x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4rv2di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (uint64x2_t) __builtin_aarch64_get_qregxiv2di (__o, 0); + ret.val[1] = (uint64x2_t) __builtin_aarch64_get_qregxiv2di (__o, 1); + ret.val[2] = (uint64x2_t) __builtin_aarch64_get_qregxiv2di (__o, 2); + ret.val[3] = (uint64x2_t) __builtin_aarch64_get_qregxiv2di (__o, 3); + return ret; +} + +__extension__ extern __inline float16x8x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4q_dup_f16 (const float16_t * __a) +{ + float16x8x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4rv8hf ((const __builtin_aarch64_simd_hf *) __a); + ret.val[0] = (float16x8_t) __builtin_aarch64_get_qregxiv8hf (__o, 0); + ret.val[1] = (float16x8_t) __builtin_aarch64_get_qregxiv8hf (__o, 1); + ret.val[2] = (float16x8_t) __builtin_aarch64_get_qregxiv8hf (__o, 2); + ret.val[3] = (float16x8_t) __builtin_aarch64_get_qregxiv8hf (__o, 3); + return ret; +} + +__extension__ extern __inline float32x4x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4q_dup_f32 (const float32_t * __a) +{ + float32x4x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4rv4sf ((const __builtin_aarch64_simd_sf *) __a); + ret.val[0] = (float32x4_t) __builtin_aarch64_get_qregxiv4sf (__o, 0); + ret.val[1] = (float32x4_t) __builtin_aarch64_get_qregxiv4sf (__o, 1); + ret.val[2] = (float32x4_t) __builtin_aarch64_get_qregxiv4sf (__o, 2); + ret.val[3] = (float32x4_t) __builtin_aarch64_get_qregxiv4sf (__o, 3); + return ret; +} + +__extension__ extern __inline float64x2x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4q_dup_f64 (const float64_t * __a) +{ + float64x2x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4rv2df ((const __builtin_aarch64_simd_df *) __a); + ret.val[0] = (float64x2_t) __builtin_aarch64_get_qregxiv2df (__o, 0); + ret.val[1] = (float64x2_t) __builtin_aarch64_get_qregxiv2df (__o, 1); + ret.val[2] = (float64x2_t) __builtin_aarch64_get_qregxiv2df (__o, 2); + ret.val[3] = (float64x2_t) __builtin_aarch64_get_qregxiv2df (__o, 3); + return ret; +} + +__extension__ extern __inline poly64x2x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vld4q_dup_p64 (const poly64_t * __a) +{ + poly64x2x4_t ret; + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_ld4rv2di ((const __builtin_aarch64_simd_di *) __a); + ret.val[0] = (poly64x2_t) __builtin_aarch64_get_qregxiv2di_pss (__o, 0); + ret.val[1] = (poly64x2_t) __builtin_aarch64_get_qregxiv2di_pss (__o, 1); + ret.val[2] = (poly64x2_t) __builtin_aarch64_get_qregxiv2di_pss (__o, 2); + ret.val[3] = (poly64x2_t) __builtin_aarch64_get_qregxiv2di_pss (__o, 3); + return ret; +} + +/* vld2_lane */ + +#define __LD2_LANE_FUNC(intype, vectype, largetype, ptrtype, mode, \ + qmode, ptrmode, funcsuffix, signedtype) \ +__extension__ extern __inline intype \ +__attribute__ ((__always_inline__, __gnu_inline__,__artificial__)) \ +vld2_lane_##funcsuffix (const ptrtype * __ptr, intype __b, const int __c) \ +{ \ + __builtin_aarch64_simd_oi __o; \ + largetype __temp; \ + __temp.val[0] = \ + vcombine_##funcsuffix (__b.val[0], vcreate_##funcsuffix (0)); \ + __temp.val[1] = \ + vcombine_##funcsuffix (__b.val[1], vcreate_##funcsuffix (0)); \ + __o = __builtin_aarch64_set_qregoi##qmode (__o, \ + (signedtype) __temp.val[0], \ + 0); \ + __o = __builtin_aarch64_set_qregoi##qmode (__o, \ + (signedtype) __temp.val[1], \ + 1); \ + __o = __builtin_aarch64_ld2_lane##mode ( \ + (__builtin_aarch64_simd_##ptrmode *) __ptr, __o, __c); \ + __b.val[0] = (vectype) __builtin_aarch64_get_dregoidi (__o, 0); \ + __b.val[1] = (vectype) __builtin_aarch64_get_dregoidi (__o, 1); \ + return __b; \ +} + +__LD2_LANE_FUNC (float16x4x2_t, float16x4_t, float16x8x2_t, float16_t, v4hf, + v8hf, hf, f16, float16x8_t) +__LD2_LANE_FUNC (float32x2x2_t, float32x2_t, float32x4x2_t, float32_t, v2sf, v4sf, + sf, f32, float32x4_t) +__LD2_LANE_FUNC (float64x1x2_t, float64x1_t, float64x2x2_t, float64_t, df, v2df, + df, f64, float64x2_t) +__LD2_LANE_FUNC (poly8x8x2_t, poly8x8_t, poly8x16x2_t, poly8_t, v8qi, v16qi, qi, p8, + int8x16_t) +__LD2_LANE_FUNC (poly16x4x2_t, poly16x4_t, poly16x8x2_t, poly16_t, v4hi, v8hi, hi, + p16, int16x8_t) +__LD2_LANE_FUNC (poly64x1x2_t, poly64x1_t, poly64x2x2_t, poly64_t, di, + v2di_ssps, di, p64, poly64x2_t) +__LD2_LANE_FUNC (int8x8x2_t, int8x8_t, int8x16x2_t, int8_t, v8qi, v16qi, qi, s8, + int8x16_t) +__LD2_LANE_FUNC (int16x4x2_t, int16x4_t, int16x8x2_t, int16_t, v4hi, v8hi, hi, s16, + int16x8_t) +__LD2_LANE_FUNC (int32x2x2_t, int32x2_t, int32x4x2_t, int32_t, v2si, v4si, si, s32, + int32x4_t) +__LD2_LANE_FUNC (int64x1x2_t, int64x1_t, int64x2x2_t, int64_t, di, v2di, di, s64, + int64x2_t) +__LD2_LANE_FUNC (uint8x8x2_t, uint8x8_t, uint8x16x2_t, uint8_t, v8qi, v16qi, qi, u8, + int8x16_t) +__LD2_LANE_FUNC (uint16x4x2_t, uint16x4_t, uint16x8x2_t, uint16_t, v4hi, v8hi, hi, + u16, int16x8_t) +__LD2_LANE_FUNC (uint32x2x2_t, uint32x2_t, uint32x4x2_t, uint32_t, v2si, v4si, si, + u32, int32x4_t) +__LD2_LANE_FUNC (uint64x1x2_t, uint64x1_t, uint64x2x2_t, uint64_t, di, v2di, di, + u64, int64x2_t) + +#undef __LD2_LANE_FUNC + +/* vld2q_lane */ + +#define __LD2_LANE_FUNC(intype, vtype, ptrtype, mode, ptrmode, funcsuffix) \ +__extension__ extern __inline intype \ +__attribute__ ((__always_inline__, __gnu_inline__,__artificial__)) \ +vld2q_lane_##funcsuffix (const ptrtype * __ptr, intype __b, const int __c) \ +{ \ + __builtin_aarch64_simd_oi __o; \ + intype ret; \ + __o = __builtin_aarch64_set_qregoiv4si (__o, (int32x4_t) __b.val[0], 0); \ + __o = __builtin_aarch64_set_qregoiv4si (__o, (int32x4_t) __b.val[1], 1); \ + __o = __builtin_aarch64_ld2_lane##mode ( \ + (__builtin_aarch64_simd_##ptrmode *) __ptr, __o, __c); \ + ret.val[0] = (vtype) __builtin_aarch64_get_qregoiv4si (__o, 0); \ + ret.val[1] = (vtype) __builtin_aarch64_get_qregoiv4si (__o, 1); \ + return ret; \ +} + +__LD2_LANE_FUNC (float16x8x2_t, float16x8_t, float16_t, v8hf, hf, f16) +__LD2_LANE_FUNC (float32x4x2_t, float32x4_t, float32_t, v4sf, sf, f32) +__LD2_LANE_FUNC (float64x2x2_t, float64x2_t, float64_t, v2df, df, f64) +__LD2_LANE_FUNC (poly8x16x2_t, poly8x16_t, poly8_t, v16qi, qi, p8) +__LD2_LANE_FUNC (poly16x8x2_t, poly16x8_t, poly16_t, v8hi, hi, p16) +__LD2_LANE_FUNC (poly64x2x2_t, poly64x2_t, poly64_t, v2di, di, p64) +__LD2_LANE_FUNC (int8x16x2_t, int8x16_t, int8_t, v16qi, qi, s8) +__LD2_LANE_FUNC (int16x8x2_t, int16x8_t, int16_t, v8hi, hi, s16) +__LD2_LANE_FUNC (int32x4x2_t, int32x4_t, int32_t, v4si, si, s32) +__LD2_LANE_FUNC (int64x2x2_t, int64x2_t, int64_t, v2di, di, s64) +__LD2_LANE_FUNC (uint8x16x2_t, uint8x16_t, uint8_t, v16qi, qi, u8) +__LD2_LANE_FUNC (uint16x8x2_t, uint16x8_t, uint16_t, v8hi, hi, u16) +__LD2_LANE_FUNC (uint32x4x2_t, uint32x4_t, uint32_t, v4si, si, u32) +__LD2_LANE_FUNC (uint64x2x2_t, uint64x2_t, uint64_t, v2di, di, u64) + +#undef __LD2_LANE_FUNC + +/* vld3_lane */ + +#define __LD3_LANE_FUNC(intype, vectype, largetype, ptrtype, mode, \ + qmode, ptrmode, funcsuffix, signedtype) \ +__extension__ extern __inline intype \ +__attribute__ ((__always_inline__, __gnu_inline__,__artificial__)) \ +vld3_lane_##funcsuffix (const ptrtype * __ptr, intype __b, const int __c) \ +{ \ + __builtin_aarch64_simd_ci __o; \ + largetype __temp; \ + __temp.val[0] = \ + vcombine_##funcsuffix (__b.val[0], vcreate_##funcsuffix (0)); \ + __temp.val[1] = \ + vcombine_##funcsuffix (__b.val[1], vcreate_##funcsuffix (0)); \ + __temp.val[2] = \ + vcombine_##funcsuffix (__b.val[2], vcreate_##funcsuffix (0)); \ + __o = __builtin_aarch64_set_qregci##qmode (__o, \ + (signedtype) __temp.val[0], \ + 0); \ + __o = __builtin_aarch64_set_qregci##qmode (__o, \ + (signedtype) __temp.val[1], \ + 1); \ + __o = __builtin_aarch64_set_qregci##qmode (__o, \ + (signedtype) __temp.val[2], \ + 2); \ + __o = __builtin_aarch64_ld3_lane##mode ( \ + (__builtin_aarch64_simd_##ptrmode *) __ptr, __o, __c); \ + __b.val[0] = (vectype) __builtin_aarch64_get_dregcidi (__o, 0); \ + __b.val[1] = (vectype) __builtin_aarch64_get_dregcidi (__o, 1); \ + __b.val[2] = (vectype) __builtin_aarch64_get_dregcidi (__o, 2); \ + return __b; \ +} + +__LD3_LANE_FUNC (float16x4x3_t, float16x4_t, float16x8x3_t, float16_t, v4hf, + v8hf, hf, f16, float16x8_t) +__LD3_LANE_FUNC (float32x2x3_t, float32x2_t, float32x4x3_t, float32_t, v2sf, v4sf, + sf, f32, float32x4_t) +__LD3_LANE_FUNC (float64x1x3_t, float64x1_t, float64x2x3_t, float64_t, df, v2df, + df, f64, float64x2_t) +__LD3_LANE_FUNC (poly8x8x3_t, poly8x8_t, poly8x16x3_t, poly8_t, v8qi, v16qi, qi, p8, + int8x16_t) +__LD3_LANE_FUNC (poly16x4x3_t, poly16x4_t, poly16x8x3_t, poly16_t, v4hi, v8hi, hi, + p16, int16x8_t) +__LD3_LANE_FUNC (poly64x1x3_t, poly64x1_t, poly64x2x3_t, poly64_t, di, + v2di_ssps, di, p64, poly64x2_t) +__LD3_LANE_FUNC (int8x8x3_t, int8x8_t, int8x16x3_t, int8_t, v8qi, v16qi, qi, s8, + int8x16_t) +__LD3_LANE_FUNC (int16x4x3_t, int16x4_t, int16x8x3_t, int16_t, v4hi, v8hi, hi, s16, + int16x8_t) +__LD3_LANE_FUNC (int32x2x3_t, int32x2_t, int32x4x3_t, int32_t, v2si, v4si, si, s32, + int32x4_t) +__LD3_LANE_FUNC (int64x1x3_t, int64x1_t, int64x2x3_t, int64_t, di, v2di, di, s64, + int64x2_t) +__LD3_LANE_FUNC (uint8x8x3_t, uint8x8_t, uint8x16x3_t, uint8_t, v8qi, v16qi, qi, u8, + int8x16_t) +__LD3_LANE_FUNC (uint16x4x3_t, uint16x4_t, uint16x8x3_t, uint16_t, v4hi, v8hi, hi, + u16, int16x8_t) +__LD3_LANE_FUNC (uint32x2x3_t, uint32x2_t, uint32x4x3_t, uint32_t, v2si, v4si, si, + u32, int32x4_t) +__LD3_LANE_FUNC (uint64x1x3_t, uint64x1_t, uint64x2x3_t, uint64_t, di, v2di, di, + u64, int64x2_t) + +#undef __LD3_LANE_FUNC + +/* vld3q_lane */ + +#define __LD3_LANE_FUNC(intype, vtype, ptrtype, mode, ptrmode, funcsuffix) \ +__extension__ extern __inline intype \ +__attribute__ ((__always_inline__, __gnu_inline__,__artificial__)) \ +vld3q_lane_##funcsuffix (const ptrtype * __ptr, intype __b, const int __c) \ +{ \ + __builtin_aarch64_simd_ci __o; \ + intype ret; \ + __o = __builtin_aarch64_set_qregciv4si (__o, (int32x4_t) __b.val[0], 0); \ + __o = __builtin_aarch64_set_qregciv4si (__o, (int32x4_t) __b.val[1], 1); \ + __o = __builtin_aarch64_set_qregciv4si (__o, (int32x4_t) __b.val[2], 2); \ + __o = __builtin_aarch64_ld3_lane##mode ( \ + (__builtin_aarch64_simd_##ptrmode *) __ptr, __o, __c); \ + ret.val[0] = (vtype) __builtin_aarch64_get_qregciv4si (__o, 0); \ + ret.val[1] = (vtype) __builtin_aarch64_get_qregciv4si (__o, 1); \ + ret.val[2] = (vtype) __builtin_aarch64_get_qregciv4si (__o, 2); \ + return ret; \ +} + +__LD3_LANE_FUNC (float16x8x3_t, float16x8_t, float16_t, v8hf, hf, f16) +__LD3_LANE_FUNC (float32x4x3_t, float32x4_t, float32_t, v4sf, sf, f32) +__LD3_LANE_FUNC (float64x2x3_t, float64x2_t, float64_t, v2df, df, f64) +__LD3_LANE_FUNC (poly8x16x3_t, poly8x16_t, poly8_t, v16qi, qi, p8) +__LD3_LANE_FUNC (poly16x8x3_t, poly16x8_t, poly16_t, v8hi, hi, p16) +__LD3_LANE_FUNC (poly64x2x3_t, poly64x2_t, poly64_t, v2di, di, p64) +__LD3_LANE_FUNC (int8x16x3_t, int8x16_t, int8_t, v16qi, qi, s8) +__LD3_LANE_FUNC (int16x8x3_t, int16x8_t, int16_t, v8hi, hi, s16) +__LD3_LANE_FUNC (int32x4x3_t, int32x4_t, int32_t, v4si, si, s32) +__LD3_LANE_FUNC (int64x2x3_t, int64x2_t, int64_t, v2di, di, s64) +__LD3_LANE_FUNC (uint8x16x3_t, uint8x16_t, uint8_t, v16qi, qi, u8) +__LD3_LANE_FUNC (uint16x8x3_t, uint16x8_t, uint16_t, v8hi, hi, u16) +__LD3_LANE_FUNC (uint32x4x3_t, uint32x4_t, uint32_t, v4si, si, u32) +__LD3_LANE_FUNC (uint64x2x3_t, uint64x2_t, uint64_t, v2di, di, u64) + +#undef __LD3_LANE_FUNC + +/* vld4_lane */ + +#define __LD4_LANE_FUNC(intype, vectype, largetype, ptrtype, mode, \ + qmode, ptrmode, funcsuffix, signedtype) \ +__extension__ extern __inline intype \ +__attribute__ ((__always_inline__, __gnu_inline__,__artificial__)) \ +vld4_lane_##funcsuffix (const ptrtype * __ptr, intype __b, const int __c) \ +{ \ + __builtin_aarch64_simd_xi __o; \ + largetype __temp; \ + __temp.val[0] = \ + vcombine_##funcsuffix (__b.val[0], vcreate_##funcsuffix (0)); \ + __temp.val[1] = \ + vcombine_##funcsuffix (__b.val[1], vcreate_##funcsuffix (0)); \ + __temp.val[2] = \ + vcombine_##funcsuffix (__b.val[2], vcreate_##funcsuffix (0)); \ + __temp.val[3] = \ + vcombine_##funcsuffix (__b.val[3], vcreate_##funcsuffix (0)); \ + __o = __builtin_aarch64_set_qregxi##qmode (__o, \ + (signedtype) __temp.val[0], \ + 0); \ + __o = __builtin_aarch64_set_qregxi##qmode (__o, \ + (signedtype) __temp.val[1], \ + 1); \ + __o = __builtin_aarch64_set_qregxi##qmode (__o, \ + (signedtype) __temp.val[2], \ + 2); \ + __o = __builtin_aarch64_set_qregxi##qmode (__o, \ + (signedtype) __temp.val[3], \ + 3); \ + __o = __builtin_aarch64_ld4_lane##mode ( \ + (__builtin_aarch64_simd_##ptrmode *) __ptr, __o, __c); \ + __b.val[0] = (vectype) __builtin_aarch64_get_dregxidi (__o, 0); \ + __b.val[1] = (vectype) __builtin_aarch64_get_dregxidi (__o, 1); \ + __b.val[2] = (vectype) __builtin_aarch64_get_dregxidi (__o, 2); \ + __b.val[3] = (vectype) __builtin_aarch64_get_dregxidi (__o, 3); \ + return __b; \ +} + +/* vld4q_lane */ + +__LD4_LANE_FUNC (float16x4x4_t, float16x4_t, float16x8x4_t, float16_t, v4hf, + v8hf, hf, f16, float16x8_t) +__LD4_LANE_FUNC (float32x2x4_t, float32x2_t, float32x4x4_t, float32_t, v2sf, v4sf, + sf, f32, float32x4_t) +__LD4_LANE_FUNC (float64x1x4_t, float64x1_t, float64x2x4_t, float64_t, df, v2df, + df, f64, float64x2_t) +__LD4_LANE_FUNC (poly8x8x4_t, poly8x8_t, poly8x16x4_t, poly8_t, v8qi, v16qi, qi, p8, + int8x16_t) +__LD4_LANE_FUNC (poly16x4x4_t, poly16x4_t, poly16x8x4_t, poly16_t, v4hi, v8hi, hi, + p16, int16x8_t) +__LD4_LANE_FUNC (poly64x1x4_t, poly64x1_t, poly64x2x4_t, poly64_t, di, + v2di_ssps, di, p64, poly64x2_t) +__LD4_LANE_FUNC (int8x8x4_t, int8x8_t, int8x16x4_t, int8_t, v8qi, v16qi, qi, s8, + int8x16_t) +__LD4_LANE_FUNC (int16x4x4_t, int16x4_t, int16x8x4_t, int16_t, v4hi, v8hi, hi, s16, + int16x8_t) +__LD4_LANE_FUNC (int32x2x4_t, int32x2_t, int32x4x4_t, int32_t, v2si, v4si, si, s32, + int32x4_t) +__LD4_LANE_FUNC (int64x1x4_t, int64x1_t, int64x2x4_t, int64_t, di, v2di, di, s64, + int64x2_t) +__LD4_LANE_FUNC (uint8x8x4_t, uint8x8_t, uint8x16x4_t, uint8_t, v8qi, v16qi, qi, u8, + int8x16_t) +__LD4_LANE_FUNC (uint16x4x4_t, uint16x4_t, uint16x8x4_t, uint16_t, v4hi, v8hi, hi, + u16, int16x8_t) +__LD4_LANE_FUNC (uint32x2x4_t, uint32x2_t, uint32x4x4_t, uint32_t, v2si, v4si, si, + u32, int32x4_t) +__LD4_LANE_FUNC (uint64x1x4_t, uint64x1_t, uint64x2x4_t, uint64_t, di, v2di, di, + u64, int64x2_t) + +#undef __LD4_LANE_FUNC + +/* vld4q_lane */ + +#define __LD4_LANE_FUNC(intype, vtype, ptrtype, mode, ptrmode, funcsuffix) \ +__extension__ extern __inline intype \ +__attribute__ ((__always_inline__, __gnu_inline__,__artificial__)) \ +vld4q_lane_##funcsuffix (const ptrtype * __ptr, intype __b, const int __c) \ +{ \ + __builtin_aarch64_simd_xi __o; \ + intype ret; \ + __o = __builtin_aarch64_set_qregxiv4si (__o, (int32x4_t) __b.val[0], 0); \ + __o = __builtin_aarch64_set_qregxiv4si (__o, (int32x4_t) __b.val[1], 1); \ + __o = __builtin_aarch64_set_qregxiv4si (__o, (int32x4_t) __b.val[2], 2); \ + __o = __builtin_aarch64_set_qregxiv4si (__o, (int32x4_t) __b.val[3], 3); \ + __o = __builtin_aarch64_ld4_lane##mode ( \ + (__builtin_aarch64_simd_##ptrmode *) __ptr, __o, __c); \ + ret.val[0] = (vtype) __builtin_aarch64_get_qregxiv4si (__o, 0); \ + ret.val[1] = (vtype) __builtin_aarch64_get_qregxiv4si (__o, 1); \ + ret.val[2] = (vtype) __builtin_aarch64_get_qregxiv4si (__o, 2); \ + ret.val[3] = (vtype) __builtin_aarch64_get_qregxiv4si (__o, 3); \ + return ret; \ +} + +__LD4_LANE_FUNC (float16x8x4_t, float16x8_t, float16_t, v8hf, hf, f16) +__LD4_LANE_FUNC (float32x4x4_t, float32x4_t, float32_t, v4sf, sf, f32) +__LD4_LANE_FUNC (float64x2x4_t, float64x2_t, float64_t, v2df, df, f64) +__LD4_LANE_FUNC (poly8x16x4_t, poly8x16_t, poly8_t, v16qi, qi, p8) +__LD4_LANE_FUNC (poly16x8x4_t, poly16x8_t, poly16_t, v8hi, hi, p16) +__LD4_LANE_FUNC (poly64x2x4_t, poly64x2_t, poly64_t, v2di, di, p64) +__LD4_LANE_FUNC (int8x16x4_t, int8x16_t, int8_t, v16qi, qi, s8) +__LD4_LANE_FUNC (int16x8x4_t, int16x8_t, int16_t, v8hi, hi, s16) +__LD4_LANE_FUNC (int32x4x4_t, int32x4_t, int32_t, v4si, si, s32) +__LD4_LANE_FUNC (int64x2x4_t, int64x2_t, int64_t, v2di, di, s64) +__LD4_LANE_FUNC (uint8x16x4_t, uint8x16_t, uint8_t, v16qi, qi, u8) +__LD4_LANE_FUNC (uint16x8x4_t, uint16x8_t, uint16_t, v8hi, hi, u16) +__LD4_LANE_FUNC (uint32x4x4_t, uint32x4_t, uint32_t, v4si, si, u32) +__LD4_LANE_FUNC (uint64x2x4_t, uint64x2_t, uint64_t, v2di, di, u64) + +#undef __LD4_LANE_FUNC + +/* vmax */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmax_f32 (float32x2_t __a, float32x2_t __b) +{ + return __builtin_aarch64_smax_nanv2sf (__a, __b); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmax_f64 (float64x1_t __a, float64x1_t __b) +{ + return (float64x1_t) + { __builtin_aarch64_smax_nandf (vget_lane_f64 (__a, 0), + vget_lane_f64 (__b, 0)) }; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmax_s8 (int8x8_t __a, int8x8_t __b) +{ + return __builtin_aarch64_smaxv8qi (__a, __b); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmax_s16 (int16x4_t __a, int16x4_t __b) +{ + return __builtin_aarch64_smaxv4hi (__a, __b); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmax_s32 (int32x2_t __a, int32x2_t __b) +{ + return __builtin_aarch64_smaxv2si (__a, __b); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmax_u8 (uint8x8_t __a, uint8x8_t __b) +{ + return (uint8x8_t) __builtin_aarch64_umaxv8qi ((int8x8_t) __a, + (int8x8_t) __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmax_u16 (uint16x4_t __a, uint16x4_t __b) +{ + return (uint16x4_t) __builtin_aarch64_umaxv4hi ((int16x4_t) __a, + (int16x4_t) __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmax_u32 (uint32x2_t __a, uint32x2_t __b) +{ + return (uint32x2_t) __builtin_aarch64_umaxv2si ((int32x2_t) __a, + (int32x2_t) __b); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxq_f32 (float32x4_t __a, float32x4_t __b) +{ + return __builtin_aarch64_smax_nanv4sf (__a, __b); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxq_f64 (float64x2_t __a, float64x2_t __b) +{ + return __builtin_aarch64_smax_nanv2df (__a, __b); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxq_s8 (int8x16_t __a, int8x16_t __b) +{ + return __builtin_aarch64_smaxv16qi (__a, __b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxq_s16 (int16x8_t __a, int16x8_t __b) +{ + return __builtin_aarch64_smaxv8hi (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxq_s32 (int32x4_t __a, int32x4_t __b) +{ + return __builtin_aarch64_smaxv4si (__a, __b); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxq_u8 (uint8x16_t __a, uint8x16_t __b) +{ + return (uint8x16_t) __builtin_aarch64_umaxv16qi ((int8x16_t) __a, + (int8x16_t) __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxq_u16 (uint16x8_t __a, uint16x8_t __b) +{ + return (uint16x8_t) __builtin_aarch64_umaxv8hi ((int16x8_t) __a, + (int16x8_t) __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxq_u32 (uint32x4_t __a, uint32x4_t __b) +{ + return (uint32x4_t) __builtin_aarch64_umaxv4si ((int32x4_t) __a, + (int32x4_t) __b); +} +/* vmulx */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulx_f32 (float32x2_t __a, float32x2_t __b) +{ + return __builtin_aarch64_fmulxv2sf (__a, __b); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulxq_f32 (float32x4_t __a, float32x4_t __b) +{ + return __builtin_aarch64_fmulxv4sf (__a, __b); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulx_f64 (float64x1_t __a, float64x1_t __b) +{ + return (float64x1_t) {__builtin_aarch64_fmulxdf (__a[0], __b[0])}; +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulxq_f64 (float64x2_t __a, float64x2_t __b) +{ + return __builtin_aarch64_fmulxv2df (__a, __b); +} + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulxs_f32 (float32_t __a, float32_t __b) +{ + return __builtin_aarch64_fmulxsf (__a, __b); +} + +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulxd_f64 (float64_t __a, float64_t __b) +{ + return __builtin_aarch64_fmulxdf (__a, __b); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulx_lane_f32 (float32x2_t __a, float32x2_t __v, const int __lane) +{ + return vmulx_f32 (__a, __aarch64_vdup_lane_f32 (__v, __lane)); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulx_lane_f64 (float64x1_t __a, float64x1_t __v, const int __lane) +{ + return vmulx_f64 (__a, __aarch64_vdup_lane_f64 (__v, __lane)); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulxq_lane_f32 (float32x4_t __a, float32x2_t __v, const int __lane) +{ + return vmulxq_f32 (__a, __aarch64_vdupq_lane_f32 (__v, __lane)); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulxq_lane_f64 (float64x2_t __a, float64x1_t __v, const int __lane) +{ + return vmulxq_f64 (__a, __aarch64_vdupq_lane_f64 (__v, __lane)); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulx_laneq_f32 (float32x2_t __a, float32x4_t __v, const int __lane) +{ + return vmulx_f32 (__a, __aarch64_vdup_laneq_f32 (__v, __lane)); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulx_laneq_f64 (float64x1_t __a, float64x2_t __v, const int __lane) +{ + return vmulx_f64 (__a, __aarch64_vdup_laneq_f64 (__v, __lane)); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulxq_laneq_f32 (float32x4_t __a, float32x4_t __v, const int __lane) +{ + return vmulxq_f32 (__a, __aarch64_vdupq_laneq_f32 (__v, __lane)); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulxq_laneq_f64 (float64x2_t __a, float64x2_t __v, const int __lane) +{ + return vmulxq_f64 (__a, __aarch64_vdupq_laneq_f64 (__v, __lane)); +} + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulxs_lane_f32 (float32_t __a, float32x2_t __v, const int __lane) +{ + return vmulxs_f32 (__a, __aarch64_vget_lane_any (__v, __lane)); +} + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulxs_laneq_f32 (float32_t __a, float32x4_t __v, const int __lane) +{ + return vmulxs_f32 (__a, __aarch64_vget_lane_any (__v, __lane)); +} + +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulxd_lane_f64 (float64_t __a, float64x1_t __v, const int __lane) +{ + return vmulxd_f64 (__a, __aarch64_vget_lane_any (__v, __lane)); +} + +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulxd_laneq_f64 (float64_t __a, float64x2_t __v, const int __lane) +{ + return vmulxd_f64 (__a, __aarch64_vget_lane_any (__v, __lane)); +} + +/* vpmax */ + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmax_s8 (int8x8_t a, int8x8_t b) +{ + return __builtin_aarch64_smaxpv8qi (a, b); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmax_s16 (int16x4_t a, int16x4_t b) +{ + return __builtin_aarch64_smaxpv4hi (a, b); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmax_s32 (int32x2_t a, int32x2_t b) +{ + return __builtin_aarch64_smaxpv2si (a, b); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmax_u8 (uint8x8_t a, uint8x8_t b) +{ + return (uint8x8_t) __builtin_aarch64_umaxpv8qi ((int8x8_t) a, + (int8x8_t) b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmax_u16 (uint16x4_t a, uint16x4_t b) +{ + return (uint16x4_t) __builtin_aarch64_umaxpv4hi ((int16x4_t) a, + (int16x4_t) b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmax_u32 (uint32x2_t a, uint32x2_t b) +{ + return (uint32x2_t) __builtin_aarch64_umaxpv2si ((int32x2_t) a, + (int32x2_t) b); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmaxq_s8 (int8x16_t a, int8x16_t b) +{ + return __builtin_aarch64_smaxpv16qi (a, b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmaxq_s16 (int16x8_t a, int16x8_t b) +{ + return __builtin_aarch64_smaxpv8hi (a, b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmaxq_s32 (int32x4_t a, int32x4_t b) +{ + return __builtin_aarch64_smaxpv4si (a, b); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmaxq_u8 (uint8x16_t a, uint8x16_t b) +{ + return (uint8x16_t) __builtin_aarch64_umaxpv16qi ((int8x16_t) a, + (int8x16_t) b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmaxq_u16 (uint16x8_t a, uint16x8_t b) +{ + return (uint16x8_t) __builtin_aarch64_umaxpv8hi ((int16x8_t) a, + (int16x8_t) b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmaxq_u32 (uint32x4_t a, uint32x4_t b) +{ + return (uint32x4_t) __builtin_aarch64_umaxpv4si ((int32x4_t) a, + (int32x4_t) b); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmax_f32 (float32x2_t a, float32x2_t b) +{ + return __builtin_aarch64_smax_nanpv2sf (a, b); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmaxq_f32 (float32x4_t a, float32x4_t b) +{ + return __builtin_aarch64_smax_nanpv4sf (a, b); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmaxq_f64 (float64x2_t a, float64x2_t b) +{ + return __builtin_aarch64_smax_nanpv2df (a, b); +} + +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmaxqd_f64 (float64x2_t a) +{ + return __builtin_aarch64_reduc_smax_nan_scal_v2df (a); +} + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmaxs_f32 (float32x2_t a) +{ + return __builtin_aarch64_reduc_smax_nan_scal_v2sf (a); +} + +/* vpmaxnm */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmaxnm_f32 (float32x2_t a, float32x2_t b) +{ + return __builtin_aarch64_smaxpv2sf (a, b); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmaxnmq_f32 (float32x4_t a, float32x4_t b) +{ + return __builtin_aarch64_smaxpv4sf (a, b); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmaxnmq_f64 (float64x2_t a, float64x2_t b) +{ + return __builtin_aarch64_smaxpv2df (a, b); +} + +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmaxnmqd_f64 (float64x2_t a) +{ + return __builtin_aarch64_reduc_smax_scal_v2df (a); +} + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmaxnms_f32 (float32x2_t a) +{ + return __builtin_aarch64_reduc_smax_scal_v2sf (a); +} + +/* vpmin */ + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmin_s8 (int8x8_t a, int8x8_t b) +{ + return __builtin_aarch64_sminpv8qi (a, b); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmin_s16 (int16x4_t a, int16x4_t b) +{ + return __builtin_aarch64_sminpv4hi (a, b); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmin_s32 (int32x2_t a, int32x2_t b) +{ + return __builtin_aarch64_sminpv2si (a, b); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmin_u8 (uint8x8_t a, uint8x8_t b) +{ + return (uint8x8_t) __builtin_aarch64_uminpv8qi ((int8x8_t) a, + (int8x8_t) b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmin_u16 (uint16x4_t a, uint16x4_t b) +{ + return (uint16x4_t) __builtin_aarch64_uminpv4hi ((int16x4_t) a, + (int16x4_t) b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmin_u32 (uint32x2_t a, uint32x2_t b) +{ + return (uint32x2_t) __builtin_aarch64_uminpv2si ((int32x2_t) a, + (int32x2_t) b); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpminq_s8 (int8x16_t a, int8x16_t b) +{ + return __builtin_aarch64_sminpv16qi (a, b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpminq_s16 (int16x8_t a, int16x8_t b) +{ + return __builtin_aarch64_sminpv8hi (a, b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpminq_s32 (int32x4_t a, int32x4_t b) +{ + return __builtin_aarch64_sminpv4si (a, b); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpminq_u8 (uint8x16_t a, uint8x16_t b) +{ + return (uint8x16_t) __builtin_aarch64_uminpv16qi ((int8x16_t) a, + (int8x16_t) b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpminq_u16 (uint16x8_t a, uint16x8_t b) +{ + return (uint16x8_t) __builtin_aarch64_uminpv8hi ((int16x8_t) a, + (int16x8_t) b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpminq_u32 (uint32x4_t a, uint32x4_t b) +{ + return (uint32x4_t) __builtin_aarch64_uminpv4si ((int32x4_t) a, + (int32x4_t) b); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmin_f32 (float32x2_t a, float32x2_t b) +{ + return __builtin_aarch64_smin_nanpv2sf (a, b); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpminq_f32 (float32x4_t a, float32x4_t b) +{ + return __builtin_aarch64_smin_nanpv4sf (a, b); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpminq_f64 (float64x2_t a, float64x2_t b) +{ + return __builtin_aarch64_smin_nanpv2df (a, b); +} + +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpminqd_f64 (float64x2_t a) +{ + return __builtin_aarch64_reduc_smin_nan_scal_v2df (a); +} + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmins_f32 (float32x2_t a) +{ + return __builtin_aarch64_reduc_smin_nan_scal_v2sf (a); +} + +/* vpminnm */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpminnm_f32 (float32x2_t a, float32x2_t b) +{ + return __builtin_aarch64_sminpv2sf (a, b); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpminnmq_f32 (float32x4_t a, float32x4_t b) +{ + return __builtin_aarch64_sminpv4sf (a, b); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpminnmq_f64 (float64x2_t a, float64x2_t b) +{ + return __builtin_aarch64_sminpv2df (a, b); +} + +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpminnmqd_f64 (float64x2_t a) +{ + return __builtin_aarch64_reduc_smin_scal_v2df (a); +} + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpminnms_f32 (float32x2_t a) +{ + return __builtin_aarch64_reduc_smin_scal_v2sf (a); +} + +/* vmaxnm */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxnm_f32 (float32x2_t __a, float32x2_t __b) +{ + return __builtin_aarch64_fmaxv2sf (__a, __b); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxnm_f64 (float64x1_t __a, float64x1_t __b) +{ + return (float64x1_t) + { __builtin_aarch64_fmaxdf (vget_lane_f64 (__a, 0), + vget_lane_f64 (__b, 0)) }; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxnmq_f32 (float32x4_t __a, float32x4_t __b) +{ + return __builtin_aarch64_fmaxv4sf (__a, __b); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxnmq_f64 (float64x2_t __a, float64x2_t __b) +{ + return __builtin_aarch64_fmaxv2df (__a, __b); +} + +/* vmaxv */ + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxv_f32 (float32x2_t __a) +{ + return __builtin_aarch64_reduc_smax_nan_scal_v2sf (__a); +} + +__extension__ extern __inline int8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxv_s8 (int8x8_t __a) +{ + return __builtin_aarch64_reduc_smax_scal_v8qi (__a); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxv_s16 (int16x4_t __a) +{ + return __builtin_aarch64_reduc_smax_scal_v4hi (__a); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxv_s32 (int32x2_t __a) +{ + return __builtin_aarch64_reduc_smax_scal_v2si (__a); +} + +__extension__ extern __inline uint8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxv_u8 (uint8x8_t __a) +{ + return __builtin_aarch64_reduc_umax_scal_v8qi_uu (__a); +} + +__extension__ extern __inline uint16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxv_u16 (uint16x4_t __a) +{ + return __builtin_aarch64_reduc_umax_scal_v4hi_uu (__a); +} + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxv_u32 (uint32x2_t __a) +{ + return __builtin_aarch64_reduc_umax_scal_v2si_uu (__a); +} + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxvq_f32 (float32x4_t __a) +{ + return __builtin_aarch64_reduc_smax_nan_scal_v4sf (__a); +} + +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxvq_f64 (float64x2_t __a) +{ + return __builtin_aarch64_reduc_smax_nan_scal_v2df (__a); +} + +__extension__ extern __inline int8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxvq_s8 (int8x16_t __a) +{ + return __builtin_aarch64_reduc_smax_scal_v16qi (__a); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxvq_s16 (int16x8_t __a) +{ + return __builtin_aarch64_reduc_smax_scal_v8hi (__a); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxvq_s32 (int32x4_t __a) +{ + return __builtin_aarch64_reduc_smax_scal_v4si (__a); +} + +__extension__ extern __inline uint8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxvq_u8 (uint8x16_t __a) +{ + return __builtin_aarch64_reduc_umax_scal_v16qi_uu (__a); +} + +__extension__ extern __inline uint16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxvq_u16 (uint16x8_t __a) +{ + return __builtin_aarch64_reduc_umax_scal_v8hi_uu (__a); +} + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxvq_u32 (uint32x4_t __a) +{ + return __builtin_aarch64_reduc_umax_scal_v4si_uu (__a); +} + +/* vmaxnmv */ + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxnmv_f32 (float32x2_t __a) +{ + return __builtin_aarch64_reduc_smax_scal_v2sf (__a); +} + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxnmvq_f32 (float32x4_t __a) +{ + return __builtin_aarch64_reduc_smax_scal_v4sf (__a); +} + +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxnmvq_f64 (float64x2_t __a) +{ + return __builtin_aarch64_reduc_smax_scal_v2df (__a); +} + +/* vmin */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmin_f32 (float32x2_t __a, float32x2_t __b) +{ + return __builtin_aarch64_smin_nanv2sf (__a, __b); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmin_f64 (float64x1_t __a, float64x1_t __b) +{ + return (float64x1_t) + { __builtin_aarch64_smin_nandf (vget_lane_f64 (__a, 0), + vget_lane_f64 (__b, 0)) }; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmin_s8 (int8x8_t __a, int8x8_t __b) +{ + return __builtin_aarch64_sminv8qi (__a, __b); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmin_s16 (int16x4_t __a, int16x4_t __b) +{ + return __builtin_aarch64_sminv4hi (__a, __b); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmin_s32 (int32x2_t __a, int32x2_t __b) +{ + return __builtin_aarch64_sminv2si (__a, __b); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmin_u8 (uint8x8_t __a, uint8x8_t __b) +{ + return (uint8x8_t) __builtin_aarch64_uminv8qi ((int8x8_t) __a, + (int8x8_t) __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmin_u16 (uint16x4_t __a, uint16x4_t __b) +{ + return (uint16x4_t) __builtin_aarch64_uminv4hi ((int16x4_t) __a, + (int16x4_t) __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmin_u32 (uint32x2_t __a, uint32x2_t __b) +{ + return (uint32x2_t) __builtin_aarch64_uminv2si ((int32x2_t) __a, + (int32x2_t) __b); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminq_f32 (float32x4_t __a, float32x4_t __b) +{ + return __builtin_aarch64_smin_nanv4sf (__a, __b); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminq_f64 (float64x2_t __a, float64x2_t __b) +{ + return __builtin_aarch64_smin_nanv2df (__a, __b); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminq_s8 (int8x16_t __a, int8x16_t __b) +{ + return __builtin_aarch64_sminv16qi (__a, __b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminq_s16 (int16x8_t __a, int16x8_t __b) +{ + return __builtin_aarch64_sminv8hi (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminq_s32 (int32x4_t __a, int32x4_t __b) +{ + return __builtin_aarch64_sminv4si (__a, __b); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminq_u8 (uint8x16_t __a, uint8x16_t __b) +{ + return (uint8x16_t) __builtin_aarch64_uminv16qi ((int8x16_t) __a, + (int8x16_t) __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminq_u16 (uint16x8_t __a, uint16x8_t __b) +{ + return (uint16x8_t) __builtin_aarch64_uminv8hi ((int16x8_t) __a, + (int16x8_t) __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminq_u32 (uint32x4_t __a, uint32x4_t __b) +{ + return (uint32x4_t) __builtin_aarch64_uminv4si ((int32x4_t) __a, + (int32x4_t) __b); +} + +/* vminnm */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminnm_f32 (float32x2_t __a, float32x2_t __b) +{ + return __builtin_aarch64_fminv2sf (__a, __b); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminnm_f64 (float64x1_t __a, float64x1_t __b) +{ + return (float64x1_t) + { __builtin_aarch64_fmindf (vget_lane_f64 (__a, 0), + vget_lane_f64 (__b, 0)) }; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminnmq_f32 (float32x4_t __a, float32x4_t __b) +{ + return __builtin_aarch64_fminv4sf (__a, __b); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminnmq_f64 (float64x2_t __a, float64x2_t __b) +{ + return __builtin_aarch64_fminv2df (__a, __b); +} + +/* vminv */ + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminv_f32 (float32x2_t __a) +{ + return __builtin_aarch64_reduc_smin_nan_scal_v2sf (__a); +} + +__extension__ extern __inline int8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminv_s8 (int8x8_t __a) +{ + return __builtin_aarch64_reduc_smin_scal_v8qi (__a); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminv_s16 (int16x4_t __a) +{ + return __builtin_aarch64_reduc_smin_scal_v4hi (__a); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminv_s32 (int32x2_t __a) +{ + return __builtin_aarch64_reduc_smin_scal_v2si (__a); +} + +__extension__ extern __inline uint8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminv_u8 (uint8x8_t __a) +{ + return __builtin_aarch64_reduc_umin_scal_v8qi_uu (__a); +} + +__extension__ extern __inline uint16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminv_u16 (uint16x4_t __a) +{ + return __builtin_aarch64_reduc_umin_scal_v4hi_uu (__a); +} + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminv_u32 (uint32x2_t __a) +{ + return __builtin_aarch64_reduc_umin_scal_v2si_uu (__a); +} + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminvq_f32 (float32x4_t __a) +{ + return __builtin_aarch64_reduc_smin_nan_scal_v4sf (__a); +} + +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminvq_f64 (float64x2_t __a) +{ + return __builtin_aarch64_reduc_smin_nan_scal_v2df (__a); +} + +__extension__ extern __inline int8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminvq_s8 (int8x16_t __a) +{ + return __builtin_aarch64_reduc_smin_scal_v16qi (__a); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminvq_s16 (int16x8_t __a) +{ + return __builtin_aarch64_reduc_smin_scal_v8hi (__a); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminvq_s32 (int32x4_t __a) +{ + return __builtin_aarch64_reduc_smin_scal_v4si (__a); +} + +__extension__ extern __inline uint8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminvq_u8 (uint8x16_t __a) +{ + return __builtin_aarch64_reduc_umin_scal_v16qi_uu (__a); +} + +__extension__ extern __inline uint16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminvq_u16 (uint16x8_t __a) +{ + return __builtin_aarch64_reduc_umin_scal_v8hi_uu (__a); +} + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminvq_u32 (uint32x4_t __a) +{ + return __builtin_aarch64_reduc_umin_scal_v4si_uu (__a); +} + +/* vminnmv */ + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminnmv_f32 (float32x2_t __a) +{ + return __builtin_aarch64_reduc_smin_scal_v2sf (__a); +} + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminnmvq_f32 (float32x4_t __a) +{ + return __builtin_aarch64_reduc_smin_scal_v4sf (__a); +} + +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminnmvq_f64 (float64x2_t __a) +{ + return __builtin_aarch64_reduc_smin_scal_v2df (__a); +} + +/* vmla */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmla_f32 (float32x2_t a, float32x2_t b, float32x2_t c) +{ + return a + b * c; +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmla_f64 (float64x1_t __a, float64x1_t __b, float64x1_t __c) +{ + return __a + __b * __c; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlaq_f32 (float32x4_t a, float32x4_t b, float32x4_t c) +{ + return a + b * c; +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlaq_f64 (float64x2_t a, float64x2_t b, float64x2_t c) +{ + return a + b * c; +} + +/* vmla_lane */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmla_lane_f32 (float32x2_t __a, float32x2_t __b, + float32x2_t __c, const int __lane) +{ + return (__a + (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmla_lane_s16 (int16x4_t __a, int16x4_t __b, + int16x4_t __c, const int __lane) +{ + return (__a + (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmla_lane_s32 (int32x2_t __a, int32x2_t __b, + int32x2_t __c, const int __lane) +{ + return (__a + (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmla_lane_u16 (uint16x4_t __a, uint16x4_t __b, + uint16x4_t __c, const int __lane) +{ + return (__a + (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmla_lane_u32 (uint32x2_t __a, uint32x2_t __b, + uint32x2_t __c, const int __lane) +{ + return (__a + (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +/* vmla_laneq */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmla_laneq_f32 (float32x2_t __a, float32x2_t __b, + float32x4_t __c, const int __lane) +{ + return (__a + (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmla_laneq_s16 (int16x4_t __a, int16x4_t __b, + int16x8_t __c, const int __lane) +{ + return (__a + (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmla_laneq_s32 (int32x2_t __a, int32x2_t __b, + int32x4_t __c, const int __lane) +{ + return (__a + (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmla_laneq_u16 (uint16x4_t __a, uint16x4_t __b, + uint16x8_t __c, const int __lane) +{ + return (__a + (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmla_laneq_u32 (uint32x2_t __a, uint32x2_t __b, + uint32x4_t __c, const int __lane) +{ + return (__a + (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +/* vmlaq_lane */ + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlaq_lane_f32 (float32x4_t __a, float32x4_t __b, + float32x2_t __c, const int __lane) +{ + return (__a + (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlaq_lane_s16 (int16x8_t __a, int16x8_t __b, + int16x4_t __c, const int __lane) +{ + return (__a + (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlaq_lane_s32 (int32x4_t __a, int32x4_t __b, + int32x2_t __c, const int __lane) +{ + return (__a + (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlaq_lane_u16 (uint16x8_t __a, uint16x8_t __b, + uint16x4_t __c, const int __lane) +{ + return (__a + (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlaq_lane_u32 (uint32x4_t __a, uint32x4_t __b, + uint32x2_t __c, const int __lane) +{ + return (__a + (__b * __aarch64_vget_lane_any (__c, __lane))); +} + + /* vmlaq_laneq */ + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlaq_laneq_f32 (float32x4_t __a, float32x4_t __b, + float32x4_t __c, const int __lane) +{ + return (__a + (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlaq_laneq_s16 (int16x8_t __a, int16x8_t __b, + int16x8_t __c, const int __lane) +{ + return (__a + (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlaq_laneq_s32 (int32x4_t __a, int32x4_t __b, + int32x4_t __c, const int __lane) +{ + return (__a + (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlaq_laneq_u16 (uint16x8_t __a, uint16x8_t __b, + uint16x8_t __c, const int __lane) +{ + return (__a + (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlaq_laneq_u32 (uint32x4_t __a, uint32x4_t __b, + uint32x4_t __c, const int __lane) +{ + return (__a + (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +/* vmls */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmls_f32 (float32x2_t a, float32x2_t b, float32x2_t c) +{ + return a - b * c; +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmls_f64 (float64x1_t __a, float64x1_t __b, float64x1_t __c) +{ + return __a - __b * __c; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsq_f32 (float32x4_t a, float32x4_t b, float32x4_t c) +{ + return a - b * c; +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsq_f64 (float64x2_t a, float64x2_t b, float64x2_t c) +{ + return a - b * c; +} + +/* vmls_lane */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmls_lane_f32 (float32x2_t __a, float32x2_t __b, + float32x2_t __c, const int __lane) +{ + return (__a - (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmls_lane_s16 (int16x4_t __a, int16x4_t __b, + int16x4_t __c, const int __lane) +{ + return (__a - (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmls_lane_s32 (int32x2_t __a, int32x2_t __b, + int32x2_t __c, const int __lane) +{ + return (__a - (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmls_lane_u16 (uint16x4_t __a, uint16x4_t __b, + uint16x4_t __c, const int __lane) +{ + return (__a - (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmls_lane_u32 (uint32x2_t __a, uint32x2_t __b, + uint32x2_t __c, const int __lane) +{ + return (__a - (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +/* vmls_laneq */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmls_laneq_f32 (float32x2_t __a, float32x2_t __b, + float32x4_t __c, const int __lane) +{ + return (__a - (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmls_laneq_s16 (int16x4_t __a, int16x4_t __b, + int16x8_t __c, const int __lane) +{ + return (__a - (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmls_laneq_s32 (int32x2_t __a, int32x2_t __b, + int32x4_t __c, const int __lane) +{ + return (__a - (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmls_laneq_u16 (uint16x4_t __a, uint16x4_t __b, + uint16x8_t __c, const int __lane) +{ + return (__a - (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmls_laneq_u32 (uint32x2_t __a, uint32x2_t __b, + uint32x4_t __c, const int __lane) +{ + return (__a - (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +/* vmlsq_lane */ + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsq_lane_f32 (float32x4_t __a, float32x4_t __b, + float32x2_t __c, const int __lane) +{ + return (__a - (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsq_lane_s16 (int16x8_t __a, int16x8_t __b, + int16x4_t __c, const int __lane) +{ + return (__a - (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsq_lane_s32 (int32x4_t __a, int32x4_t __b, + int32x2_t __c, const int __lane) +{ + return (__a - (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsq_lane_u16 (uint16x8_t __a, uint16x8_t __b, + uint16x4_t __c, const int __lane) +{ + return (__a - (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsq_lane_u32 (uint32x4_t __a, uint32x4_t __b, + uint32x2_t __c, const int __lane) +{ + return (__a - (__b * __aarch64_vget_lane_any (__c, __lane))); +} + + /* vmlsq_laneq */ + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsq_laneq_f32 (float32x4_t __a, float32x4_t __b, + float32x4_t __c, const int __lane) +{ + return (__a - (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsq_laneq_s16 (int16x8_t __a, int16x8_t __b, + int16x8_t __c, const int __lane) +{ + return (__a - (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsq_laneq_s32 (int32x4_t __a, int32x4_t __b, + int32x4_t __c, const int __lane) +{ + return (__a - (__b * __aarch64_vget_lane_any (__c, __lane))); +} +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsq_laneq_u16 (uint16x8_t __a, uint16x8_t __b, + uint16x8_t __c, const int __lane) +{ + return (__a - (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmlsq_laneq_u32 (uint32x4_t __a, uint32x4_t __b, + uint32x4_t __c, const int __lane) +{ + return (__a - (__b * __aarch64_vget_lane_any (__c, __lane))); +} + +/* vmov_n_ */ + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmov_n_f16 (float16_t __a) +{ + return vdup_n_f16 (__a); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmov_n_f32 (float32_t __a) +{ + return vdup_n_f32 (__a); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmov_n_f64 (float64_t __a) +{ + return (float64x1_t) {__a}; +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmov_n_p8 (poly8_t __a) +{ + return vdup_n_p8 (__a); +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmov_n_p16 (poly16_t __a) +{ + return vdup_n_p16 (__a); +} + +__extension__ extern __inline poly64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmov_n_p64 (poly64_t __a) +{ + return vdup_n_p64 (__a); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmov_n_s8 (int8_t __a) +{ + return vdup_n_s8 (__a); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmov_n_s16 (int16_t __a) +{ + return vdup_n_s16 (__a); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmov_n_s32 (int32_t __a) +{ + return vdup_n_s32 (__a); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmov_n_s64 (int64_t __a) +{ + return (int64x1_t) {__a}; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmov_n_u8 (uint8_t __a) +{ + return vdup_n_u8 (__a); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmov_n_u16 (uint16_t __a) +{ + return vdup_n_u16 (__a); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmov_n_u32 (uint32_t __a) +{ + return vdup_n_u32 (__a); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmov_n_u64 (uint64_t __a) +{ + return (uint64x1_t) {__a}; +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovq_n_f16 (float16_t __a) +{ + return vdupq_n_f16 (__a); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovq_n_f32 (float32_t __a) +{ + return vdupq_n_f32 (__a); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovq_n_f64 (float64_t __a) +{ + return vdupq_n_f64 (__a); +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovq_n_p8 (poly8_t __a) +{ + return vdupq_n_p8 (__a); +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovq_n_p16 (poly16_t __a) +{ + return vdupq_n_p16 (__a); +} + +__extension__ extern __inline poly64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovq_n_p64 (poly64_t __a) +{ + return vdupq_n_p64 (__a); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovq_n_s8 (int8_t __a) +{ + return vdupq_n_s8 (__a); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovq_n_s16 (int16_t __a) +{ + return vdupq_n_s16 (__a); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovq_n_s32 (int32_t __a) +{ + return vdupq_n_s32 (__a); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovq_n_s64 (int64_t __a) +{ + return vdupq_n_s64 (__a); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovq_n_u8 (uint8_t __a) +{ + return vdupq_n_u8 (__a); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovq_n_u16 (uint16_t __a) +{ + return vdupq_n_u16 (__a); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovq_n_u32 (uint32_t __a) +{ + return vdupq_n_u32 (__a); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmovq_n_u64 (uint64_t __a) +{ + return vdupq_n_u64 (__a); +} + +/* vmul_lane */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmul_lane_f32 (float32x2_t __a, float32x2_t __b, const int __lane) +{ + return __a * __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmul_lane_f64 (float64x1_t __a, float64x1_t __b, const int __lane) +{ + return __a * __b; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmul_lane_s16 (int16x4_t __a, int16x4_t __b, const int __lane) +{ + return __a * __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmul_lane_s32 (int32x2_t __a, int32x2_t __b, const int __lane) +{ + return __a * __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmul_lane_u16 (uint16x4_t __a, uint16x4_t __b, const int __lane) +{ + return __a * __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmul_lane_u32 (uint32x2_t __a, uint32x2_t __b, const int __lane) +{ + return __a * __aarch64_vget_lane_any (__b, __lane); +} + +/* vmuld_lane */ + +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmuld_lane_f64 (float64_t __a, float64x1_t __b, const int __lane) +{ + return __a * __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmuld_laneq_f64 (float64_t __a, float64x2_t __b, const int __lane) +{ + return __a * __aarch64_vget_lane_any (__b, __lane); +} + +/* vmuls_lane */ + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmuls_lane_f32 (float32_t __a, float32x2_t __b, const int __lane) +{ + return __a * __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmuls_laneq_f32 (float32_t __a, float32x4_t __b, const int __lane) +{ + return __a * __aarch64_vget_lane_any (__b, __lane); +} + +/* vmul_laneq */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmul_laneq_f32 (float32x2_t __a, float32x4_t __b, const int __lane) +{ + return __a * __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmul_laneq_f64 (float64x1_t __a, float64x2_t __b, const int __lane) +{ + return __a * __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmul_laneq_s16 (int16x4_t __a, int16x8_t __b, const int __lane) +{ + return __a * __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmul_laneq_s32 (int32x2_t __a, int32x4_t __b, const int __lane) +{ + return __a * __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmul_laneq_u16 (uint16x4_t __a, uint16x8_t __b, const int __lane) +{ + return __a * __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmul_laneq_u32 (uint32x2_t __a, uint32x4_t __b, const int __lane) +{ + return __a * __aarch64_vget_lane_any (__b, __lane); +} + +/* vmul_n */ + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmul_n_f64 (float64x1_t __a, float64_t __b) +{ + return (float64x1_t) { vget_lane_f64 (__a, 0) * __b }; +} + +/* vmulq_lane */ + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulq_lane_f32 (float32x4_t __a, float32x2_t __b, const int __lane) +{ + return __a * __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulq_lane_f64 (float64x2_t __a, float64x1_t __b, const int __lane) +{ + __AARCH64_LANE_CHECK (__a, __lane); + return __a * __b[0]; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulq_lane_s16 (int16x8_t __a, int16x4_t __b, const int __lane) +{ + return __a * __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulq_lane_s32 (int32x4_t __a, int32x2_t __b, const int __lane) +{ + return __a * __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulq_lane_u16 (uint16x8_t __a, uint16x4_t __b, const int __lane) +{ + return __a * __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulq_lane_u32 (uint32x4_t __a, uint32x2_t __b, const int __lane) +{ + return __a * __aarch64_vget_lane_any (__b, __lane); +} + +/* vmulq_laneq */ + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulq_laneq_f32 (float32x4_t __a, float32x4_t __b, const int __lane) +{ + return __a * __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulq_laneq_f64 (float64x2_t __a, float64x2_t __b, const int __lane) +{ + return __a * __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulq_laneq_s16 (int16x8_t __a, int16x8_t __b, const int __lane) +{ + return __a * __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulq_laneq_s32 (int32x4_t __a, int32x4_t __b, const int __lane) +{ + return __a * __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulq_laneq_u16 (uint16x8_t __a, uint16x8_t __b, const int __lane) +{ + return __a * __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulq_laneq_u32 (uint32x4_t __a, uint32x4_t __b, const int __lane) +{ + return __a * __aarch64_vget_lane_any (__b, __lane); +} + +/* vmul_n. */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmul_n_f32 (float32x2_t __a, float32_t __b) +{ + return __a * __b; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulq_n_f32 (float32x4_t __a, float32_t __b) +{ + return __a * __b; +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulq_n_f64 (float64x2_t __a, float64_t __b) +{ + return __a * __b; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmul_n_s16 (int16x4_t __a, int16_t __b) +{ + return __a * __b; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulq_n_s16 (int16x8_t __a, int16_t __b) +{ + return __a * __b; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmul_n_s32 (int32x2_t __a, int32_t __b) +{ + return __a * __b; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulq_n_s32 (int32x4_t __a, int32_t __b) +{ + return __a * __b; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmul_n_u16 (uint16x4_t __a, uint16_t __b) +{ + return __a * __b; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulq_n_u16 (uint16x8_t __a, uint16_t __b) +{ + return __a * __b; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmul_n_u32 (uint32x2_t __a, uint32_t __b) +{ + return __a * __b; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulq_n_u32 (uint32x4_t __a, uint32_t __b) +{ + return __a * __b; +} + +/* vmvn */ + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmvn_p8 (poly8x8_t __a) +{ + return (poly8x8_t) ~((int8x8_t) __a); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmvn_s8 (int8x8_t __a) +{ + return ~__a; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmvn_s16 (int16x4_t __a) +{ + return ~__a; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmvn_s32 (int32x2_t __a) +{ + return ~__a; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmvn_u8 (uint8x8_t __a) +{ + return ~__a; +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmvn_u16 (uint16x4_t __a) +{ + return ~__a; +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmvn_u32 (uint32x2_t __a) +{ + return ~__a; +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmvnq_p8 (poly8x16_t __a) +{ + return (poly8x16_t) ~((int8x16_t) __a); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmvnq_s8 (int8x16_t __a) +{ + return ~__a; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmvnq_s16 (int16x8_t __a) +{ + return ~__a; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmvnq_s32 (int32x4_t __a) +{ + return ~__a; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmvnq_u8 (uint8x16_t __a) +{ + return ~__a; +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmvnq_u16 (uint16x8_t __a) +{ + return ~__a; +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmvnq_u32 (uint32x4_t __a) +{ + return ~__a; +} + +/* vneg */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vneg_f32 (float32x2_t __a) +{ + return -__a; +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vneg_f64 (float64x1_t __a) +{ + return -__a; +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vneg_s8 (int8x8_t __a) +{ + return -__a; +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vneg_s16 (int16x4_t __a) +{ + return -__a; +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vneg_s32 (int32x2_t __a) +{ + return -__a; +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vneg_s64 (int64x1_t __a) +{ + return -__a; +} + +/* According to the ACLE, the negative of the minimum (signed) + value is itself. This leads to a semantics mismatch, as this is + undefined behaviour in C. The value range predictor is not + aware that the negation of a negative number can still be negative + and it may try to fold the expression. See the test in + gcc.target/aarch64/vnegd_s64.c for an example. + + The cast below tricks the value range predictor to include + INT64_MIN in the range it computes. So for x in the range + [INT64_MIN, y] the range prediction after vnegd_s64 (x) will + be ~[INT64_MIN + 1, y]. */ + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vnegd_s64 (int64_t __a) +{ + return - (uint64_t) __a; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vnegq_f32 (float32x4_t __a) +{ + return -__a; +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vnegq_f64 (float64x2_t __a) +{ + return -__a; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vnegq_s8 (int8x16_t __a) +{ + return -__a; +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vnegq_s16 (int16x8_t __a) +{ + return -__a; +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vnegq_s32 (int32x4_t __a) +{ + return -__a; +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vnegq_s64 (int64x2_t __a) +{ + return -__a; +} + +/* vpadd */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpadd_f32 (float32x2_t __a, float32x2_t __b) +{ + return __builtin_aarch64_faddpv2sf (__a, __b); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpaddq_f32 (float32x4_t __a, float32x4_t __b) +{ + return __builtin_aarch64_faddpv4sf (__a, __b); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpaddq_f64 (float64x2_t __a, float64x2_t __b) +{ + return __builtin_aarch64_faddpv2df (__a, __b); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpadd_s8 (int8x8_t __a, int8x8_t __b) +{ + return __builtin_aarch64_addpv8qi (__a, __b); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpadd_s16 (int16x4_t __a, int16x4_t __b) +{ + return __builtin_aarch64_addpv4hi (__a, __b); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpadd_s32 (int32x2_t __a, int32x2_t __b) +{ + return __builtin_aarch64_addpv2si (__a, __b); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpadd_u8 (uint8x8_t __a, uint8x8_t __b) +{ + return (uint8x8_t) __builtin_aarch64_addpv8qi ((int8x8_t) __a, + (int8x8_t) __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpadd_u16 (uint16x4_t __a, uint16x4_t __b) +{ + return (uint16x4_t) __builtin_aarch64_addpv4hi ((int16x4_t) __a, + (int16x4_t) __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpadd_u32 (uint32x2_t __a, uint32x2_t __b) +{ + return (uint32x2_t) __builtin_aarch64_addpv2si ((int32x2_t) __a, + (int32x2_t) __b); +} + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpadds_f32 (float32x2_t __a) +{ + return __builtin_aarch64_reduc_plus_scal_v2sf (__a); +} + +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpaddd_f64 (float64x2_t __a) +{ + return __builtin_aarch64_reduc_plus_scal_v2df (__a); +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpaddd_s64 (int64x2_t __a) +{ + return __builtin_aarch64_addpdi (__a); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpaddd_u64 (uint64x2_t __a) +{ + return __builtin_aarch64_addpdi ((int64x2_t) __a); +} + +/* vqabs */ + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqabsq_s64 (int64x2_t __a) +{ + return (int64x2_t) __builtin_aarch64_sqabsv2di (__a); +} + +__extension__ extern __inline int8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqabsb_s8 (int8_t __a) +{ + return (int8_t) __builtin_aarch64_sqabsqi (__a); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqabsh_s16 (int16_t __a) +{ + return (int16_t) __builtin_aarch64_sqabshi (__a); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqabss_s32 (int32_t __a) +{ + return (int32_t) __builtin_aarch64_sqabssi (__a); +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqabsd_s64 (int64_t __a) +{ + return __builtin_aarch64_sqabsdi (__a); +} + +/* vqadd */ + +__extension__ extern __inline int8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqaddb_s8 (int8_t __a, int8_t __b) +{ + return (int8_t) __builtin_aarch64_sqaddqi (__a, __b); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqaddh_s16 (int16_t __a, int16_t __b) +{ + return (int16_t) __builtin_aarch64_sqaddhi (__a, __b); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqadds_s32 (int32_t __a, int32_t __b) +{ + return (int32_t) __builtin_aarch64_sqaddsi (__a, __b); +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqaddd_s64 (int64_t __a, int64_t __b) +{ + return __builtin_aarch64_sqadddi (__a, __b); +} + +__extension__ extern __inline uint8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqaddb_u8 (uint8_t __a, uint8_t __b) +{ + return (uint8_t) __builtin_aarch64_uqaddqi_uuu (__a, __b); +} + +__extension__ extern __inline uint16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqaddh_u16 (uint16_t __a, uint16_t __b) +{ + return (uint16_t) __builtin_aarch64_uqaddhi_uuu (__a, __b); +} + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqadds_u32 (uint32_t __a, uint32_t __b) +{ + return (uint32_t) __builtin_aarch64_uqaddsi_uuu (__a, __b); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqaddd_u64 (uint64_t __a, uint64_t __b) +{ + return __builtin_aarch64_uqadddi_uuu (__a, __b); +} + +/* vqdmlal */ + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlal_s16 (int32x4_t __a, int16x4_t __b, int16x4_t __c) +{ + return __builtin_aarch64_sqdmlalv4hi (__a, __b, __c); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlal_high_s16 (int32x4_t __a, int16x8_t __b, int16x8_t __c) +{ + return __builtin_aarch64_sqdmlal2v8hi (__a, __b, __c); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlal_high_lane_s16 (int32x4_t __a, int16x8_t __b, int16x4_t __c, + int const __d) +{ + return __builtin_aarch64_sqdmlal2_lanev8hi (__a, __b, __c, __d); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlal_high_laneq_s16 (int32x4_t __a, int16x8_t __b, int16x8_t __c, + int const __d) +{ + return __builtin_aarch64_sqdmlal2_laneqv8hi (__a, __b, __c, __d); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlal_high_n_s16 (int32x4_t __a, int16x8_t __b, int16_t __c) +{ + return __builtin_aarch64_sqdmlal2_nv8hi (__a, __b, __c); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlal_lane_s16 (int32x4_t __a, int16x4_t __b, int16x4_t __c, int const __d) +{ + return __builtin_aarch64_sqdmlal_lanev4hi (__a, __b, __c, __d); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlal_laneq_s16 (int32x4_t __a, int16x4_t __b, int16x8_t __c, int const __d) +{ + return __builtin_aarch64_sqdmlal_laneqv4hi (__a, __b, __c, __d); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlal_n_s16 (int32x4_t __a, int16x4_t __b, int16_t __c) +{ + return __builtin_aarch64_sqdmlal_nv4hi (__a, __b, __c); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlal_s32 (int64x2_t __a, int32x2_t __b, int32x2_t __c) +{ + return __builtin_aarch64_sqdmlalv2si (__a, __b, __c); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlal_high_s32 (int64x2_t __a, int32x4_t __b, int32x4_t __c) +{ + return __builtin_aarch64_sqdmlal2v4si (__a, __b, __c); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlal_high_lane_s32 (int64x2_t __a, int32x4_t __b, int32x2_t __c, + int const __d) +{ + return __builtin_aarch64_sqdmlal2_lanev4si (__a, __b, __c, __d); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlal_high_laneq_s32 (int64x2_t __a, int32x4_t __b, int32x4_t __c, + int const __d) +{ + return __builtin_aarch64_sqdmlal2_laneqv4si (__a, __b, __c, __d); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlal_high_n_s32 (int64x2_t __a, int32x4_t __b, int32_t __c) +{ + return __builtin_aarch64_sqdmlal2_nv4si (__a, __b, __c); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlal_lane_s32 (int64x2_t __a, int32x2_t __b, int32x2_t __c, int const __d) +{ + return __builtin_aarch64_sqdmlal_lanev2si (__a, __b, __c, __d); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlal_laneq_s32 (int64x2_t __a, int32x2_t __b, int32x4_t __c, int const __d) +{ + return __builtin_aarch64_sqdmlal_laneqv2si (__a, __b, __c, __d); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlal_n_s32 (int64x2_t __a, int32x2_t __b, int32_t __c) +{ + return __builtin_aarch64_sqdmlal_nv2si (__a, __b, __c); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlalh_s16 (int32_t __a, int16_t __b, int16_t __c) +{ + return __builtin_aarch64_sqdmlalhi (__a, __b, __c); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlalh_lane_s16 (int32_t __a, int16_t __b, int16x4_t __c, const int __d) +{ + return __builtin_aarch64_sqdmlal_lanehi (__a, __b, __c, __d); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlalh_laneq_s16 (int32_t __a, int16_t __b, int16x8_t __c, const int __d) +{ + return __builtin_aarch64_sqdmlal_laneqhi (__a, __b, __c, __d); +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlals_s32 (int64_t __a, int32_t __b, int32_t __c) +{ + return __builtin_aarch64_sqdmlalsi (__a, __b, __c); +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlals_lane_s32 (int64_t __a, int32_t __b, int32x2_t __c, const int __d) +{ + return __builtin_aarch64_sqdmlal_lanesi (__a, __b, __c, __d); +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlals_laneq_s32 (int64_t __a, int32_t __b, int32x4_t __c, const int __d) +{ + return __builtin_aarch64_sqdmlal_laneqsi (__a, __b, __c, __d); +} + +/* vqdmlsl */ + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlsl_s16 (int32x4_t __a, int16x4_t __b, int16x4_t __c) +{ + return __builtin_aarch64_sqdmlslv4hi (__a, __b, __c); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlsl_high_s16 (int32x4_t __a, int16x8_t __b, int16x8_t __c) +{ + return __builtin_aarch64_sqdmlsl2v8hi (__a, __b, __c); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlsl_high_lane_s16 (int32x4_t __a, int16x8_t __b, int16x4_t __c, + int const __d) +{ + return __builtin_aarch64_sqdmlsl2_lanev8hi (__a, __b, __c, __d); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlsl_high_laneq_s16 (int32x4_t __a, int16x8_t __b, int16x8_t __c, + int const __d) +{ + return __builtin_aarch64_sqdmlsl2_laneqv8hi (__a, __b, __c, __d); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlsl_high_n_s16 (int32x4_t __a, int16x8_t __b, int16_t __c) +{ + return __builtin_aarch64_sqdmlsl2_nv8hi (__a, __b, __c); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlsl_lane_s16 (int32x4_t __a, int16x4_t __b, int16x4_t __c, int const __d) +{ + return __builtin_aarch64_sqdmlsl_lanev4hi (__a, __b, __c, __d); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlsl_laneq_s16 (int32x4_t __a, int16x4_t __b, int16x8_t __c, int const __d) +{ + return __builtin_aarch64_sqdmlsl_laneqv4hi (__a, __b, __c, __d); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlsl_n_s16 (int32x4_t __a, int16x4_t __b, int16_t __c) +{ + return __builtin_aarch64_sqdmlsl_nv4hi (__a, __b, __c); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlsl_s32 (int64x2_t __a, int32x2_t __b, int32x2_t __c) +{ + return __builtin_aarch64_sqdmlslv2si (__a, __b, __c); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlsl_high_s32 (int64x2_t __a, int32x4_t __b, int32x4_t __c) +{ + return __builtin_aarch64_sqdmlsl2v4si (__a, __b, __c); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlsl_high_lane_s32 (int64x2_t __a, int32x4_t __b, int32x2_t __c, + int const __d) +{ + return __builtin_aarch64_sqdmlsl2_lanev4si (__a, __b, __c, __d); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlsl_high_laneq_s32 (int64x2_t __a, int32x4_t __b, int32x4_t __c, + int const __d) +{ + return __builtin_aarch64_sqdmlsl2_laneqv4si (__a, __b, __c, __d); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlsl_high_n_s32 (int64x2_t __a, int32x4_t __b, int32_t __c) +{ + return __builtin_aarch64_sqdmlsl2_nv4si (__a, __b, __c); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlsl_lane_s32 (int64x2_t __a, int32x2_t __b, int32x2_t __c, int const __d) +{ + return __builtin_aarch64_sqdmlsl_lanev2si (__a, __b, __c, __d); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlsl_laneq_s32 (int64x2_t __a, int32x2_t __b, int32x4_t __c, int const __d) +{ + return __builtin_aarch64_sqdmlsl_laneqv2si (__a, __b, __c, __d); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlsl_n_s32 (int64x2_t __a, int32x2_t __b, int32_t __c) +{ + return __builtin_aarch64_sqdmlsl_nv2si (__a, __b, __c); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlslh_s16 (int32_t __a, int16_t __b, int16_t __c) +{ + return __builtin_aarch64_sqdmlslhi (__a, __b, __c); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlslh_lane_s16 (int32_t __a, int16_t __b, int16x4_t __c, const int __d) +{ + return __builtin_aarch64_sqdmlsl_lanehi (__a, __b, __c, __d); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlslh_laneq_s16 (int32_t __a, int16_t __b, int16x8_t __c, const int __d) +{ + return __builtin_aarch64_sqdmlsl_laneqhi (__a, __b, __c, __d); +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlsls_s32 (int64_t __a, int32_t __b, int32_t __c) +{ + return __builtin_aarch64_sqdmlslsi (__a, __b, __c); +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlsls_lane_s32 (int64_t __a, int32_t __b, int32x2_t __c, const int __d) +{ + return __builtin_aarch64_sqdmlsl_lanesi (__a, __b, __c, __d); +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmlsls_laneq_s32 (int64_t __a, int32_t __b, int32x4_t __c, const int __d) +{ + return __builtin_aarch64_sqdmlsl_laneqsi (__a, __b, __c, __d); +} + +/* vqdmulh */ + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmulh_lane_s16 (int16x4_t __a, int16x4_t __b, const int __c) +{ + return __builtin_aarch64_sqdmulh_lanev4hi (__a, __b, __c); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmulh_lane_s32 (int32x2_t __a, int32x2_t __b, const int __c) +{ + return __builtin_aarch64_sqdmulh_lanev2si (__a, __b, __c); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmulhq_lane_s16 (int16x8_t __a, int16x4_t __b, const int __c) +{ + return __builtin_aarch64_sqdmulh_lanev8hi (__a, __b, __c); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmulhq_lane_s32 (int32x4_t __a, int32x2_t __b, const int __c) +{ + return __builtin_aarch64_sqdmulh_lanev4si (__a, __b, __c); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmulhh_s16 (int16_t __a, int16_t __b) +{ + return (int16_t) __builtin_aarch64_sqdmulhhi (__a, __b); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmulhh_lane_s16 (int16_t __a, int16x4_t __b, const int __c) +{ + return __builtin_aarch64_sqdmulh_lanehi (__a, __b, __c); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmulhh_laneq_s16 (int16_t __a, int16x8_t __b, const int __c) +{ + return __builtin_aarch64_sqdmulh_laneqhi (__a, __b, __c); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmulhs_s32 (int32_t __a, int32_t __b) +{ + return (int32_t) __builtin_aarch64_sqdmulhsi (__a, __b); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmulhs_lane_s32 (int32_t __a, int32x2_t __b, const int __c) +{ + return __builtin_aarch64_sqdmulh_lanesi (__a, __b, __c); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmulhs_laneq_s32 (int32_t __a, int32x4_t __b, const int __c) +{ + return __builtin_aarch64_sqdmulh_laneqsi (__a, __b, __c); +} + +/* vqdmull */ + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmull_s16 (int16x4_t __a, int16x4_t __b) +{ + return __builtin_aarch64_sqdmullv4hi (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmull_high_s16 (int16x8_t __a, int16x8_t __b) +{ + return __builtin_aarch64_sqdmull2v8hi (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmull_high_lane_s16 (int16x8_t __a, int16x4_t __b, int const __c) +{ + return __builtin_aarch64_sqdmull2_lanev8hi (__a, __b,__c); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmull_high_laneq_s16 (int16x8_t __a, int16x8_t __b, int const __c) +{ + return __builtin_aarch64_sqdmull2_laneqv8hi (__a, __b,__c); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmull_high_n_s16 (int16x8_t __a, int16_t __b) +{ + return __builtin_aarch64_sqdmull2_nv8hi (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmull_lane_s16 (int16x4_t __a, int16x4_t __b, int const __c) +{ + return __builtin_aarch64_sqdmull_lanev4hi (__a, __b, __c); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmull_laneq_s16 (int16x4_t __a, int16x8_t __b, int const __c) +{ + return __builtin_aarch64_sqdmull_laneqv4hi (__a, __b, __c); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmull_n_s16 (int16x4_t __a, int16_t __b) +{ + return __builtin_aarch64_sqdmull_nv4hi (__a, __b); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmull_s32 (int32x2_t __a, int32x2_t __b) +{ + return __builtin_aarch64_sqdmullv2si (__a, __b); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmull_high_s32 (int32x4_t __a, int32x4_t __b) +{ + return __builtin_aarch64_sqdmull2v4si (__a, __b); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmull_high_lane_s32 (int32x4_t __a, int32x2_t __b, int const __c) +{ + return __builtin_aarch64_sqdmull2_lanev4si (__a, __b, __c); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmull_high_laneq_s32 (int32x4_t __a, int32x4_t __b, int const __c) +{ + return __builtin_aarch64_sqdmull2_laneqv4si (__a, __b, __c); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmull_high_n_s32 (int32x4_t __a, int32_t __b) +{ + return __builtin_aarch64_sqdmull2_nv4si (__a, __b); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmull_lane_s32 (int32x2_t __a, int32x2_t __b, int const __c) +{ + return __builtin_aarch64_sqdmull_lanev2si (__a, __b, __c); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmull_laneq_s32 (int32x2_t __a, int32x4_t __b, int const __c) +{ + return __builtin_aarch64_sqdmull_laneqv2si (__a, __b, __c); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmull_n_s32 (int32x2_t __a, int32_t __b) +{ + return __builtin_aarch64_sqdmull_nv2si (__a, __b); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmullh_s16 (int16_t __a, int16_t __b) +{ + return (int32_t) __builtin_aarch64_sqdmullhi (__a, __b); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmullh_lane_s16 (int16_t __a, int16x4_t __b, const int __c) +{ + return __builtin_aarch64_sqdmull_lanehi (__a, __b, __c); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmullh_laneq_s16 (int16_t __a, int16x8_t __b, const int __c) +{ + return __builtin_aarch64_sqdmull_laneqhi (__a, __b, __c); +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmulls_s32 (int32_t __a, int32_t __b) +{ + return __builtin_aarch64_sqdmullsi (__a, __b); +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmulls_lane_s32 (int32_t __a, int32x2_t __b, const int __c) +{ + return __builtin_aarch64_sqdmull_lanesi (__a, __b, __c); +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqdmulls_laneq_s32 (int32_t __a, int32x4_t __b, const int __c) +{ + return __builtin_aarch64_sqdmull_laneqsi (__a, __b, __c); +} + +/* vqmovn */ + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqmovn_s16 (int16x8_t __a) +{ + return (int8x8_t) __builtin_aarch64_sqmovnv8hi (__a); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqmovn_s32 (int32x4_t __a) +{ + return (int16x4_t) __builtin_aarch64_sqmovnv4si (__a); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqmovn_s64 (int64x2_t __a) +{ + return (int32x2_t) __builtin_aarch64_sqmovnv2di (__a); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqmovn_u16 (uint16x8_t __a) +{ + return (uint8x8_t) __builtin_aarch64_uqmovnv8hi ((int16x8_t) __a); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqmovn_u32 (uint32x4_t __a) +{ + return (uint16x4_t) __builtin_aarch64_uqmovnv4si ((int32x4_t) __a); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqmovn_u64 (uint64x2_t __a) +{ + return (uint32x2_t) __builtin_aarch64_uqmovnv2di ((int64x2_t) __a); +} + +__extension__ extern __inline int8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqmovnh_s16 (int16_t __a) +{ + return (int8_t) __builtin_aarch64_sqmovnhi (__a); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqmovns_s32 (int32_t __a) +{ + return (int16_t) __builtin_aarch64_sqmovnsi (__a); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqmovnd_s64 (int64_t __a) +{ + return (int32_t) __builtin_aarch64_sqmovndi (__a); +} + +__extension__ extern __inline uint8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqmovnh_u16 (uint16_t __a) +{ + return (uint8_t) __builtin_aarch64_uqmovnhi (__a); +} + +__extension__ extern __inline uint16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqmovns_u32 (uint32_t __a) +{ + return (uint16_t) __builtin_aarch64_uqmovnsi (__a); +} + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqmovnd_u64 (uint64_t __a) +{ + return (uint32_t) __builtin_aarch64_uqmovndi (__a); +} + +/* vqmovun */ + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqmovun_s16 (int16x8_t __a) +{ + return (uint8x8_t) __builtin_aarch64_sqmovunv8hi (__a); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqmovun_s32 (int32x4_t __a) +{ + return (uint16x4_t) __builtin_aarch64_sqmovunv4si (__a); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqmovun_s64 (int64x2_t __a) +{ + return (uint32x2_t) __builtin_aarch64_sqmovunv2di (__a); +} + +__extension__ extern __inline int8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqmovunh_s16 (int16_t __a) +{ + return (int8_t) __builtin_aarch64_sqmovunhi (__a); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqmovuns_s32 (int32_t __a) +{ + return (int16_t) __builtin_aarch64_sqmovunsi (__a); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqmovund_s64 (int64_t __a) +{ + return (int32_t) __builtin_aarch64_sqmovundi (__a); +} + +/* vqneg */ + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqnegq_s64 (int64x2_t __a) +{ + return (int64x2_t) __builtin_aarch64_sqnegv2di (__a); +} + +__extension__ extern __inline int8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqnegb_s8 (int8_t __a) +{ + return (int8_t) __builtin_aarch64_sqnegqi (__a); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqnegh_s16 (int16_t __a) +{ + return (int16_t) __builtin_aarch64_sqneghi (__a); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqnegs_s32 (int32_t __a) +{ + return (int32_t) __builtin_aarch64_sqnegsi (__a); +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqnegd_s64 (int64_t __a) +{ + return __builtin_aarch64_sqnegdi (__a); +} + +/* vqrdmulh */ + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmulh_lane_s16 (int16x4_t __a, int16x4_t __b, const int __c) +{ + return __builtin_aarch64_sqrdmulh_lanev4hi (__a, __b, __c); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmulh_lane_s32 (int32x2_t __a, int32x2_t __b, const int __c) +{ + return __builtin_aarch64_sqrdmulh_lanev2si (__a, __b, __c); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmulhq_lane_s16 (int16x8_t __a, int16x4_t __b, const int __c) +{ + return __builtin_aarch64_sqrdmulh_lanev8hi (__a, __b, __c); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmulhq_lane_s32 (int32x4_t __a, int32x2_t __b, const int __c) +{ + return __builtin_aarch64_sqrdmulh_lanev4si (__a, __b, __c); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmulhh_s16 (int16_t __a, int16_t __b) +{ + return (int16_t) __builtin_aarch64_sqrdmulhhi (__a, __b); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmulhh_lane_s16 (int16_t __a, int16x4_t __b, const int __c) +{ + return __builtin_aarch64_sqrdmulh_lanehi (__a, __b, __c); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmulhh_laneq_s16 (int16_t __a, int16x8_t __b, const int __c) +{ + return __builtin_aarch64_sqrdmulh_laneqhi (__a, __b, __c); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmulhs_s32 (int32_t __a, int32_t __b) +{ + return (int32_t) __builtin_aarch64_sqrdmulhsi (__a, __b); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmulhs_lane_s32 (int32_t __a, int32x2_t __b, const int __c) +{ + return __builtin_aarch64_sqrdmulh_lanesi (__a, __b, __c); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrdmulhs_laneq_s32 (int32_t __a, int32x4_t __b, const int __c) +{ + return __builtin_aarch64_sqrdmulh_laneqsi (__a, __b, __c); +} + +/* vqrshl */ + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshl_s8 (int8x8_t __a, int8x8_t __b) +{ + return __builtin_aarch64_sqrshlv8qi (__a, __b); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshl_s16 (int16x4_t __a, int16x4_t __b) +{ + return __builtin_aarch64_sqrshlv4hi (__a, __b); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshl_s32 (int32x2_t __a, int32x2_t __b) +{ + return __builtin_aarch64_sqrshlv2si (__a, __b); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshl_s64 (int64x1_t __a, int64x1_t __b) +{ + return (int64x1_t) {__builtin_aarch64_sqrshldi (__a[0], __b[0])}; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshl_u8 (uint8x8_t __a, int8x8_t __b) +{ + return __builtin_aarch64_uqrshlv8qi_uus ( __a, __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshl_u16 (uint16x4_t __a, int16x4_t __b) +{ + return __builtin_aarch64_uqrshlv4hi_uus ( __a, __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshl_u32 (uint32x2_t __a, int32x2_t __b) +{ + return __builtin_aarch64_uqrshlv2si_uus ( __a, __b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshl_u64 (uint64x1_t __a, int64x1_t __b) +{ + return (uint64x1_t) {__builtin_aarch64_uqrshldi_uus (__a[0], __b[0])}; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshlq_s8 (int8x16_t __a, int8x16_t __b) +{ + return __builtin_aarch64_sqrshlv16qi (__a, __b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshlq_s16 (int16x8_t __a, int16x8_t __b) +{ + return __builtin_aarch64_sqrshlv8hi (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshlq_s32 (int32x4_t __a, int32x4_t __b) +{ + return __builtin_aarch64_sqrshlv4si (__a, __b); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshlq_s64 (int64x2_t __a, int64x2_t __b) +{ + return __builtin_aarch64_sqrshlv2di (__a, __b); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshlq_u8 (uint8x16_t __a, int8x16_t __b) +{ + return __builtin_aarch64_uqrshlv16qi_uus ( __a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshlq_u16 (uint16x8_t __a, int16x8_t __b) +{ + return __builtin_aarch64_uqrshlv8hi_uus ( __a, __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshlq_u32 (uint32x4_t __a, int32x4_t __b) +{ + return __builtin_aarch64_uqrshlv4si_uus ( __a, __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshlq_u64 (uint64x2_t __a, int64x2_t __b) +{ + return __builtin_aarch64_uqrshlv2di_uus ( __a, __b); +} + +__extension__ extern __inline int8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshlb_s8 (int8_t __a, int8_t __b) +{ + return __builtin_aarch64_sqrshlqi (__a, __b); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshlh_s16 (int16_t __a, int16_t __b) +{ + return __builtin_aarch64_sqrshlhi (__a, __b); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshls_s32 (int32_t __a, int32_t __b) +{ + return __builtin_aarch64_sqrshlsi (__a, __b); +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshld_s64 (int64_t __a, int64_t __b) +{ + return __builtin_aarch64_sqrshldi (__a, __b); +} + +__extension__ extern __inline uint8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshlb_u8 (uint8_t __a, uint8_t __b) +{ + return __builtin_aarch64_uqrshlqi_uus (__a, __b); +} + +__extension__ extern __inline uint16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshlh_u16 (uint16_t __a, uint16_t __b) +{ + return __builtin_aarch64_uqrshlhi_uus (__a, __b); +} + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshls_u32 (uint32_t __a, uint32_t __b) +{ + return __builtin_aarch64_uqrshlsi_uus (__a, __b); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshld_u64 (uint64_t __a, uint64_t __b) +{ + return __builtin_aarch64_uqrshldi_uus (__a, __b); +} + +/* vqrshrn */ + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshrn_n_s16 (int16x8_t __a, const int __b) +{ + return (int8x8_t) __builtin_aarch64_sqrshrn_nv8hi (__a, __b); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshrn_n_s32 (int32x4_t __a, const int __b) +{ + return (int16x4_t) __builtin_aarch64_sqrshrn_nv4si (__a, __b); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshrn_n_s64 (int64x2_t __a, const int __b) +{ + return (int32x2_t) __builtin_aarch64_sqrshrn_nv2di (__a, __b); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshrn_n_u16 (uint16x8_t __a, const int __b) +{ + return __builtin_aarch64_uqrshrn_nv8hi_uus ( __a, __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshrn_n_u32 (uint32x4_t __a, const int __b) +{ + return __builtin_aarch64_uqrshrn_nv4si_uus ( __a, __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshrn_n_u64 (uint64x2_t __a, const int __b) +{ + return __builtin_aarch64_uqrshrn_nv2di_uus ( __a, __b); +} + +__extension__ extern __inline int8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshrnh_n_s16 (int16_t __a, const int __b) +{ + return (int8_t) __builtin_aarch64_sqrshrn_nhi (__a, __b); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshrns_n_s32 (int32_t __a, const int __b) +{ + return (int16_t) __builtin_aarch64_sqrshrn_nsi (__a, __b); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshrnd_n_s64 (int64_t __a, const int __b) +{ + return (int32_t) __builtin_aarch64_sqrshrn_ndi (__a, __b); +} + +__extension__ extern __inline uint8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshrnh_n_u16 (uint16_t __a, const int __b) +{ + return __builtin_aarch64_uqrshrn_nhi_uus (__a, __b); +} + +__extension__ extern __inline uint16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshrns_n_u32 (uint32_t __a, const int __b) +{ + return __builtin_aarch64_uqrshrn_nsi_uus (__a, __b); +} + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshrnd_n_u64 (uint64_t __a, const int __b) +{ + return __builtin_aarch64_uqrshrn_ndi_uus (__a, __b); +} + +/* vqrshrun */ + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshrun_n_s16 (int16x8_t __a, const int __b) +{ + return (uint8x8_t) __builtin_aarch64_sqrshrun_nv8hi (__a, __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshrun_n_s32 (int32x4_t __a, const int __b) +{ + return (uint16x4_t) __builtin_aarch64_sqrshrun_nv4si (__a, __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshrun_n_s64 (int64x2_t __a, const int __b) +{ + return (uint32x2_t) __builtin_aarch64_sqrshrun_nv2di (__a, __b); +} + +__extension__ extern __inline int8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshrunh_n_s16 (int16_t __a, const int __b) +{ + return (int8_t) __builtin_aarch64_sqrshrun_nhi (__a, __b); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshruns_n_s32 (int32_t __a, const int __b) +{ + return (int16_t) __builtin_aarch64_sqrshrun_nsi (__a, __b); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqrshrund_n_s64 (int64_t __a, const int __b) +{ + return (int32_t) __builtin_aarch64_sqrshrun_ndi (__a, __b); +} + +/* vqshl */ + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshl_s8 (int8x8_t __a, int8x8_t __b) +{ + return __builtin_aarch64_sqshlv8qi (__a, __b); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshl_s16 (int16x4_t __a, int16x4_t __b) +{ + return __builtin_aarch64_sqshlv4hi (__a, __b); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshl_s32 (int32x2_t __a, int32x2_t __b) +{ + return __builtin_aarch64_sqshlv2si (__a, __b); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshl_s64 (int64x1_t __a, int64x1_t __b) +{ + return (int64x1_t) {__builtin_aarch64_sqshldi (__a[0], __b[0])}; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshl_u8 (uint8x8_t __a, int8x8_t __b) +{ + return __builtin_aarch64_uqshlv8qi_uus ( __a, __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshl_u16 (uint16x4_t __a, int16x4_t __b) +{ + return __builtin_aarch64_uqshlv4hi_uus ( __a, __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshl_u32 (uint32x2_t __a, int32x2_t __b) +{ + return __builtin_aarch64_uqshlv2si_uus ( __a, __b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshl_u64 (uint64x1_t __a, int64x1_t __b) +{ + return (uint64x1_t) {__builtin_aarch64_uqshldi_uus (__a[0], __b[0])}; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshlq_s8 (int8x16_t __a, int8x16_t __b) +{ + return __builtin_aarch64_sqshlv16qi (__a, __b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshlq_s16 (int16x8_t __a, int16x8_t __b) +{ + return __builtin_aarch64_sqshlv8hi (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshlq_s32 (int32x4_t __a, int32x4_t __b) +{ + return __builtin_aarch64_sqshlv4si (__a, __b); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshlq_s64 (int64x2_t __a, int64x2_t __b) +{ + return __builtin_aarch64_sqshlv2di (__a, __b); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshlq_u8 (uint8x16_t __a, int8x16_t __b) +{ + return __builtin_aarch64_uqshlv16qi_uus ( __a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshlq_u16 (uint16x8_t __a, int16x8_t __b) +{ + return __builtin_aarch64_uqshlv8hi_uus ( __a, __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshlq_u32 (uint32x4_t __a, int32x4_t __b) +{ + return __builtin_aarch64_uqshlv4si_uus ( __a, __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshlq_u64 (uint64x2_t __a, int64x2_t __b) +{ + return __builtin_aarch64_uqshlv2di_uus ( __a, __b); +} + +__extension__ extern __inline int8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshlb_s8 (int8_t __a, int8_t __b) +{ + return __builtin_aarch64_sqshlqi (__a, __b); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshlh_s16 (int16_t __a, int16_t __b) +{ + return __builtin_aarch64_sqshlhi (__a, __b); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshls_s32 (int32_t __a, int32_t __b) +{ + return __builtin_aarch64_sqshlsi (__a, __b); +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshld_s64 (int64_t __a, int64_t __b) +{ + return __builtin_aarch64_sqshldi (__a, __b); +} + +__extension__ extern __inline uint8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshlb_u8 (uint8_t __a, uint8_t __b) +{ + return __builtin_aarch64_uqshlqi_uus (__a, __b); +} + +__extension__ extern __inline uint16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshlh_u16 (uint16_t __a, uint16_t __b) +{ + return __builtin_aarch64_uqshlhi_uus (__a, __b); +} + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshls_u32 (uint32_t __a, uint32_t __b) +{ + return __builtin_aarch64_uqshlsi_uus (__a, __b); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshld_u64 (uint64_t __a, uint64_t __b) +{ + return __builtin_aarch64_uqshldi_uus (__a, __b); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshl_n_s8 (int8x8_t __a, const int __b) +{ + return (int8x8_t) __builtin_aarch64_sqshl_nv8qi (__a, __b); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshl_n_s16 (int16x4_t __a, const int __b) +{ + return (int16x4_t) __builtin_aarch64_sqshl_nv4hi (__a, __b); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshl_n_s32 (int32x2_t __a, const int __b) +{ + return (int32x2_t) __builtin_aarch64_sqshl_nv2si (__a, __b); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshl_n_s64 (int64x1_t __a, const int __b) +{ + return (int64x1_t) {__builtin_aarch64_sqshl_ndi (__a[0], __b)}; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshl_n_u8 (uint8x8_t __a, const int __b) +{ + return __builtin_aarch64_uqshl_nv8qi_uus (__a, __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshl_n_u16 (uint16x4_t __a, const int __b) +{ + return __builtin_aarch64_uqshl_nv4hi_uus (__a, __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshl_n_u32 (uint32x2_t __a, const int __b) +{ + return __builtin_aarch64_uqshl_nv2si_uus (__a, __b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshl_n_u64 (uint64x1_t __a, const int __b) +{ + return (uint64x1_t) {__builtin_aarch64_uqshl_ndi_uus (__a[0], __b)}; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshlq_n_s8 (int8x16_t __a, const int __b) +{ + return (int8x16_t) __builtin_aarch64_sqshl_nv16qi (__a, __b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshlq_n_s16 (int16x8_t __a, const int __b) +{ + return (int16x8_t) __builtin_aarch64_sqshl_nv8hi (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshlq_n_s32 (int32x4_t __a, const int __b) +{ + return (int32x4_t) __builtin_aarch64_sqshl_nv4si (__a, __b); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshlq_n_s64 (int64x2_t __a, const int __b) +{ + return (int64x2_t) __builtin_aarch64_sqshl_nv2di (__a, __b); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshlq_n_u8 (uint8x16_t __a, const int __b) +{ + return __builtin_aarch64_uqshl_nv16qi_uus (__a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshlq_n_u16 (uint16x8_t __a, const int __b) +{ + return __builtin_aarch64_uqshl_nv8hi_uus (__a, __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshlq_n_u32 (uint32x4_t __a, const int __b) +{ + return __builtin_aarch64_uqshl_nv4si_uus (__a, __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshlq_n_u64 (uint64x2_t __a, const int __b) +{ + return __builtin_aarch64_uqshl_nv2di_uus (__a, __b); +} + +__extension__ extern __inline int8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshlb_n_s8 (int8_t __a, const int __b) +{ + return (int8_t) __builtin_aarch64_sqshl_nqi (__a, __b); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshlh_n_s16 (int16_t __a, const int __b) +{ + return (int16_t) __builtin_aarch64_sqshl_nhi (__a, __b); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshls_n_s32 (int32_t __a, const int __b) +{ + return (int32_t) __builtin_aarch64_sqshl_nsi (__a, __b); +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshld_n_s64 (int64_t __a, const int __b) +{ + return __builtin_aarch64_sqshl_ndi (__a, __b); +} + +__extension__ extern __inline uint8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshlb_n_u8 (uint8_t __a, const int __b) +{ + return __builtin_aarch64_uqshl_nqi_uus (__a, __b); +} + +__extension__ extern __inline uint16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshlh_n_u16 (uint16_t __a, const int __b) +{ + return __builtin_aarch64_uqshl_nhi_uus (__a, __b); +} + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshls_n_u32 (uint32_t __a, const int __b) +{ + return __builtin_aarch64_uqshl_nsi_uus (__a, __b); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshld_n_u64 (uint64_t __a, const int __b) +{ + return __builtin_aarch64_uqshl_ndi_uus (__a, __b); +} + +/* vqshlu */ + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshlu_n_s8 (int8x8_t __a, const int __b) +{ + return __builtin_aarch64_sqshlu_nv8qi_uss (__a, __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshlu_n_s16 (int16x4_t __a, const int __b) +{ + return __builtin_aarch64_sqshlu_nv4hi_uss (__a, __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshlu_n_s32 (int32x2_t __a, const int __b) +{ + return __builtin_aarch64_sqshlu_nv2si_uss (__a, __b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshlu_n_s64 (int64x1_t __a, const int __b) +{ + return (uint64x1_t) {__builtin_aarch64_sqshlu_ndi_uss (__a[0], __b)}; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshluq_n_s8 (int8x16_t __a, const int __b) +{ + return __builtin_aarch64_sqshlu_nv16qi_uss (__a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshluq_n_s16 (int16x8_t __a, const int __b) +{ + return __builtin_aarch64_sqshlu_nv8hi_uss (__a, __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshluq_n_s32 (int32x4_t __a, const int __b) +{ + return __builtin_aarch64_sqshlu_nv4si_uss (__a, __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshluq_n_s64 (int64x2_t __a, const int __b) +{ + return __builtin_aarch64_sqshlu_nv2di_uss (__a, __b); +} + +__extension__ extern __inline int8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshlub_n_s8 (int8_t __a, const int __b) +{ + return (int8_t) __builtin_aarch64_sqshlu_nqi_uss (__a, __b); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshluh_n_s16 (int16_t __a, const int __b) +{ + return (int16_t) __builtin_aarch64_sqshlu_nhi_uss (__a, __b); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshlus_n_s32 (int32_t __a, const int __b) +{ + return (int32_t) __builtin_aarch64_sqshlu_nsi_uss (__a, __b); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshlud_n_s64 (int64_t __a, const int __b) +{ + return __builtin_aarch64_sqshlu_ndi_uss (__a, __b); +} + +/* vqshrn */ + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshrn_n_s16 (int16x8_t __a, const int __b) +{ + return (int8x8_t) __builtin_aarch64_sqshrn_nv8hi (__a, __b); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshrn_n_s32 (int32x4_t __a, const int __b) +{ + return (int16x4_t) __builtin_aarch64_sqshrn_nv4si (__a, __b); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshrn_n_s64 (int64x2_t __a, const int __b) +{ + return (int32x2_t) __builtin_aarch64_sqshrn_nv2di (__a, __b); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshrn_n_u16 (uint16x8_t __a, const int __b) +{ + return __builtin_aarch64_uqshrn_nv8hi_uus ( __a, __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshrn_n_u32 (uint32x4_t __a, const int __b) +{ + return __builtin_aarch64_uqshrn_nv4si_uus ( __a, __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshrn_n_u64 (uint64x2_t __a, const int __b) +{ + return __builtin_aarch64_uqshrn_nv2di_uus ( __a, __b); +} + +__extension__ extern __inline int8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshrnh_n_s16 (int16_t __a, const int __b) +{ + return (int8_t) __builtin_aarch64_sqshrn_nhi (__a, __b); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshrns_n_s32 (int32_t __a, const int __b) +{ + return (int16_t) __builtin_aarch64_sqshrn_nsi (__a, __b); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshrnd_n_s64 (int64_t __a, const int __b) +{ + return (int32_t) __builtin_aarch64_sqshrn_ndi (__a, __b); +} + +__extension__ extern __inline uint8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshrnh_n_u16 (uint16_t __a, const int __b) +{ + return __builtin_aarch64_uqshrn_nhi_uus (__a, __b); +} + +__extension__ extern __inline uint16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshrns_n_u32 (uint32_t __a, const int __b) +{ + return __builtin_aarch64_uqshrn_nsi_uus (__a, __b); +} + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshrnd_n_u64 (uint64_t __a, const int __b) +{ + return __builtin_aarch64_uqshrn_ndi_uus (__a, __b); +} + +/* vqshrun */ + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshrun_n_s16 (int16x8_t __a, const int __b) +{ + return (uint8x8_t) __builtin_aarch64_sqshrun_nv8hi (__a, __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshrun_n_s32 (int32x4_t __a, const int __b) +{ + return (uint16x4_t) __builtin_aarch64_sqshrun_nv4si (__a, __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshrun_n_s64 (int64x2_t __a, const int __b) +{ + return (uint32x2_t) __builtin_aarch64_sqshrun_nv2di (__a, __b); +} + +__extension__ extern __inline int8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshrunh_n_s16 (int16_t __a, const int __b) +{ + return (int8_t) __builtin_aarch64_sqshrun_nhi (__a, __b); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshruns_n_s32 (int32_t __a, const int __b) +{ + return (int16_t) __builtin_aarch64_sqshrun_nsi (__a, __b); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqshrund_n_s64 (int64_t __a, const int __b) +{ + return (int32_t) __builtin_aarch64_sqshrun_ndi (__a, __b); +} + +/* vqsub */ + +__extension__ extern __inline int8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqsubb_s8 (int8_t __a, int8_t __b) +{ + return (int8_t) __builtin_aarch64_sqsubqi (__a, __b); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqsubh_s16 (int16_t __a, int16_t __b) +{ + return (int16_t) __builtin_aarch64_sqsubhi (__a, __b); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqsubs_s32 (int32_t __a, int32_t __b) +{ + return (int32_t) __builtin_aarch64_sqsubsi (__a, __b); +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqsubd_s64 (int64_t __a, int64_t __b) +{ + return __builtin_aarch64_sqsubdi (__a, __b); +} + +__extension__ extern __inline uint8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqsubb_u8 (uint8_t __a, uint8_t __b) +{ + return (uint8_t) __builtin_aarch64_uqsubqi_uuu (__a, __b); +} + +__extension__ extern __inline uint16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqsubh_u16 (uint16_t __a, uint16_t __b) +{ + return (uint16_t) __builtin_aarch64_uqsubhi_uuu (__a, __b); +} + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqsubs_u32 (uint32_t __a, uint32_t __b) +{ + return (uint32_t) __builtin_aarch64_uqsubsi_uuu (__a, __b); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqsubd_u64 (uint64_t __a, uint64_t __b) +{ + return __builtin_aarch64_uqsubdi_uuu (__a, __b); +} + +/* vqtbl2 */ + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbl2_s8 (int8x16x2_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv16qi (__o, tab.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, tab.val[1], 1); + return __builtin_aarch64_tbl3v8qi (__o, (int8x8_t)idx); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbl2_u8 (uint8x16x2_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[1], 1); + return (uint8x8_t)__builtin_aarch64_tbl3v8qi (__o, (int8x8_t)idx); +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbl2_p8 (poly8x16x2_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[1], 1); + return (poly8x8_t)__builtin_aarch64_tbl3v8qi (__o, (int8x8_t)idx); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbl2q_s8 (int8x16x2_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[1], 1); + return __builtin_aarch64_tbl3v16qi (__o, (int8x16_t)idx); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbl2q_u8 (uint8x16x2_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[1], 1); + return (uint8x16_t)__builtin_aarch64_tbl3v16qi (__o, (int8x16_t)idx); +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbl2q_p8 (poly8x16x2_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[1], 1); + return (poly8x16_t)__builtin_aarch64_tbl3v16qi (__o, (int8x16_t)idx); +} + +/* vqtbl3 */ + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbl3_s8 (int8x16x3_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[2], 2); + return __builtin_aarch64_qtbl3v8qi (__o, (int8x8_t)idx); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbl3_u8 (uint8x16x3_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[2], 2); + return (uint8x8_t)__builtin_aarch64_qtbl3v8qi (__o, (int8x8_t)idx); +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbl3_p8 (poly8x16x3_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[2], 2); + return (poly8x8_t)__builtin_aarch64_qtbl3v8qi (__o, (int8x8_t)idx); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbl3q_s8 (int8x16x3_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[2], 2); + return __builtin_aarch64_qtbl3v16qi (__o, (int8x16_t)idx); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbl3q_u8 (uint8x16x3_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[2], 2); + return (uint8x16_t)__builtin_aarch64_qtbl3v16qi (__o, (int8x16_t)idx); +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbl3q_p8 (poly8x16x3_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[2], 2); + return (poly8x16_t)__builtin_aarch64_qtbl3v16qi (__o, (int8x16_t)idx); +} + +/* vqtbl4 */ + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbl4_s8 (int8x16x4_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[2], 2); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[3], 3); + return __builtin_aarch64_qtbl4v8qi (__o, (int8x8_t)idx); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbl4_u8 (uint8x16x4_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[2], 2); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[3], 3); + return (uint8x8_t)__builtin_aarch64_qtbl4v8qi (__o, (int8x8_t)idx); +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbl4_p8 (poly8x16x4_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[2], 2); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[3], 3); + return (poly8x8_t)__builtin_aarch64_qtbl4v8qi (__o, (int8x8_t)idx); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbl4q_s8 (int8x16x4_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[2], 2); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[3], 3); + return __builtin_aarch64_qtbl4v16qi (__o, (int8x16_t)idx); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbl4q_u8 (uint8x16x4_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[2], 2); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[3], 3); + return (uint8x16_t)__builtin_aarch64_qtbl4v16qi (__o, (int8x16_t)idx); +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbl4q_p8 (poly8x16x4_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[2], 2); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[3], 3); + return (poly8x16_t)__builtin_aarch64_qtbl4v16qi (__o, (int8x16_t)idx); +} + + +/* vqtbx2 */ +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbx2_s8 (int8x8_t r, int8x16x2_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv16qi (__o, tab.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, tab.val[1], 1); + return __builtin_aarch64_tbx4v8qi (r, __o, (int8x8_t)idx); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbx2_u8 (uint8x8_t r, uint8x16x2_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[1], 1); + return (uint8x8_t)__builtin_aarch64_tbx4v8qi ((int8x8_t)r, __o, + (int8x8_t)idx); +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbx2_p8 (poly8x8_t r, poly8x16x2_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[1], 1); + return (poly8x8_t)__builtin_aarch64_tbx4v8qi ((int8x8_t)r, __o, + (int8x8_t)idx); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbx2q_s8 (int8x16_t r, int8x16x2_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv16qi (__o, tab.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, tab.val[1], 1); + return __builtin_aarch64_tbx4v16qi (r, __o, (int8x16_t)idx); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbx2q_u8 (uint8x16_t r, uint8x16x2_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[1], 1); + return (uint8x16_t)__builtin_aarch64_tbx4v16qi ((int8x16_t)r, __o, + (int8x16_t)idx); +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbx2q_p8 (poly8x16_t r, poly8x16x2_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[1], 1); + return (poly8x16_t)__builtin_aarch64_tbx4v16qi ((int8x16_t)r, __o, + (int8x16_t)idx); +} + +/* vqtbx3 */ +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbx3_s8 (int8x8_t r, int8x16x3_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv16qi (__o, tab.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, tab.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, tab.val[2], 2); + return __builtin_aarch64_qtbx3v8qi (r, __o, (int8x8_t)idx); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbx3_u8 (uint8x8_t r, uint8x16x3_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[2], 2); + return (uint8x8_t)__builtin_aarch64_qtbx3v8qi ((int8x8_t)r, __o, + (int8x8_t)idx); +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbx3_p8 (poly8x8_t r, poly8x16x3_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[2], 2); + return (poly8x8_t)__builtin_aarch64_qtbx3v8qi ((int8x8_t)r, __o, + (int8x8_t)idx); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbx3q_s8 (int8x16_t r, int8x16x3_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv16qi (__o, tab.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, tab.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, tab.val[2], 2); + return __builtin_aarch64_qtbx3v16qi (r, __o, (int8x16_t)idx); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbx3q_u8 (uint8x16_t r, uint8x16x3_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[2], 2); + return (uint8x16_t)__builtin_aarch64_qtbx3v16qi ((int8x16_t)r, __o, + (int8x16_t)idx); +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbx3q_p8 (poly8x16_t r, poly8x16x3_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[2], 2); + return (poly8x16_t)__builtin_aarch64_qtbx3v16qi ((int8x16_t)r, __o, + (int8x16_t)idx); +} + +/* vqtbx4 */ + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbx4_s8 (int8x8_t r, int8x16x4_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv16qi (__o, tab.val[0], 0); + __o = __builtin_aarch64_set_qregxiv16qi (__o, tab.val[1], 1); + __o = __builtin_aarch64_set_qregxiv16qi (__o, tab.val[2], 2); + __o = __builtin_aarch64_set_qregxiv16qi (__o, tab.val[3], 3); + return __builtin_aarch64_qtbx4v8qi (r, __o, (int8x8_t)idx); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbx4_u8 (uint8x8_t r, uint8x16x4_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[2], 2); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[3], 3); + return (uint8x8_t)__builtin_aarch64_qtbx4v8qi ((int8x8_t)r, __o, + (int8x8_t)idx); +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbx4_p8 (poly8x8_t r, poly8x16x4_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[2], 2); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[3], 3); + return (poly8x8_t)__builtin_aarch64_qtbx4v8qi ((int8x8_t)r, __o, + (int8x8_t)idx); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbx4q_s8 (int8x16_t r, int8x16x4_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv16qi (__o, tab.val[0], 0); + __o = __builtin_aarch64_set_qregxiv16qi (__o, tab.val[1], 1); + __o = __builtin_aarch64_set_qregxiv16qi (__o, tab.val[2], 2); + __o = __builtin_aarch64_set_qregxiv16qi (__o, tab.val[3], 3); + return __builtin_aarch64_qtbx4v16qi (r, __o, (int8x16_t)idx); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbx4q_u8 (uint8x16_t r, uint8x16x4_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[2], 2); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[3], 3); + return (uint8x16_t)__builtin_aarch64_qtbx4v16qi ((int8x16_t)r, __o, + (int8x16_t)idx); +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vqtbx4q_p8 (poly8x16_t r, poly8x16x4_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[2], 2); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[3], 3); + return (poly8x16_t)__builtin_aarch64_qtbx4v16qi ((int8x16_t)r, __o, + (int8x16_t)idx); +} + +/* vrbit */ + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrbit_p8 (poly8x8_t __a) +{ + return (poly8x8_t) __builtin_aarch64_rbitv8qi ((int8x8_t) __a); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrbit_s8 (int8x8_t __a) +{ + return __builtin_aarch64_rbitv8qi (__a); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrbit_u8 (uint8x8_t __a) +{ + return (uint8x8_t) __builtin_aarch64_rbitv8qi ((int8x8_t) __a); +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrbitq_p8 (poly8x16_t __a) +{ + return (poly8x16_t) __builtin_aarch64_rbitv16qi ((int8x16_t)__a); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrbitq_s8 (int8x16_t __a) +{ + return __builtin_aarch64_rbitv16qi (__a); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrbitq_u8 (uint8x16_t __a) +{ + return (uint8x16_t) __builtin_aarch64_rbitv16qi ((int8x16_t) __a); +} + +/* vrecpe */ + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrecpe_u32 (uint32x2_t __a) +{ + return (uint32x2_t) __builtin_aarch64_urecpev2si ((int32x2_t) __a); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrecpeq_u32 (uint32x4_t __a) +{ + return (uint32x4_t) __builtin_aarch64_urecpev4si ((int32x4_t) __a); +} + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrecpes_f32 (float32_t __a) +{ + return __builtin_aarch64_frecpesf (__a); +} + +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrecped_f64 (float64_t __a) +{ + return __builtin_aarch64_frecpedf (__a); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrecpe_f32 (float32x2_t __a) +{ + return __builtin_aarch64_frecpev2sf (__a); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrecpe_f64 (float64x1_t __a) +{ + return (float64x1_t) { vrecped_f64 (vget_lane_f64 (__a, 0)) }; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrecpeq_f32 (float32x4_t __a) +{ + return __builtin_aarch64_frecpev4sf (__a); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrecpeq_f64 (float64x2_t __a) +{ + return __builtin_aarch64_frecpev2df (__a); +} + +/* vrecps */ + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrecpss_f32 (float32_t __a, float32_t __b) +{ + return __builtin_aarch64_frecpssf (__a, __b); +} + +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrecpsd_f64 (float64_t __a, float64_t __b) +{ + return __builtin_aarch64_frecpsdf (__a, __b); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrecps_f32 (float32x2_t __a, float32x2_t __b) +{ + return __builtin_aarch64_frecpsv2sf (__a, __b); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrecps_f64 (float64x1_t __a, float64x1_t __b) +{ + return (float64x1_t) { vrecpsd_f64 (vget_lane_f64 (__a, 0), + vget_lane_f64 (__b, 0)) }; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrecpsq_f32 (float32x4_t __a, float32x4_t __b) +{ + return __builtin_aarch64_frecpsv4sf (__a, __b); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrecpsq_f64 (float64x2_t __a, float64x2_t __b) +{ + return __builtin_aarch64_frecpsv2df (__a, __b); +} + +/* vrecpx */ + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrecpxs_f32 (float32_t __a) +{ + return __builtin_aarch64_frecpxsf (__a); +} + +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrecpxd_f64 (float64_t __a) +{ + return __builtin_aarch64_frecpxdf (__a); +} + + +/* vrev */ + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev16_p8 (poly8x8_t a) +{ + return __builtin_shuffle (a, (uint8x8_t) { 1, 0, 3, 2, 5, 4, 7, 6 }); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev16_s8 (int8x8_t a) +{ + return __builtin_shuffle (a, (uint8x8_t) { 1, 0, 3, 2, 5, 4, 7, 6 }); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev16_u8 (uint8x8_t a) +{ + return __builtin_shuffle (a, (uint8x8_t) { 1, 0, 3, 2, 5, 4, 7, 6 }); +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev16q_p8 (poly8x16_t a) +{ + return __builtin_shuffle (a, + (uint8x16_t) { 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14 }); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev16q_s8 (int8x16_t a) +{ + return __builtin_shuffle (a, + (uint8x16_t) { 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14 }); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev16q_u8 (uint8x16_t a) +{ + return __builtin_shuffle (a, + (uint8x16_t) { 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14 }); +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev32_p8 (poly8x8_t a) +{ + return __builtin_shuffle (a, (uint8x8_t) { 3, 2, 1, 0, 7, 6, 5, 4 }); +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev32_p16 (poly16x4_t a) +{ + return __builtin_shuffle (a, (uint16x4_t) { 1, 0, 3, 2 }); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev32_s8 (int8x8_t a) +{ + return __builtin_shuffle (a, (uint8x8_t) { 3, 2, 1, 0, 7, 6, 5, 4 }); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev32_s16 (int16x4_t a) +{ + return __builtin_shuffle (a, (uint16x4_t) { 1, 0, 3, 2 }); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev32_u8 (uint8x8_t a) +{ + return __builtin_shuffle (a, (uint8x8_t) { 3, 2, 1, 0, 7, 6, 5, 4 }); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev32_u16 (uint16x4_t a) +{ + return __builtin_shuffle (a, (uint16x4_t) { 1, 0, 3, 2 }); +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev32q_p8 (poly8x16_t a) +{ + return __builtin_shuffle (a, + (uint8x16_t) { 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12 }); +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev32q_p16 (poly16x8_t a) +{ + return __builtin_shuffle (a, (uint16x8_t) { 1, 0, 3, 2, 5, 4, 7, 6 }); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev32q_s8 (int8x16_t a) +{ + return __builtin_shuffle (a, + (uint8x16_t) { 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12 }); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev32q_s16 (int16x8_t a) +{ + return __builtin_shuffle (a, (uint16x8_t) { 1, 0, 3, 2, 5, 4, 7, 6 }); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev32q_u8 (uint8x16_t a) +{ + return __builtin_shuffle (a, + (uint8x16_t) { 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12 }); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev32q_u16 (uint16x8_t a) +{ + return __builtin_shuffle (a, (uint16x8_t) { 1, 0, 3, 2, 5, 4, 7, 6 }); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev64_f16 (float16x4_t __a) +{ + return __builtin_shuffle (__a, (uint16x4_t) { 3, 2, 1, 0 }); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev64_f32 (float32x2_t a) +{ + return __builtin_shuffle (a, (uint32x2_t) { 1, 0 }); +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev64_p8 (poly8x8_t a) +{ + return __builtin_shuffle (a, (uint8x8_t) { 7, 6, 5, 4, 3, 2, 1, 0 }); +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev64_p16 (poly16x4_t a) +{ + return __builtin_shuffle (a, (uint16x4_t) { 3, 2, 1, 0 }); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev64_s8 (int8x8_t a) +{ + return __builtin_shuffle (a, (uint8x8_t) { 7, 6, 5, 4, 3, 2, 1, 0 }); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev64_s16 (int16x4_t a) +{ + return __builtin_shuffle (a, (uint16x4_t) { 3, 2, 1, 0 }); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev64_s32 (int32x2_t a) +{ + return __builtin_shuffle (a, (uint32x2_t) { 1, 0 }); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev64_u8 (uint8x8_t a) +{ + return __builtin_shuffle (a, (uint8x8_t) { 7, 6, 5, 4, 3, 2, 1, 0 }); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev64_u16 (uint16x4_t a) +{ + return __builtin_shuffle (a, (uint16x4_t) { 3, 2, 1, 0 }); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev64_u32 (uint32x2_t a) +{ + return __builtin_shuffle (a, (uint32x2_t) { 1, 0 }); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev64q_f16 (float16x8_t __a) +{ + return __builtin_shuffle (__a, (uint16x8_t) { 3, 2, 1, 0, 7, 6, 5, 4 }); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev64q_f32 (float32x4_t a) +{ + return __builtin_shuffle (a, (uint32x4_t) { 1, 0, 3, 2 }); +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev64q_p8 (poly8x16_t a) +{ + return __builtin_shuffle (a, + (uint8x16_t) { 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8 }); +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev64q_p16 (poly16x8_t a) +{ + return __builtin_shuffle (a, (uint16x8_t) { 3, 2, 1, 0, 7, 6, 5, 4 }); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev64q_s8 (int8x16_t a) +{ + return __builtin_shuffle (a, + (uint8x16_t) { 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8 }); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev64q_s16 (int16x8_t a) +{ + return __builtin_shuffle (a, (uint16x8_t) { 3, 2, 1, 0, 7, 6, 5, 4 }); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev64q_s32 (int32x4_t a) +{ + return __builtin_shuffle (a, (uint32x4_t) { 1, 0, 3, 2 }); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev64q_u8 (uint8x16_t a) +{ + return __builtin_shuffle (a, + (uint8x16_t) { 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8 }); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev64q_u16 (uint16x8_t a) +{ + return __builtin_shuffle (a, (uint16x8_t) { 3, 2, 1, 0, 7, 6, 5, 4 }); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrev64q_u32 (uint32x4_t a) +{ + return __builtin_shuffle (a, (uint32x4_t) { 1, 0, 3, 2 }); +} + +/* vrnd */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrnd_f32 (float32x2_t __a) +{ + return __builtin_aarch64_btruncv2sf (__a); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrnd_f64 (float64x1_t __a) +{ + return vset_lane_f64 (__builtin_trunc (vget_lane_f64 (__a, 0)), __a, 0); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndq_f32 (float32x4_t __a) +{ + return __builtin_aarch64_btruncv4sf (__a); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndq_f64 (float64x2_t __a) +{ + return __builtin_aarch64_btruncv2df (__a); +} + +/* vrnda */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrnda_f32 (float32x2_t __a) +{ + return __builtin_aarch64_roundv2sf (__a); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrnda_f64 (float64x1_t __a) +{ + return vset_lane_f64 (__builtin_round (vget_lane_f64 (__a, 0)), __a, 0); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndaq_f32 (float32x4_t __a) +{ + return __builtin_aarch64_roundv4sf (__a); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndaq_f64 (float64x2_t __a) +{ + return __builtin_aarch64_roundv2df (__a); +} + +/* vrndi */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndi_f32 (float32x2_t __a) +{ + return __builtin_aarch64_nearbyintv2sf (__a); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndi_f64 (float64x1_t __a) +{ + return vset_lane_f64 (__builtin_nearbyint (vget_lane_f64 (__a, 0)), __a, 0); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndiq_f32 (float32x4_t __a) +{ + return __builtin_aarch64_nearbyintv4sf (__a); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndiq_f64 (float64x2_t __a) +{ + return __builtin_aarch64_nearbyintv2df (__a); +} + +/* vrndm */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndm_f32 (float32x2_t __a) +{ + return __builtin_aarch64_floorv2sf (__a); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndm_f64 (float64x1_t __a) +{ + return vset_lane_f64 (__builtin_floor (vget_lane_f64 (__a, 0)), __a, 0); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndmq_f32 (float32x4_t __a) +{ + return __builtin_aarch64_floorv4sf (__a); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndmq_f64 (float64x2_t __a) +{ + return __builtin_aarch64_floorv2df (__a); +} + +/* vrndn */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndn_f32 (float32x2_t __a) +{ + return __builtin_aarch64_frintnv2sf (__a); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndn_f64 (float64x1_t __a) +{ + return (float64x1_t) {__builtin_aarch64_frintndf (__a[0])}; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndnq_f32 (float32x4_t __a) +{ + return __builtin_aarch64_frintnv4sf (__a); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndnq_f64 (float64x2_t __a) +{ + return __builtin_aarch64_frintnv2df (__a); +} + +/* vrndp */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndp_f32 (float32x2_t __a) +{ + return __builtin_aarch64_ceilv2sf (__a); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndp_f64 (float64x1_t __a) +{ + return vset_lane_f64 (__builtin_ceil (vget_lane_f64 (__a, 0)), __a, 0); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndpq_f32 (float32x4_t __a) +{ + return __builtin_aarch64_ceilv4sf (__a); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndpq_f64 (float64x2_t __a) +{ + return __builtin_aarch64_ceilv2df (__a); +} + +/* vrndx */ + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndx_f32 (float32x2_t __a) +{ + return __builtin_aarch64_rintv2sf (__a); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndx_f64 (float64x1_t __a) +{ + return vset_lane_f64 (__builtin_rint (vget_lane_f64 (__a, 0)), __a, 0); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndxq_f32 (float32x4_t __a) +{ + return __builtin_aarch64_rintv4sf (__a); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndxq_f64 (float64x2_t __a) +{ + return __builtin_aarch64_rintv2df (__a); +} + +/* vrshl */ + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshl_s8 (int8x8_t __a, int8x8_t __b) +{ + return (int8x8_t) __builtin_aarch64_srshlv8qi (__a, __b); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshl_s16 (int16x4_t __a, int16x4_t __b) +{ + return (int16x4_t) __builtin_aarch64_srshlv4hi (__a, __b); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshl_s32 (int32x2_t __a, int32x2_t __b) +{ + return (int32x2_t) __builtin_aarch64_srshlv2si (__a, __b); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshl_s64 (int64x1_t __a, int64x1_t __b) +{ + return (int64x1_t) {__builtin_aarch64_srshldi (__a[0], __b[0])}; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshl_u8 (uint8x8_t __a, int8x8_t __b) +{ + return __builtin_aarch64_urshlv8qi_uus (__a, __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshl_u16 (uint16x4_t __a, int16x4_t __b) +{ + return __builtin_aarch64_urshlv4hi_uus (__a, __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshl_u32 (uint32x2_t __a, int32x2_t __b) +{ + return __builtin_aarch64_urshlv2si_uus (__a, __b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshl_u64 (uint64x1_t __a, int64x1_t __b) +{ + return (uint64x1_t) {__builtin_aarch64_urshldi_uus (__a[0], __b[0])}; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshlq_s8 (int8x16_t __a, int8x16_t __b) +{ + return (int8x16_t) __builtin_aarch64_srshlv16qi (__a, __b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshlq_s16 (int16x8_t __a, int16x8_t __b) +{ + return (int16x8_t) __builtin_aarch64_srshlv8hi (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshlq_s32 (int32x4_t __a, int32x4_t __b) +{ + return (int32x4_t) __builtin_aarch64_srshlv4si (__a, __b); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshlq_s64 (int64x2_t __a, int64x2_t __b) +{ + return (int64x2_t) __builtin_aarch64_srshlv2di (__a, __b); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshlq_u8 (uint8x16_t __a, int8x16_t __b) +{ + return __builtin_aarch64_urshlv16qi_uus (__a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshlq_u16 (uint16x8_t __a, int16x8_t __b) +{ + return __builtin_aarch64_urshlv8hi_uus (__a, __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshlq_u32 (uint32x4_t __a, int32x4_t __b) +{ + return __builtin_aarch64_urshlv4si_uus (__a, __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshlq_u64 (uint64x2_t __a, int64x2_t __b) +{ + return __builtin_aarch64_urshlv2di_uus (__a, __b); +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshld_s64 (int64_t __a, int64_t __b) +{ + return __builtin_aarch64_srshldi (__a, __b); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshld_u64 (uint64_t __a, int64_t __b) +{ + return __builtin_aarch64_urshldi_uus (__a, __b); +} + +/* vrshr */ + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshr_n_s8 (int8x8_t __a, const int __b) +{ + return (int8x8_t) __builtin_aarch64_srshr_nv8qi (__a, __b); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshr_n_s16 (int16x4_t __a, const int __b) +{ + return (int16x4_t) __builtin_aarch64_srshr_nv4hi (__a, __b); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshr_n_s32 (int32x2_t __a, const int __b) +{ + return (int32x2_t) __builtin_aarch64_srshr_nv2si (__a, __b); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshr_n_s64 (int64x1_t __a, const int __b) +{ + return (int64x1_t) {__builtin_aarch64_srshr_ndi (__a[0], __b)}; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshr_n_u8 (uint8x8_t __a, const int __b) +{ + return __builtin_aarch64_urshr_nv8qi_uus (__a, __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshr_n_u16 (uint16x4_t __a, const int __b) +{ + return __builtin_aarch64_urshr_nv4hi_uus (__a, __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshr_n_u32 (uint32x2_t __a, const int __b) +{ + return __builtin_aarch64_urshr_nv2si_uus (__a, __b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshr_n_u64 (uint64x1_t __a, const int __b) +{ + return (uint64x1_t) {__builtin_aarch64_urshr_ndi_uus (__a[0], __b)}; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshrq_n_s8 (int8x16_t __a, const int __b) +{ + return (int8x16_t) __builtin_aarch64_srshr_nv16qi (__a, __b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshrq_n_s16 (int16x8_t __a, const int __b) +{ + return (int16x8_t) __builtin_aarch64_srshr_nv8hi (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshrq_n_s32 (int32x4_t __a, const int __b) +{ + return (int32x4_t) __builtin_aarch64_srshr_nv4si (__a, __b); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshrq_n_s64 (int64x2_t __a, const int __b) +{ + return (int64x2_t) __builtin_aarch64_srshr_nv2di (__a, __b); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshrq_n_u8 (uint8x16_t __a, const int __b) +{ + return __builtin_aarch64_urshr_nv16qi_uus (__a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshrq_n_u16 (uint16x8_t __a, const int __b) +{ + return __builtin_aarch64_urshr_nv8hi_uus (__a, __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshrq_n_u32 (uint32x4_t __a, const int __b) +{ + return __builtin_aarch64_urshr_nv4si_uus (__a, __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshrq_n_u64 (uint64x2_t __a, const int __b) +{ + return __builtin_aarch64_urshr_nv2di_uus (__a, __b); +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshrd_n_s64 (int64_t __a, const int __b) +{ + return __builtin_aarch64_srshr_ndi (__a, __b); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrshrd_n_u64 (uint64_t __a, const int __b) +{ + return __builtin_aarch64_urshr_ndi_uus (__a, __b); +} + +/* vrsqrte. */ + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsqrtes_f32 (float32_t __a) +{ + return __builtin_aarch64_rsqrtesf (__a); +} + +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsqrted_f64 (float64_t __a) +{ + return __builtin_aarch64_rsqrtedf (__a); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsqrte_f32 (float32x2_t __a) +{ + return __builtin_aarch64_rsqrtev2sf (__a); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsqrte_f64 (float64x1_t __a) +{ + return (float64x1_t) {vrsqrted_f64 (vget_lane_f64 (__a, 0))}; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsqrteq_f32 (float32x4_t __a) +{ + return __builtin_aarch64_rsqrtev4sf (__a); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsqrteq_f64 (float64x2_t __a) +{ + return __builtin_aarch64_rsqrtev2df (__a); +} + +/* vrsqrts. */ + +__extension__ extern __inline float32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsqrtss_f32 (float32_t __a, float32_t __b) +{ + return __builtin_aarch64_rsqrtssf (__a, __b); +} + +__extension__ extern __inline float64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsqrtsd_f64 (float64_t __a, float64_t __b) +{ + return __builtin_aarch64_rsqrtsdf (__a, __b); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsqrts_f32 (float32x2_t __a, float32x2_t __b) +{ + return __builtin_aarch64_rsqrtsv2sf (__a, __b); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsqrts_f64 (float64x1_t __a, float64x1_t __b) +{ + return (float64x1_t) {vrsqrtsd_f64 (vget_lane_f64 (__a, 0), + vget_lane_f64 (__b, 0))}; +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsqrtsq_f32 (float32x4_t __a, float32x4_t __b) +{ + return __builtin_aarch64_rsqrtsv4sf (__a, __b); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsqrtsq_f64 (float64x2_t __a, float64x2_t __b) +{ + return __builtin_aarch64_rsqrtsv2df (__a, __b); +} + +/* vrsra */ + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsra_n_s8 (int8x8_t __a, int8x8_t __b, const int __c) +{ + return (int8x8_t) __builtin_aarch64_srsra_nv8qi (__a, __b, __c); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsra_n_s16 (int16x4_t __a, int16x4_t __b, const int __c) +{ + return (int16x4_t) __builtin_aarch64_srsra_nv4hi (__a, __b, __c); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsra_n_s32 (int32x2_t __a, int32x2_t __b, const int __c) +{ + return (int32x2_t) __builtin_aarch64_srsra_nv2si (__a, __b, __c); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsra_n_s64 (int64x1_t __a, int64x1_t __b, const int __c) +{ + return (int64x1_t) {__builtin_aarch64_srsra_ndi (__a[0], __b[0], __c)}; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsra_n_u8 (uint8x8_t __a, uint8x8_t __b, const int __c) +{ + return __builtin_aarch64_ursra_nv8qi_uuus (__a, __b, __c); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsra_n_u16 (uint16x4_t __a, uint16x4_t __b, const int __c) +{ + return __builtin_aarch64_ursra_nv4hi_uuus (__a, __b, __c); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsra_n_u32 (uint32x2_t __a, uint32x2_t __b, const int __c) +{ + return __builtin_aarch64_ursra_nv2si_uuus (__a, __b, __c); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsra_n_u64 (uint64x1_t __a, uint64x1_t __b, const int __c) +{ + return (uint64x1_t) {__builtin_aarch64_ursra_ndi_uuus (__a[0], __b[0], __c)}; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsraq_n_s8 (int8x16_t __a, int8x16_t __b, const int __c) +{ + return (int8x16_t) __builtin_aarch64_srsra_nv16qi (__a, __b, __c); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsraq_n_s16 (int16x8_t __a, int16x8_t __b, const int __c) +{ + return (int16x8_t) __builtin_aarch64_srsra_nv8hi (__a, __b, __c); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsraq_n_s32 (int32x4_t __a, int32x4_t __b, const int __c) +{ + return (int32x4_t) __builtin_aarch64_srsra_nv4si (__a, __b, __c); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsraq_n_s64 (int64x2_t __a, int64x2_t __b, const int __c) +{ + return (int64x2_t) __builtin_aarch64_srsra_nv2di (__a, __b, __c); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsraq_n_u8 (uint8x16_t __a, uint8x16_t __b, const int __c) +{ + return __builtin_aarch64_ursra_nv16qi_uuus (__a, __b, __c); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsraq_n_u16 (uint16x8_t __a, uint16x8_t __b, const int __c) +{ + return __builtin_aarch64_ursra_nv8hi_uuus (__a, __b, __c); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsraq_n_u32 (uint32x4_t __a, uint32x4_t __b, const int __c) +{ + return __builtin_aarch64_ursra_nv4si_uuus (__a, __b, __c); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsraq_n_u64 (uint64x2_t __a, uint64x2_t __b, const int __c) +{ + return __builtin_aarch64_ursra_nv2di_uuus (__a, __b, __c); +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsrad_n_s64 (int64_t __a, int64_t __b, const int __c) +{ + return __builtin_aarch64_srsra_ndi (__a, __b, __c); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsrad_n_u64 (uint64_t __a, uint64_t __b, const int __c) +{ + return __builtin_aarch64_ursra_ndi_uuus (__a, __b, __c); +} + +#pragma GCC push_options +#pragma GCC target ("+nothing+crypto") + +/* vsha1 */ + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsha1cq_u32 (uint32x4_t hash_abcd, uint32_t hash_e, uint32x4_t wk) +{ + return __builtin_aarch64_crypto_sha1cv4si_uuuu (hash_abcd, hash_e, wk); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsha1mq_u32 (uint32x4_t hash_abcd, uint32_t hash_e, uint32x4_t wk) +{ + return __builtin_aarch64_crypto_sha1mv4si_uuuu (hash_abcd, hash_e, wk); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsha1pq_u32 (uint32x4_t hash_abcd, uint32_t hash_e, uint32x4_t wk) +{ + return __builtin_aarch64_crypto_sha1pv4si_uuuu (hash_abcd, hash_e, wk); +} + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsha1h_u32 (uint32_t hash_e) +{ + return __builtin_aarch64_crypto_sha1hsi_uu (hash_e); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsha1su0q_u32 (uint32x4_t w0_3, uint32x4_t w4_7, uint32x4_t w8_11) +{ + return __builtin_aarch64_crypto_sha1su0v4si_uuuu (w0_3, w4_7, w8_11); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsha1su1q_u32 (uint32x4_t tw0_3, uint32x4_t w12_15) +{ + return __builtin_aarch64_crypto_sha1su1v4si_uuu (tw0_3, w12_15); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsha256hq_u32 (uint32x4_t hash_abcd, uint32x4_t hash_efgh, uint32x4_t wk) +{ + return __builtin_aarch64_crypto_sha256hv4si_uuuu (hash_abcd, hash_efgh, wk); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsha256h2q_u32 (uint32x4_t hash_efgh, uint32x4_t hash_abcd, uint32x4_t wk) +{ + return __builtin_aarch64_crypto_sha256h2v4si_uuuu (hash_efgh, hash_abcd, wk); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsha256su0q_u32 (uint32x4_t w0_3, uint32x4_t w4_7) +{ + return __builtin_aarch64_crypto_sha256su0v4si_uuu (w0_3, w4_7); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsha256su1q_u32 (uint32x4_t tw0_3, uint32x4_t w8_11, uint32x4_t w12_15) +{ + return __builtin_aarch64_crypto_sha256su1v4si_uuuu (tw0_3, w8_11, w12_15); +} + +__extension__ extern __inline poly128_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmull_p64 (poly64_t a, poly64_t b) +{ + return + __builtin_aarch64_crypto_pmulldi_ppp (a, b); +} + +__extension__ extern __inline poly128_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmull_high_p64 (poly64x2_t a, poly64x2_t b) +{ + return __builtin_aarch64_crypto_pmullv2di_ppp (a, b); +} + +#pragma GCC pop_options + +/* vshl */ + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshl_n_s8 (int8x8_t __a, const int __b) +{ + return (int8x8_t) __builtin_aarch64_ashlv8qi (__a, __b); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshl_n_s16 (int16x4_t __a, const int __b) +{ + return (int16x4_t) __builtin_aarch64_ashlv4hi (__a, __b); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshl_n_s32 (int32x2_t __a, const int __b) +{ + return (int32x2_t) __builtin_aarch64_ashlv2si (__a, __b); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshl_n_s64 (int64x1_t __a, const int __b) +{ + return (int64x1_t) {__builtin_aarch64_ashldi (__a[0], __b)}; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshl_n_u8 (uint8x8_t __a, const int __b) +{ + return (uint8x8_t) __builtin_aarch64_ashlv8qi ((int8x8_t) __a, __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshl_n_u16 (uint16x4_t __a, const int __b) +{ + return (uint16x4_t) __builtin_aarch64_ashlv4hi ((int16x4_t) __a, __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshl_n_u32 (uint32x2_t __a, const int __b) +{ + return (uint32x2_t) __builtin_aarch64_ashlv2si ((int32x2_t) __a, __b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshl_n_u64 (uint64x1_t __a, const int __b) +{ + return (uint64x1_t) {__builtin_aarch64_ashldi ((int64_t) __a[0], __b)}; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshlq_n_s8 (int8x16_t __a, const int __b) +{ + return (int8x16_t) __builtin_aarch64_ashlv16qi (__a, __b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshlq_n_s16 (int16x8_t __a, const int __b) +{ + return (int16x8_t) __builtin_aarch64_ashlv8hi (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshlq_n_s32 (int32x4_t __a, const int __b) +{ + return (int32x4_t) __builtin_aarch64_ashlv4si (__a, __b); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshlq_n_s64 (int64x2_t __a, const int __b) +{ + return (int64x2_t) __builtin_aarch64_ashlv2di (__a, __b); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshlq_n_u8 (uint8x16_t __a, const int __b) +{ + return (uint8x16_t) __builtin_aarch64_ashlv16qi ((int8x16_t) __a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshlq_n_u16 (uint16x8_t __a, const int __b) +{ + return (uint16x8_t) __builtin_aarch64_ashlv8hi ((int16x8_t) __a, __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshlq_n_u32 (uint32x4_t __a, const int __b) +{ + return (uint32x4_t) __builtin_aarch64_ashlv4si ((int32x4_t) __a, __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshlq_n_u64 (uint64x2_t __a, const int __b) +{ + return (uint64x2_t) __builtin_aarch64_ashlv2di ((int64x2_t) __a, __b); +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshld_n_s64 (int64_t __a, const int __b) +{ + return __builtin_aarch64_ashldi (__a, __b); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshld_n_u64 (uint64_t __a, const int __b) +{ + return (uint64_t) __builtin_aarch64_ashldi (__a, __b); +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshl_s8 (int8x8_t __a, int8x8_t __b) +{ + return __builtin_aarch64_sshlv8qi (__a, __b); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshl_s16 (int16x4_t __a, int16x4_t __b) +{ + return __builtin_aarch64_sshlv4hi (__a, __b); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshl_s32 (int32x2_t __a, int32x2_t __b) +{ + return __builtin_aarch64_sshlv2si (__a, __b); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshl_s64 (int64x1_t __a, int64x1_t __b) +{ + return (int64x1_t) {__builtin_aarch64_sshldi (__a[0], __b[0])}; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshl_u8 (uint8x8_t __a, int8x8_t __b) +{ + return __builtin_aarch64_ushlv8qi_uus (__a, __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshl_u16 (uint16x4_t __a, int16x4_t __b) +{ + return __builtin_aarch64_ushlv4hi_uus (__a, __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshl_u32 (uint32x2_t __a, int32x2_t __b) +{ + return __builtin_aarch64_ushlv2si_uus (__a, __b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshl_u64 (uint64x1_t __a, int64x1_t __b) +{ + return (uint64x1_t) {__builtin_aarch64_ushldi_uus (__a[0], __b[0])}; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshlq_s8 (int8x16_t __a, int8x16_t __b) +{ + return __builtin_aarch64_sshlv16qi (__a, __b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshlq_s16 (int16x8_t __a, int16x8_t __b) +{ + return __builtin_aarch64_sshlv8hi (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshlq_s32 (int32x4_t __a, int32x4_t __b) +{ + return __builtin_aarch64_sshlv4si (__a, __b); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshlq_s64 (int64x2_t __a, int64x2_t __b) +{ + return __builtin_aarch64_sshlv2di (__a, __b); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshlq_u8 (uint8x16_t __a, int8x16_t __b) +{ + return __builtin_aarch64_ushlv16qi_uus (__a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshlq_u16 (uint16x8_t __a, int16x8_t __b) +{ + return __builtin_aarch64_ushlv8hi_uus (__a, __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshlq_u32 (uint32x4_t __a, int32x4_t __b) +{ + return __builtin_aarch64_ushlv4si_uus (__a, __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshlq_u64 (uint64x2_t __a, int64x2_t __b) +{ + return __builtin_aarch64_ushlv2di_uus (__a, __b); +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshld_s64 (int64_t __a, int64_t __b) +{ + return __builtin_aarch64_sshldi (__a, __b); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshld_u64 (uint64_t __a, uint64_t __b) +{ + return __builtin_aarch64_ushldi_uus (__a, __b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshll_high_n_s8 (int8x16_t __a, const int __b) +{ + return __builtin_aarch64_sshll2_nv16qi (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshll_high_n_s16 (int16x8_t __a, const int __b) +{ + return __builtin_aarch64_sshll2_nv8hi (__a, __b); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshll_high_n_s32 (int32x4_t __a, const int __b) +{ + return __builtin_aarch64_sshll2_nv4si (__a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshll_high_n_u8 (uint8x16_t __a, const int __b) +{ + return (uint16x8_t) __builtin_aarch64_ushll2_nv16qi ((int8x16_t) __a, __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshll_high_n_u16 (uint16x8_t __a, const int __b) +{ + return (uint32x4_t) __builtin_aarch64_ushll2_nv8hi ((int16x8_t) __a, __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshll_high_n_u32 (uint32x4_t __a, const int __b) +{ + return (uint64x2_t) __builtin_aarch64_ushll2_nv4si ((int32x4_t) __a, __b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshll_n_s8 (int8x8_t __a, const int __b) +{ + return __builtin_aarch64_sshll_nv8qi (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshll_n_s16 (int16x4_t __a, const int __b) +{ + return __builtin_aarch64_sshll_nv4hi (__a, __b); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshll_n_s32 (int32x2_t __a, const int __b) +{ + return __builtin_aarch64_sshll_nv2si (__a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshll_n_u8 (uint8x8_t __a, const int __b) +{ + return __builtin_aarch64_ushll_nv8qi_uus (__a, __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshll_n_u16 (uint16x4_t __a, const int __b) +{ + return __builtin_aarch64_ushll_nv4hi_uus (__a, __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshll_n_u32 (uint32x2_t __a, const int __b) +{ + return __builtin_aarch64_ushll_nv2si_uus (__a, __b); +} + +/* vshr */ + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshr_n_s8 (int8x8_t __a, const int __b) +{ + return (int8x8_t) __builtin_aarch64_ashrv8qi (__a, __b); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshr_n_s16 (int16x4_t __a, const int __b) +{ + return (int16x4_t) __builtin_aarch64_ashrv4hi (__a, __b); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshr_n_s32 (int32x2_t __a, const int __b) +{ + return (int32x2_t) __builtin_aarch64_ashrv2si (__a, __b); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshr_n_s64 (int64x1_t __a, const int __b) +{ + return (int64x1_t) {__builtin_aarch64_ashr_simddi (__a[0], __b)}; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshr_n_u8 (uint8x8_t __a, const int __b) +{ + return (uint8x8_t) __builtin_aarch64_lshrv8qi ((int8x8_t) __a, __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshr_n_u16 (uint16x4_t __a, const int __b) +{ + return (uint16x4_t) __builtin_aarch64_lshrv4hi ((int16x4_t) __a, __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshr_n_u32 (uint32x2_t __a, const int __b) +{ + return (uint32x2_t) __builtin_aarch64_lshrv2si ((int32x2_t) __a, __b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshr_n_u64 (uint64x1_t __a, const int __b) +{ + return (uint64x1_t) {__builtin_aarch64_lshr_simddi_uus ( __a[0], __b)}; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshrq_n_s8 (int8x16_t __a, const int __b) +{ + return (int8x16_t) __builtin_aarch64_ashrv16qi (__a, __b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshrq_n_s16 (int16x8_t __a, const int __b) +{ + return (int16x8_t) __builtin_aarch64_ashrv8hi (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshrq_n_s32 (int32x4_t __a, const int __b) +{ + return (int32x4_t) __builtin_aarch64_ashrv4si (__a, __b); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshrq_n_s64 (int64x2_t __a, const int __b) +{ + return (int64x2_t) __builtin_aarch64_ashrv2di (__a, __b); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshrq_n_u8 (uint8x16_t __a, const int __b) +{ + return (uint8x16_t) __builtin_aarch64_lshrv16qi ((int8x16_t) __a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshrq_n_u16 (uint16x8_t __a, const int __b) +{ + return (uint16x8_t) __builtin_aarch64_lshrv8hi ((int16x8_t) __a, __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshrq_n_u32 (uint32x4_t __a, const int __b) +{ + return (uint32x4_t) __builtin_aarch64_lshrv4si ((int32x4_t) __a, __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshrq_n_u64 (uint64x2_t __a, const int __b) +{ + return (uint64x2_t) __builtin_aarch64_lshrv2di ((int64x2_t) __a, __b); +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshrd_n_s64 (int64_t __a, const int __b) +{ + return __builtin_aarch64_ashr_simddi (__a, __b); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vshrd_n_u64 (uint64_t __a, const int __b) +{ + return __builtin_aarch64_lshr_simddi_uus (__a, __b); +} + +/* vsli */ + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsli_n_s8 (int8x8_t __a, int8x8_t __b, const int __c) +{ + return (int8x8_t) __builtin_aarch64_ssli_nv8qi (__a, __b, __c); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsli_n_s16 (int16x4_t __a, int16x4_t __b, const int __c) +{ + return (int16x4_t) __builtin_aarch64_ssli_nv4hi (__a, __b, __c); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsli_n_s32 (int32x2_t __a, int32x2_t __b, const int __c) +{ + return (int32x2_t) __builtin_aarch64_ssli_nv2si (__a, __b, __c); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsli_n_s64 (int64x1_t __a, int64x1_t __b, const int __c) +{ + return (int64x1_t) {__builtin_aarch64_ssli_ndi (__a[0], __b[0], __c)}; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsli_n_u8 (uint8x8_t __a, uint8x8_t __b, const int __c) +{ + return __builtin_aarch64_usli_nv8qi_uuus (__a, __b, __c); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsli_n_u16 (uint16x4_t __a, uint16x4_t __b, const int __c) +{ + return __builtin_aarch64_usli_nv4hi_uuus (__a, __b, __c); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsli_n_u32 (uint32x2_t __a, uint32x2_t __b, const int __c) +{ + return __builtin_aarch64_usli_nv2si_uuus (__a, __b, __c); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsli_n_u64 (uint64x1_t __a, uint64x1_t __b, const int __c) +{ + return (uint64x1_t) {__builtin_aarch64_usli_ndi_uuus (__a[0], __b[0], __c)}; +} + +__extension__ extern __inline poly64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsli_n_p64 (poly64x1_t __a, poly64x1_t __b, const int __c) +{ + return (poly64x1_t) {__builtin_aarch64_ssli_ndi_ppps (__a[0], __b[0], __c)}; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsliq_n_s8 (int8x16_t __a, int8x16_t __b, const int __c) +{ + return (int8x16_t) __builtin_aarch64_ssli_nv16qi (__a, __b, __c); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsliq_n_s16 (int16x8_t __a, int16x8_t __b, const int __c) +{ + return (int16x8_t) __builtin_aarch64_ssli_nv8hi (__a, __b, __c); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsliq_n_s32 (int32x4_t __a, int32x4_t __b, const int __c) +{ + return (int32x4_t) __builtin_aarch64_ssli_nv4si (__a, __b, __c); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsliq_n_s64 (int64x2_t __a, int64x2_t __b, const int __c) +{ + return (int64x2_t) __builtin_aarch64_ssli_nv2di (__a, __b, __c); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsliq_n_u8 (uint8x16_t __a, uint8x16_t __b, const int __c) +{ + return __builtin_aarch64_usli_nv16qi_uuus (__a, __b, __c); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsliq_n_u16 (uint16x8_t __a, uint16x8_t __b, const int __c) +{ + return __builtin_aarch64_usli_nv8hi_uuus (__a, __b, __c); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsliq_n_u32 (uint32x4_t __a, uint32x4_t __b, const int __c) +{ + return __builtin_aarch64_usli_nv4si_uuus (__a, __b, __c); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsliq_n_u64 (uint64x2_t __a, uint64x2_t __b, const int __c) +{ + return __builtin_aarch64_usli_nv2di_uuus (__a, __b, __c); +} + +__extension__ extern __inline poly64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsliq_n_p64 (poly64x2_t __a, poly64x2_t __b, const int __c) +{ + return __builtin_aarch64_ssli_nv2di_ppps (__a, __b, __c); +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vslid_n_s64 (int64_t __a, int64_t __b, const int __c) +{ + return __builtin_aarch64_ssli_ndi (__a, __b, __c); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vslid_n_u64 (uint64_t __a, uint64_t __b, const int __c) +{ + return __builtin_aarch64_usli_ndi_uuus (__a, __b, __c); +} + +/* vsqadd */ + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsqadd_u8 (uint8x8_t __a, int8x8_t __b) +{ + return __builtin_aarch64_usqaddv8qi_uus (__a, __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsqadd_u16 (uint16x4_t __a, int16x4_t __b) +{ + return __builtin_aarch64_usqaddv4hi_uus (__a, __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsqadd_u32 (uint32x2_t __a, int32x2_t __b) +{ + return __builtin_aarch64_usqaddv2si_uus (__a, __b); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsqadd_u64 (uint64x1_t __a, int64x1_t __b) +{ + return (uint64x1_t) {__builtin_aarch64_usqadddi_uus (__a[0], __b[0])}; +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsqaddq_u8 (uint8x16_t __a, int8x16_t __b) +{ + return __builtin_aarch64_usqaddv16qi_uus (__a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsqaddq_u16 (uint16x8_t __a, int16x8_t __b) +{ + return __builtin_aarch64_usqaddv8hi_uus (__a, __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsqaddq_u32 (uint32x4_t __a, int32x4_t __b) +{ + return __builtin_aarch64_usqaddv4si_uus (__a, __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsqaddq_u64 (uint64x2_t __a, int64x2_t __b) +{ + return __builtin_aarch64_usqaddv2di_uus (__a, __b); +} + +__extension__ extern __inline uint8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsqaddb_u8 (uint8_t __a, int8_t __b) +{ + return __builtin_aarch64_usqaddqi_uus (__a, __b); +} + +__extension__ extern __inline uint16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsqaddh_u16 (uint16_t __a, int16_t __b) +{ + return __builtin_aarch64_usqaddhi_uus (__a, __b); +} + +__extension__ extern __inline uint32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsqadds_u32 (uint32_t __a, int32_t __b) +{ + return __builtin_aarch64_usqaddsi_uus (__a, __b); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsqaddd_u64 (uint64_t __a, int64_t __b) +{ + return __builtin_aarch64_usqadddi_uus (__a, __b); +} + +/* vsqrt */ +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsqrt_f32 (float32x2_t a) +{ + return __builtin_aarch64_sqrtv2sf (a); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsqrtq_f32 (float32x4_t a) +{ + return __builtin_aarch64_sqrtv4sf (a); +} + +__extension__ extern __inline float64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsqrt_f64 (float64x1_t a) +{ + return (float64x1_t) { __builtin_aarch64_sqrtdf (a[0]) }; +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsqrtq_f64 (float64x2_t a) +{ + return __builtin_aarch64_sqrtv2df (a); +} + +/* vsra */ + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsra_n_s8 (int8x8_t __a, int8x8_t __b, const int __c) +{ + return (int8x8_t) __builtin_aarch64_ssra_nv8qi (__a, __b, __c); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsra_n_s16 (int16x4_t __a, int16x4_t __b, const int __c) +{ + return (int16x4_t) __builtin_aarch64_ssra_nv4hi (__a, __b, __c); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsra_n_s32 (int32x2_t __a, int32x2_t __b, const int __c) +{ + return (int32x2_t) __builtin_aarch64_ssra_nv2si (__a, __b, __c); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsra_n_s64 (int64x1_t __a, int64x1_t __b, const int __c) +{ + return (int64x1_t) {__builtin_aarch64_ssra_ndi (__a[0], __b[0], __c)}; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsra_n_u8 (uint8x8_t __a, uint8x8_t __b, const int __c) +{ + return __builtin_aarch64_usra_nv8qi_uuus (__a, __b, __c); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsra_n_u16 (uint16x4_t __a, uint16x4_t __b, const int __c) +{ + return __builtin_aarch64_usra_nv4hi_uuus (__a, __b, __c); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsra_n_u32 (uint32x2_t __a, uint32x2_t __b, const int __c) +{ + return __builtin_aarch64_usra_nv2si_uuus (__a, __b, __c); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsra_n_u64 (uint64x1_t __a, uint64x1_t __b, const int __c) +{ + return (uint64x1_t) {__builtin_aarch64_usra_ndi_uuus (__a[0], __b[0], __c)}; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsraq_n_s8 (int8x16_t __a, int8x16_t __b, const int __c) +{ + return (int8x16_t) __builtin_aarch64_ssra_nv16qi (__a, __b, __c); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsraq_n_s16 (int16x8_t __a, int16x8_t __b, const int __c) +{ + return (int16x8_t) __builtin_aarch64_ssra_nv8hi (__a, __b, __c); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsraq_n_s32 (int32x4_t __a, int32x4_t __b, const int __c) +{ + return (int32x4_t) __builtin_aarch64_ssra_nv4si (__a, __b, __c); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsraq_n_s64 (int64x2_t __a, int64x2_t __b, const int __c) +{ + return (int64x2_t) __builtin_aarch64_ssra_nv2di (__a, __b, __c); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsraq_n_u8 (uint8x16_t __a, uint8x16_t __b, const int __c) +{ + return __builtin_aarch64_usra_nv16qi_uuus (__a, __b, __c); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsraq_n_u16 (uint16x8_t __a, uint16x8_t __b, const int __c) +{ + return __builtin_aarch64_usra_nv8hi_uuus (__a, __b, __c); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsraq_n_u32 (uint32x4_t __a, uint32x4_t __b, const int __c) +{ + return __builtin_aarch64_usra_nv4si_uuus (__a, __b, __c); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsraq_n_u64 (uint64x2_t __a, uint64x2_t __b, const int __c) +{ + return __builtin_aarch64_usra_nv2di_uuus (__a, __b, __c); +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsrad_n_s64 (int64_t __a, int64_t __b, const int __c) +{ + return __builtin_aarch64_ssra_ndi (__a, __b, __c); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsrad_n_u64 (uint64_t __a, uint64_t __b, const int __c) +{ + return __builtin_aarch64_usra_ndi_uuus (__a, __b, __c); +} + +/* vsri */ + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsri_n_s8 (int8x8_t __a, int8x8_t __b, const int __c) +{ + return (int8x8_t) __builtin_aarch64_ssri_nv8qi (__a, __b, __c); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsri_n_s16 (int16x4_t __a, int16x4_t __b, const int __c) +{ + return (int16x4_t) __builtin_aarch64_ssri_nv4hi (__a, __b, __c); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsri_n_s32 (int32x2_t __a, int32x2_t __b, const int __c) +{ + return (int32x2_t) __builtin_aarch64_ssri_nv2si (__a, __b, __c); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsri_n_s64 (int64x1_t __a, int64x1_t __b, const int __c) +{ + return (int64x1_t) {__builtin_aarch64_ssri_ndi (__a[0], __b[0], __c)}; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsri_n_u8 (uint8x8_t __a, uint8x8_t __b, const int __c) +{ + return __builtin_aarch64_usri_nv8qi_uuus (__a, __b, __c); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsri_n_u16 (uint16x4_t __a, uint16x4_t __b, const int __c) +{ + return __builtin_aarch64_usri_nv4hi_uuus (__a, __b, __c); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsri_n_u32 (uint32x2_t __a, uint32x2_t __b, const int __c) +{ + return __builtin_aarch64_usri_nv2si_uuus (__a, __b, __c); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsri_n_u64 (uint64x1_t __a, uint64x1_t __b, const int __c) +{ + return (uint64x1_t) {__builtin_aarch64_usri_ndi_uuus (__a[0], __b[0], __c)}; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsriq_n_s8 (int8x16_t __a, int8x16_t __b, const int __c) +{ + return (int8x16_t) __builtin_aarch64_ssri_nv16qi (__a, __b, __c); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsriq_n_s16 (int16x8_t __a, int16x8_t __b, const int __c) +{ + return (int16x8_t) __builtin_aarch64_ssri_nv8hi (__a, __b, __c); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsriq_n_s32 (int32x4_t __a, int32x4_t __b, const int __c) +{ + return (int32x4_t) __builtin_aarch64_ssri_nv4si (__a, __b, __c); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsriq_n_s64 (int64x2_t __a, int64x2_t __b, const int __c) +{ + return (int64x2_t) __builtin_aarch64_ssri_nv2di (__a, __b, __c); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsriq_n_u8 (uint8x16_t __a, uint8x16_t __b, const int __c) +{ + return __builtin_aarch64_usri_nv16qi_uuus (__a, __b, __c); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsriq_n_u16 (uint16x8_t __a, uint16x8_t __b, const int __c) +{ + return __builtin_aarch64_usri_nv8hi_uuus (__a, __b, __c); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsriq_n_u32 (uint32x4_t __a, uint32x4_t __b, const int __c) +{ + return __builtin_aarch64_usri_nv4si_uuus (__a, __b, __c); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsriq_n_u64 (uint64x2_t __a, uint64x2_t __b, const int __c) +{ + return __builtin_aarch64_usri_nv2di_uuus (__a, __b, __c); +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsrid_n_s64 (int64_t __a, int64_t __b, const int __c) +{ + return __builtin_aarch64_ssri_ndi (__a, __b, __c); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsrid_n_u64 (uint64_t __a, uint64_t __b, const int __c) +{ + return __builtin_aarch64_usri_ndi_uuus (__a, __b, __c); +} + +/* vst1 */ + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_f16 (float16_t *__a, float16x4_t __b) +{ + __builtin_aarch64_st1v4hf (__a, __b); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_f32 (float32_t *a, float32x2_t b) +{ + __builtin_aarch64_st1v2sf ((__builtin_aarch64_simd_sf *) a, b); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_f64 (float64_t *a, float64x1_t b) +{ + *a = b[0]; +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_p8 (poly8_t *a, poly8x8_t b) +{ + __builtin_aarch64_st1v8qi ((__builtin_aarch64_simd_qi *) a, + (int8x8_t) b); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_p16 (poly16_t *a, poly16x4_t b) +{ + __builtin_aarch64_st1v4hi ((__builtin_aarch64_simd_hi *) a, + (int16x4_t) b); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_p64 (poly64_t *a, poly64x1_t b) +{ + *a = b[0]; +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_s8 (int8_t *a, int8x8_t b) +{ + __builtin_aarch64_st1v8qi ((__builtin_aarch64_simd_qi *) a, b); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_s16 (int16_t *a, int16x4_t b) +{ + __builtin_aarch64_st1v4hi ((__builtin_aarch64_simd_hi *) a, b); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_s32 (int32_t *a, int32x2_t b) +{ + __builtin_aarch64_st1v2si ((__builtin_aarch64_simd_si *) a, b); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_s64 (int64_t *a, int64x1_t b) +{ + *a = b[0]; +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_u8 (uint8_t *a, uint8x8_t b) +{ + __builtin_aarch64_st1v8qi ((__builtin_aarch64_simd_qi *) a, + (int8x8_t) b); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_u16 (uint16_t *a, uint16x4_t b) +{ + __builtin_aarch64_st1v4hi ((__builtin_aarch64_simd_hi *) a, + (int16x4_t) b); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_u32 (uint32_t *a, uint32x2_t b) +{ + __builtin_aarch64_st1v2si ((__builtin_aarch64_simd_si *) a, + (int32x2_t) b); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_u64 (uint64_t *a, uint64x1_t b) +{ + *a = b[0]; +} + +/* vst1q */ + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_f16 (float16_t *__a, float16x8_t __b) +{ + __builtin_aarch64_st1v8hf (__a, __b); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_f32 (float32_t *a, float32x4_t b) +{ + __builtin_aarch64_st1v4sf ((__builtin_aarch64_simd_sf *) a, b); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_f64 (float64_t *a, float64x2_t b) +{ + __builtin_aarch64_st1v2df ((__builtin_aarch64_simd_df *) a, b); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_p8 (poly8_t *a, poly8x16_t b) +{ + __builtin_aarch64_st1v16qi ((__builtin_aarch64_simd_qi *) a, + (int8x16_t) b); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_p16 (poly16_t *a, poly16x8_t b) +{ + __builtin_aarch64_st1v8hi ((__builtin_aarch64_simd_hi *) a, + (int16x8_t) b); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_p64 (poly64_t *a, poly64x2_t b) +{ + __builtin_aarch64_st1v2di_sp ((__builtin_aarch64_simd_di *) a, + (poly64x2_t) b); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_s8 (int8_t *a, int8x16_t b) +{ + __builtin_aarch64_st1v16qi ((__builtin_aarch64_simd_qi *) a, b); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_s16 (int16_t *a, int16x8_t b) +{ + __builtin_aarch64_st1v8hi ((__builtin_aarch64_simd_hi *) a, b); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_s32 (int32_t *a, int32x4_t b) +{ + __builtin_aarch64_st1v4si ((__builtin_aarch64_simd_si *) a, b); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_s64 (int64_t *a, int64x2_t b) +{ + __builtin_aarch64_st1v2di ((__builtin_aarch64_simd_di *) a, b); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_u8 (uint8_t *a, uint8x16_t b) +{ + __builtin_aarch64_st1v16qi ((__builtin_aarch64_simd_qi *) a, + (int8x16_t) b); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_u16 (uint16_t *a, uint16x8_t b) +{ + __builtin_aarch64_st1v8hi ((__builtin_aarch64_simd_hi *) a, + (int16x8_t) b); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_u32 (uint32_t *a, uint32x4_t b) +{ + __builtin_aarch64_st1v4si ((__builtin_aarch64_simd_si *) a, + (int32x4_t) b); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_u64 (uint64_t *a, uint64x2_t b) +{ + __builtin_aarch64_st1v2di ((__builtin_aarch64_simd_di *) a, + (int64x2_t) b); +} + +/* vst1_lane */ + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_lane_f16 (float16_t *__a, float16x4_t __b, const int __lane) +{ + *__a = __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_lane_f32 (float32_t *__a, float32x2_t __b, const int __lane) +{ + *__a = __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_lane_f64 (float64_t *__a, float64x1_t __b, const int __lane) +{ + *__a = __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_lane_p8 (poly8_t *__a, poly8x8_t __b, const int __lane) +{ + *__a = __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_lane_p16 (poly16_t *__a, poly16x4_t __b, const int __lane) +{ + *__a = __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_lane_p64 (poly64_t *__a, poly64x1_t __b, const int __lane) +{ + *__a = __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_lane_s8 (int8_t *__a, int8x8_t __b, const int __lane) +{ + *__a = __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_lane_s16 (int16_t *__a, int16x4_t __b, const int __lane) +{ + *__a = __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_lane_s32 (int32_t *__a, int32x2_t __b, const int __lane) +{ + *__a = __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_lane_s64 (int64_t *__a, int64x1_t __b, const int __lane) +{ + *__a = __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_lane_u8 (uint8_t *__a, uint8x8_t __b, const int __lane) +{ + *__a = __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_lane_u16 (uint16_t *__a, uint16x4_t __b, const int __lane) +{ + *__a = __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_lane_u32 (uint32_t *__a, uint32x2_t __b, const int __lane) +{ + *__a = __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_lane_u64 (uint64_t *__a, uint64x1_t __b, const int __lane) +{ + *__a = __aarch64_vget_lane_any (__b, __lane); +} + +/* vst1q_lane */ + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_lane_f16 (float16_t *__a, float16x8_t __b, const int __lane) +{ + *__a = __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_lane_f32 (float32_t *__a, float32x4_t __b, const int __lane) +{ + *__a = __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_lane_f64 (float64_t *__a, float64x2_t __b, const int __lane) +{ + *__a = __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_lane_p8 (poly8_t *__a, poly8x16_t __b, const int __lane) +{ + *__a = __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_lane_p16 (poly16_t *__a, poly16x8_t __b, const int __lane) +{ + *__a = __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_lane_p64 (poly64_t *__a, poly64x2_t __b, const int __lane) +{ + *__a = __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_lane_s8 (int8_t *__a, int8x16_t __b, const int __lane) +{ + *__a = __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_lane_s16 (int16_t *__a, int16x8_t __b, const int __lane) +{ + *__a = __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_lane_s32 (int32_t *__a, int32x4_t __b, const int __lane) +{ + *__a = __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_lane_s64 (int64_t *__a, int64x2_t __b, const int __lane) +{ + *__a = __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_lane_u8 (uint8_t *__a, uint8x16_t __b, const int __lane) +{ + *__a = __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_lane_u16 (uint16_t *__a, uint16x8_t __b, const int __lane) +{ + *__a = __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_lane_u32 (uint32_t *__a, uint32x4_t __b, const int __lane) +{ + *__a = __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_lane_u64 (uint64_t *__a, uint64x2_t __b, const int __lane) +{ + *__a = __aarch64_vget_lane_any (__b, __lane); +} + +/* vst1x2 */ + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_s64_x2 (int64_t * __a, int64x1x2_t val) +{ + __builtin_aarch64_simd_oi __o; + int64x2x2_t temp; + temp.val[0] = vcombine_s64 (val.val[0], vcreate_s64 (__AARCH64_INT64_C (0))); + temp.val[1] = vcombine_s64 (val.val[1], vcreate_s64 (__AARCH64_INT64_C (0))); + __o = __builtin_aarch64_set_qregoiv2di (__o, (int64x2_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv2di (__o, (int64x2_t) temp.val[1], 1); + __builtin_aarch64_st1x2di ((__builtin_aarch64_simd_di *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_u64_x2 (uint64_t * __a, uint64x1x2_t val) +{ + __builtin_aarch64_simd_oi __o; + uint64x2x2_t temp; + temp.val[0] = vcombine_u64 (val.val[0], vcreate_u64 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_u64 (val.val[1], vcreate_u64 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregoiv2di (__o, (int64x2_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv2di (__o, (int64x2_t) temp.val[1], 1); + __builtin_aarch64_st1x2di ((__builtin_aarch64_simd_di *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_f64_x2 (float64_t * __a, float64x1x2_t val) +{ + __builtin_aarch64_simd_oi __o; + float64x2x2_t temp; + temp.val[0] = vcombine_f64 (val.val[0], vcreate_f64 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_f64 (val.val[1], vcreate_f64 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregoiv2df (__o, (float64x2_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv2df (__o, (float64x2_t) temp.val[1], 1); + __builtin_aarch64_st1x2df ((__builtin_aarch64_simd_df *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_s8_x2 (int8_t * __a, int8x8x2_t val) +{ + __builtin_aarch64_simd_oi __o; + int8x16x2_t temp; + temp.val[0] = vcombine_s8 (val.val[0], vcreate_s8 (__AARCH64_INT64_C (0))); + temp.val[1] = vcombine_s8 (val.val[1], vcreate_s8 (__AARCH64_INT64_C (0))); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t) temp.val[1], 1); + __builtin_aarch64_st1x2v8qi ((__builtin_aarch64_simd_qi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_p8_x2 (poly8_t * __a, poly8x8x2_t val) +{ + __builtin_aarch64_simd_oi __o; + poly8x16x2_t temp; + temp.val[0] = vcombine_p8 (val.val[0], vcreate_p8 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_p8 (val.val[1], vcreate_p8 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t) temp.val[1], 1); + __builtin_aarch64_st1x2v8qi ((__builtin_aarch64_simd_qi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_s16_x2 (int16_t * __a, int16x4x2_t val) +{ + __builtin_aarch64_simd_oi __o; + int16x8x2_t temp; + temp.val[0] = vcombine_s16 (val.val[0], vcreate_s16 (__AARCH64_INT64_C (0))); + temp.val[1] = vcombine_s16 (val.val[1], vcreate_s16 (__AARCH64_INT64_C (0))); + __o = __builtin_aarch64_set_qregoiv8hi (__o, (int16x8_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv8hi (__o, (int16x8_t) temp.val[1], 1); + __builtin_aarch64_st1x2v4hi ((__builtin_aarch64_simd_hi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_p16_x2 (poly16_t * __a, poly16x4x2_t val) +{ + __builtin_aarch64_simd_oi __o; + poly16x8x2_t temp; + temp.val[0] = vcombine_p16 (val.val[0], vcreate_p16 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_p16 (val.val[1], vcreate_p16 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregoiv8hi (__o, (int16x8_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv8hi (__o, (int16x8_t) temp.val[1], 1); + __builtin_aarch64_st1x2v4hi ((__builtin_aarch64_simd_hi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_s32_x2 (int32_t * __a, int32x2x2_t val) +{ + __builtin_aarch64_simd_oi __o; + int32x4x2_t temp; + temp.val[0] = vcombine_s32 (val.val[0], vcreate_s32 (__AARCH64_INT64_C (0))); + temp.val[1] = vcombine_s32 (val.val[1], vcreate_s32 (__AARCH64_INT64_C (0))); + __o = __builtin_aarch64_set_qregoiv4si (__o, (int32x4_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv4si (__o, (int32x4_t) temp.val[1], 1); + __builtin_aarch64_st1x2v2si ((__builtin_aarch64_simd_si *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_u8_x2 (uint8_t * __a, uint8x8x2_t val) +{ + __builtin_aarch64_simd_oi __o; + uint8x16x2_t temp; + temp.val[0] = vcombine_u8 (val.val[0], vcreate_u8 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_u8 (val.val[1], vcreate_u8 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t) temp.val[1], 1); + __builtin_aarch64_st1x2v8qi ((__builtin_aarch64_simd_qi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_u16_x2 (uint16_t * __a, uint16x4x2_t val) +{ + __builtin_aarch64_simd_oi __o; + uint16x8x2_t temp; + temp.val[0] = vcombine_u16 (val.val[0], vcreate_u16 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_u16 (val.val[1], vcreate_u16 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregoiv8hi (__o, (int16x8_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv8hi (__o, (int16x8_t) temp.val[1], 1); + __builtin_aarch64_st1x2v4hi ((__builtin_aarch64_simd_hi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_u32_x2 (uint32_t * __a, uint32x2x2_t val) +{ + __builtin_aarch64_simd_oi __o; + uint32x4x2_t temp; + temp.val[0] = vcombine_u32 (val.val[0], vcreate_u32 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_u32 (val.val[1], vcreate_u32 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregoiv4si (__o, (int32x4_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv4si (__o, (int32x4_t) temp.val[1], 1); + __builtin_aarch64_st1x2v2si ((__builtin_aarch64_simd_si *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_f16_x2 (float16_t * __a, float16x4x2_t val) +{ + __builtin_aarch64_simd_oi __o; + float16x8x2_t temp; + temp.val[0] = vcombine_f16 (val.val[0], vcreate_f16 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_f16 (val.val[1], vcreate_f16 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregoiv8hf (__o, temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv8hf (__o, temp.val[1], 1); + __builtin_aarch64_st1x2v4hf (__a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_f32_x2 (float32_t * __a, float32x2x2_t val) +{ + __builtin_aarch64_simd_oi __o; + float32x4x2_t temp; + temp.val[0] = vcombine_f32 (val.val[0], vcreate_f32 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_f32 (val.val[1], vcreate_f32 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregoiv4sf (__o, (float32x4_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv4sf (__o, (float32x4_t) temp.val[1], 1); + __builtin_aarch64_st1x2v2sf ((__builtin_aarch64_simd_sf *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_p64_x2 (poly64_t * __a, poly64x1x2_t val) +{ + __builtin_aarch64_simd_oi __o; + poly64x2x2_t temp; + temp.val[0] = vcombine_p64 (val.val[0], vcreate_p64 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_p64 (val.val[1], vcreate_p64 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregoiv2di_ssps (__o, + (poly64x2_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv2di_ssps (__o, + (poly64x2_t) temp.val[1], 1); + __builtin_aarch64_st1x2di ((__builtin_aarch64_simd_di *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_s8_x2 (int8_t * __a, int8x16x2_t val) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t) val.val[1], 1); + __builtin_aarch64_st1x2v16qi ((__builtin_aarch64_simd_qi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_p8_x2 (poly8_t * __a, poly8x16x2_t val) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t) val.val[1], 1); + __builtin_aarch64_st1x2v16qi ((__builtin_aarch64_simd_qi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_s16_x2 (int16_t * __a, int16x8x2_t val) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv8hi (__o, (int16x8_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregoiv8hi (__o, (int16x8_t) val.val[1], 1); + __builtin_aarch64_st1x2v8hi ((__builtin_aarch64_simd_hi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_p16_x2 (poly16_t * __a, poly16x8x2_t val) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv8hi (__o, (int16x8_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregoiv8hi (__o, (int16x8_t) val.val[1], 1); + __builtin_aarch64_st1x2v8hi ((__builtin_aarch64_simd_hi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_s32_x2 (int32_t * __a, int32x4x2_t val) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv4si (__o, (int32x4_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregoiv4si (__o, (int32x4_t) val.val[1], 1); + __builtin_aarch64_st1x2v4si ((__builtin_aarch64_simd_si *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_s64_x2 (int64_t * __a, int64x2x2_t val) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv2di (__o, (int64x2_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregoiv2di (__o, (int64x2_t) val.val[1], 1); + __builtin_aarch64_st1x2v2di ((__builtin_aarch64_simd_di *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_u8_x2 (uint8_t * __a, uint8x16x2_t val) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t) val.val[1], 1); + __builtin_aarch64_st1x2v16qi ((__builtin_aarch64_simd_qi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_u16_x2 (uint16_t * __a, uint16x8x2_t val) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv8hi (__o, (int16x8_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregoiv8hi (__o, (int16x8_t) val.val[1], 1); + __builtin_aarch64_st1x2v8hi ((__builtin_aarch64_simd_hi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_u32_x2 (uint32_t * __a, uint32x4x2_t val) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv4si (__o, (int32x4_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregoiv4si (__o, (int32x4_t) val.val[1], 1); + __builtin_aarch64_st1x2v4si ((__builtin_aarch64_simd_si *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_u64_x2 (uint64_t * __a, uint64x2x2_t val) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv2di (__o, (int64x2_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregoiv2di (__o, (int64x2_t) val.val[1], 1); + __builtin_aarch64_st1x2v2di ((__builtin_aarch64_simd_di *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_f16_x2 (float16_t * __a, float16x8x2_t val) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv8hf (__o, val.val[0], 0); + __o = __builtin_aarch64_set_qregoiv8hf (__o, val.val[1], 1); + __builtin_aarch64_st1x2v8hf (__a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_f32_x2 (float32_t * __a, float32x4x2_t val) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv4sf (__o, (float32x4_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregoiv4sf (__o, (float32x4_t) val.val[1], 1); + __builtin_aarch64_st1x2v4sf ((__builtin_aarch64_simd_sf *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_f64_x2 (float64_t * __a, float64x2x2_t val) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv2df (__o, (float64x2_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregoiv2df (__o, (float64x2_t) val.val[1], 1); + __builtin_aarch64_st1x2v2df ((__builtin_aarch64_simd_df *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_p64_x2 (poly64_t * __a, poly64x2x2_t val) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv2di_ssps (__o, + (poly64x2_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregoiv2di_ssps (__o, + (poly64x2_t) val.val[1], 1); + __builtin_aarch64_st1x2v2di ((__builtin_aarch64_simd_di *) __a, __o); +} + +/* vst1x3 */ + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_s64_x3 (int64_t * __a, int64x1x3_t val) +{ + __builtin_aarch64_simd_ci __o; + int64x2x3_t temp; + temp.val[0] = vcombine_s64 (val.val[0], vcreate_s64 (__AARCH64_INT64_C (0))); + temp.val[1] = vcombine_s64 (val.val[1], vcreate_s64 (__AARCH64_INT64_C (0))); + temp.val[2] = vcombine_s64 (val.val[2], vcreate_s64 (__AARCH64_INT64_C (0))); + __o = __builtin_aarch64_set_qregciv2di (__o, (int64x2_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregciv2di (__o, (int64x2_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregciv2di (__o, (int64x2_t) temp.val[2], 2); + __builtin_aarch64_st1x3di ((__builtin_aarch64_simd_di *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_u64_x3 (uint64_t * __a, uint64x1x3_t val) +{ + __builtin_aarch64_simd_ci __o; + uint64x2x3_t temp; + temp.val[0] = vcombine_u64 (val.val[0], vcreate_u64 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_u64 (val.val[1], vcreate_u64 (__AARCH64_UINT64_C (0))); + temp.val[2] = vcombine_u64 (val.val[2], vcreate_u64 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregciv2di (__o, (int64x2_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregciv2di (__o, (int64x2_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregciv2di (__o, (int64x2_t) temp.val[2], 2); + __builtin_aarch64_st1x3di ((__builtin_aarch64_simd_di *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_f64_x3 (float64_t * __a, float64x1x3_t val) +{ + __builtin_aarch64_simd_ci __o; + float64x2x3_t temp; + temp.val[0] = vcombine_f64 (val.val[0], vcreate_f64 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_f64 (val.val[1], vcreate_f64 (__AARCH64_UINT64_C (0))); + temp.val[2] = vcombine_f64 (val.val[2], vcreate_f64 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregciv2df (__o, (float64x2_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregciv2df (__o, (float64x2_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregciv2df (__o, (float64x2_t) temp.val[2], 2); + __builtin_aarch64_st1x3df ((__builtin_aarch64_simd_df *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_s8_x3 (int8_t * __a, int8x8x3_t val) +{ + __builtin_aarch64_simd_ci __o; + int8x16x3_t temp; + temp.val[0] = vcombine_s8 (val.val[0], vcreate_s8 (__AARCH64_INT64_C (0))); + temp.val[1] = vcombine_s8 (val.val[1], vcreate_s8 (__AARCH64_INT64_C (0))); + temp.val[2] = vcombine_s8 (val.val[2], vcreate_s8 (__AARCH64_INT64_C (0))); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) temp.val[2], 2); + __builtin_aarch64_st1x3v8qi ((__builtin_aarch64_simd_qi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_p8_x3 (poly8_t * __a, poly8x8x3_t val) +{ + __builtin_aarch64_simd_ci __o; + poly8x16x3_t temp; + temp.val[0] = vcombine_p8 (val.val[0], vcreate_p8 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_p8 (val.val[1], vcreate_p8 (__AARCH64_UINT64_C (0))); + temp.val[2] = vcombine_p8 (val.val[2], vcreate_p8 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) temp.val[2], 2); + __builtin_aarch64_st1x3v8qi ((__builtin_aarch64_simd_qi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_s16_x3 (int16_t * __a, int16x4x3_t val) +{ + __builtin_aarch64_simd_ci __o; + int16x8x3_t temp; + temp.val[0] = vcombine_s16 (val.val[0], vcreate_s16 (__AARCH64_INT64_C (0))); + temp.val[1] = vcombine_s16 (val.val[1], vcreate_s16 (__AARCH64_INT64_C (0))); + temp.val[2] = vcombine_s16 (val.val[2], vcreate_s16 (__AARCH64_INT64_C (0))); + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) temp.val[2], 2); + __builtin_aarch64_st1x3v4hi ((__builtin_aarch64_simd_hi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_p16_x3 (poly16_t * __a, poly16x4x3_t val) +{ + __builtin_aarch64_simd_ci __o; + poly16x8x3_t temp; + temp.val[0] = vcombine_p16 (val.val[0], vcreate_p16 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_p16 (val.val[1], vcreate_p16 (__AARCH64_UINT64_C (0))); + temp.val[2] = vcombine_p16 (val.val[2], vcreate_p16 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) temp.val[2], 2); + __builtin_aarch64_st1x3v4hi ((__builtin_aarch64_simd_hi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_s32_x3 (int32_t * __a, int32x2x3_t val) +{ + __builtin_aarch64_simd_ci __o; + int32x4x3_t temp; + temp.val[0] = vcombine_s32 (val.val[0], vcreate_s32 (__AARCH64_INT64_C (0))); + temp.val[1] = vcombine_s32 (val.val[1], vcreate_s32 (__AARCH64_INT64_C (0))); + temp.val[2] = vcombine_s32 (val.val[2], vcreate_s32 (__AARCH64_INT64_C (0))); + __o = __builtin_aarch64_set_qregciv4si (__o, (int32x4_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregciv4si (__o, (int32x4_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregciv4si (__o, (int32x4_t) temp.val[2], 2); + __builtin_aarch64_st1x3v2si ((__builtin_aarch64_simd_si *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_u8_x3 (uint8_t * __a, uint8x8x3_t val) +{ + __builtin_aarch64_simd_ci __o; + uint8x16x3_t temp; + temp.val[0] = vcombine_u8 (val.val[0], vcreate_u8 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_u8 (val.val[1], vcreate_u8 (__AARCH64_UINT64_C (0))); + temp.val[2] = vcombine_u8 (val.val[2], vcreate_u8 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) temp.val[2], 2); + __builtin_aarch64_st1x3v8qi ((__builtin_aarch64_simd_qi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_u16_x3 (uint16_t * __a, uint16x4x3_t val) +{ + __builtin_aarch64_simd_ci __o; + uint16x8x3_t temp; + temp.val[0] = vcombine_u16 (val.val[0], vcreate_u16 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_u16 (val.val[1], vcreate_u16 (__AARCH64_UINT64_C (0))); + temp.val[2] = vcombine_u16 (val.val[2], vcreate_u16 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) temp.val[2], 2); + __builtin_aarch64_st1x3v4hi ((__builtin_aarch64_simd_hi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_u32_x3 (uint32_t * __a, uint32x2x3_t val) +{ + __builtin_aarch64_simd_ci __o; + uint32x4x3_t temp; + temp.val[0] = vcombine_u32 (val.val[0], vcreate_u32 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_u32 (val.val[1], vcreate_u32 (__AARCH64_UINT64_C (0))); + temp.val[2] = vcombine_u32 (val.val[2], vcreate_u32 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregciv4si (__o, (int32x4_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregciv4si (__o, (int32x4_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregciv4si (__o, (int32x4_t) temp.val[2], 2); + __builtin_aarch64_st1x3v2si ((__builtin_aarch64_simd_si *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_f16_x3 (float16_t * __a, float16x4x3_t val) +{ + __builtin_aarch64_simd_ci __o; + float16x8x3_t temp; + temp.val[0] = vcombine_f16 (val.val[0], vcreate_f16 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_f16 (val.val[1], vcreate_f16 (__AARCH64_UINT64_C (0))); + temp.val[2] = vcombine_f16 (val.val[2], vcreate_f16 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregciv8hf (__o, (float16x8_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregciv8hf (__o, (float16x8_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregciv8hf (__o, (float16x8_t) temp.val[2], 2); + __builtin_aarch64_st1x3v4hf ((__builtin_aarch64_simd_hf *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_f32_x3 (float32_t * __a, float32x2x3_t val) +{ + __builtin_aarch64_simd_ci __o; + float32x4x3_t temp; + temp.val[0] = vcombine_f32 (val.val[0], vcreate_f32 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_f32 (val.val[1], vcreate_f32 (__AARCH64_UINT64_C (0))); + temp.val[2] = vcombine_f32 (val.val[2], vcreate_f32 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregciv4sf (__o, (float32x4_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregciv4sf (__o, (float32x4_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregciv4sf (__o, (float32x4_t) temp.val[2], 2); + __builtin_aarch64_st1x3v2sf ((__builtin_aarch64_simd_sf *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1_p64_x3 (poly64_t * __a, poly64x1x3_t val) +{ + __builtin_aarch64_simd_ci __o; + poly64x2x3_t temp; + temp.val[0] = vcombine_p64 (val.val[0], vcreate_p64 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_p64 (val.val[1], vcreate_p64 (__AARCH64_UINT64_C (0))); + temp.val[2] = vcombine_p64 (val.val[2], vcreate_p64 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregciv2di_ssps (__o, + (poly64x2_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregciv2di_ssps (__o, + (poly64x2_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregciv2di_ssps (__o, + (poly64x2_t) temp.val[2], 2); + __builtin_aarch64_st1x3di ((__builtin_aarch64_simd_di *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_s8_x3 (int8_t * __a, int8x16x3_t val) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) val.val[2], 2); + __builtin_aarch64_st1x3v16qi ((__builtin_aarch64_simd_qi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_p8_x3 (poly8_t * __a, poly8x16x3_t val) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) val.val[2], 2); + __builtin_aarch64_st1x3v16qi ((__builtin_aarch64_simd_qi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_s16_x3 (int16_t * __a, int16x8x3_t val) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) val.val[2], 2); + __builtin_aarch64_st1x3v8hi ((__builtin_aarch64_simd_hi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_p16_x3 (poly16_t * __a, poly16x8x3_t val) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) val.val[2], 2); + __builtin_aarch64_st1x3v8hi ((__builtin_aarch64_simd_hi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_s32_x3 (int32_t * __a, int32x4x3_t val) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv4si (__o, (int32x4_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregciv4si (__o, (int32x4_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregciv4si (__o, (int32x4_t) val.val[2], 2); + __builtin_aarch64_st1x3v4si ((__builtin_aarch64_simd_si *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_s64_x3 (int64_t * __a, int64x2x3_t val) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv2di (__o, (int64x2_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregciv2di (__o, (int64x2_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregciv2di (__o, (int64x2_t) val.val[2], 2); + __builtin_aarch64_st1x3v2di ((__builtin_aarch64_simd_di *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_u8_x3 (uint8_t * __a, uint8x16x3_t val) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) val.val[2], 2); + __builtin_aarch64_st1x3v16qi ((__builtin_aarch64_simd_qi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_u16_x3 (uint16_t * __a, uint16x8x3_t val) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) val.val[2], 2); + __builtin_aarch64_st1x3v8hi ((__builtin_aarch64_simd_hi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_u32_x3 (uint32_t * __a, uint32x4x3_t val) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv4si (__o, (int32x4_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregciv4si (__o, (int32x4_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregciv4si (__o, (int32x4_t) val.val[2], 2); + __builtin_aarch64_st1x3v4si ((__builtin_aarch64_simd_si *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_u64_x3 (uint64_t * __a, uint64x2x3_t val) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv2di (__o, (int64x2_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregciv2di (__o, (int64x2_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregciv2di (__o, (int64x2_t) val.val[2], 2); + __builtin_aarch64_st1x3v2di ((__builtin_aarch64_simd_di *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_f16_x3 (float16_t * __a, float16x8x3_t val) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv8hf (__o, (float16x8_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregciv8hf (__o, (float16x8_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregciv8hf (__o, (float16x8_t) val.val[2], 2); + __builtin_aarch64_st1x3v8hf ((__builtin_aarch64_simd_hf *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_f32_x3 (float32_t * __a, float32x4x3_t val) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv4sf (__o, (float32x4_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregciv4sf (__o, (float32x4_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregciv4sf (__o, (float32x4_t) val.val[2], 2); + __builtin_aarch64_st1x3v4sf ((__builtin_aarch64_simd_sf *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_f64_x3 (float64_t * __a, float64x2x3_t val) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv2df (__o, (float64x2_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregciv2df (__o, (float64x2_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregciv2df (__o, (float64x2_t) val.val[2], 2); + __builtin_aarch64_st1x3v2df ((__builtin_aarch64_simd_df *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst1q_p64_x3 (poly64_t * __a, poly64x2x3_t val) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv2di_ssps (__o, + (poly64x2_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregciv2di_ssps (__o, + (poly64x2_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregciv2di_ssps (__o, + (poly64x2_t) val.val[2], 2); + __builtin_aarch64_st1x3v2di ((__builtin_aarch64_simd_di *) __a, __o); +} + +/* vstn */ + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst2_s64 (int64_t * __a, int64x1x2_t val) +{ + __builtin_aarch64_simd_oi __o; + int64x2x2_t temp; + temp.val[0] = vcombine_s64 (val.val[0], vcreate_s64 (__AARCH64_INT64_C (0))); + temp.val[1] = vcombine_s64 (val.val[1], vcreate_s64 (__AARCH64_INT64_C (0))); + __o = __builtin_aarch64_set_qregoiv2di (__o, (int64x2_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv2di (__o, (int64x2_t) temp.val[1], 1); + __builtin_aarch64_st2di ((__builtin_aarch64_simd_di *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst2_u64 (uint64_t * __a, uint64x1x2_t val) +{ + __builtin_aarch64_simd_oi __o; + uint64x2x2_t temp; + temp.val[0] = vcombine_u64 (val.val[0], vcreate_u64 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_u64 (val.val[1], vcreate_u64 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregoiv2di (__o, (int64x2_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv2di (__o, (int64x2_t) temp.val[1], 1); + __builtin_aarch64_st2di ((__builtin_aarch64_simd_di *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst2_f64 (float64_t * __a, float64x1x2_t val) +{ + __builtin_aarch64_simd_oi __o; + float64x2x2_t temp; + temp.val[0] = vcombine_f64 (val.val[0], vcreate_f64 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_f64 (val.val[1], vcreate_f64 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregoiv2df (__o, (float64x2_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv2df (__o, (float64x2_t) temp.val[1], 1); + __builtin_aarch64_st2df ((__builtin_aarch64_simd_df *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst2_s8 (int8_t * __a, int8x8x2_t val) +{ + __builtin_aarch64_simd_oi __o; + int8x16x2_t temp; + temp.val[0] = vcombine_s8 (val.val[0], vcreate_s8 (__AARCH64_INT64_C (0))); + temp.val[1] = vcombine_s8 (val.val[1], vcreate_s8 (__AARCH64_INT64_C (0))); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t) temp.val[1], 1); + __builtin_aarch64_st2v8qi ((__builtin_aarch64_simd_qi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst2_p8 (poly8_t * __a, poly8x8x2_t val) +{ + __builtin_aarch64_simd_oi __o; + poly8x16x2_t temp; + temp.val[0] = vcombine_p8 (val.val[0], vcreate_p8 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_p8 (val.val[1], vcreate_p8 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t) temp.val[1], 1); + __builtin_aarch64_st2v8qi ((__builtin_aarch64_simd_qi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst2_s16 (int16_t * __a, int16x4x2_t val) +{ + __builtin_aarch64_simd_oi __o; + int16x8x2_t temp; + temp.val[0] = vcombine_s16 (val.val[0], vcreate_s16 (__AARCH64_INT64_C (0))); + temp.val[1] = vcombine_s16 (val.val[1], vcreate_s16 (__AARCH64_INT64_C (0))); + __o = __builtin_aarch64_set_qregoiv8hi (__o, (int16x8_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv8hi (__o, (int16x8_t) temp.val[1], 1); + __builtin_aarch64_st2v4hi ((__builtin_aarch64_simd_hi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst2_p16 (poly16_t * __a, poly16x4x2_t val) +{ + __builtin_aarch64_simd_oi __o; + poly16x8x2_t temp; + temp.val[0] = vcombine_p16 (val.val[0], vcreate_p16 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_p16 (val.val[1], vcreate_p16 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregoiv8hi (__o, (int16x8_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv8hi (__o, (int16x8_t) temp.val[1], 1); + __builtin_aarch64_st2v4hi ((__builtin_aarch64_simd_hi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst2_s32 (int32_t * __a, int32x2x2_t val) +{ + __builtin_aarch64_simd_oi __o; + int32x4x2_t temp; + temp.val[0] = vcombine_s32 (val.val[0], vcreate_s32 (__AARCH64_INT64_C (0))); + temp.val[1] = vcombine_s32 (val.val[1], vcreate_s32 (__AARCH64_INT64_C (0))); + __o = __builtin_aarch64_set_qregoiv4si (__o, (int32x4_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv4si (__o, (int32x4_t) temp.val[1], 1); + __builtin_aarch64_st2v2si ((__builtin_aarch64_simd_si *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst2_u8 (uint8_t * __a, uint8x8x2_t val) +{ + __builtin_aarch64_simd_oi __o; + uint8x16x2_t temp; + temp.val[0] = vcombine_u8 (val.val[0], vcreate_u8 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_u8 (val.val[1], vcreate_u8 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t) temp.val[1], 1); + __builtin_aarch64_st2v8qi ((__builtin_aarch64_simd_qi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst2_u16 (uint16_t * __a, uint16x4x2_t val) +{ + __builtin_aarch64_simd_oi __o; + uint16x8x2_t temp; + temp.val[0] = vcombine_u16 (val.val[0], vcreate_u16 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_u16 (val.val[1], vcreate_u16 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregoiv8hi (__o, (int16x8_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv8hi (__o, (int16x8_t) temp.val[1], 1); + __builtin_aarch64_st2v4hi ((__builtin_aarch64_simd_hi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst2_u32 (uint32_t * __a, uint32x2x2_t val) +{ + __builtin_aarch64_simd_oi __o; + uint32x4x2_t temp; + temp.val[0] = vcombine_u32 (val.val[0], vcreate_u32 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_u32 (val.val[1], vcreate_u32 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregoiv4si (__o, (int32x4_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv4si (__o, (int32x4_t) temp.val[1], 1); + __builtin_aarch64_st2v2si ((__builtin_aarch64_simd_si *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst2_f16 (float16_t * __a, float16x4x2_t val) +{ + __builtin_aarch64_simd_oi __o; + float16x8x2_t temp; + temp.val[0] = vcombine_f16 (val.val[0], vcreate_f16 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_f16 (val.val[1], vcreate_f16 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregoiv8hf (__o, temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv8hf (__o, temp.val[1], 1); + __builtin_aarch64_st2v4hf (__a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst2_f32 (float32_t * __a, float32x2x2_t val) +{ + __builtin_aarch64_simd_oi __o; + float32x4x2_t temp; + temp.val[0] = vcombine_f32 (val.val[0], vcreate_f32 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_f32 (val.val[1], vcreate_f32 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregoiv4sf (__o, (float32x4_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv4sf (__o, (float32x4_t) temp.val[1], 1); + __builtin_aarch64_st2v2sf ((__builtin_aarch64_simd_sf *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst2_p64 (poly64_t * __a, poly64x1x2_t val) +{ + __builtin_aarch64_simd_oi __o; + poly64x2x2_t temp; + temp.val[0] = vcombine_p64 (val.val[0], vcreate_p64 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_p64 (val.val[1], vcreate_p64 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregoiv2di_ssps (__o, + (poly64x2_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv2di_ssps (__o, + (poly64x2_t) temp.val[1], 1); + __builtin_aarch64_st2di ((__builtin_aarch64_simd_di *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst2q_s8 (int8_t * __a, int8x16x2_t val) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t) val.val[1], 1); + __builtin_aarch64_st2v16qi ((__builtin_aarch64_simd_qi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst2q_p8 (poly8_t * __a, poly8x16x2_t val) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t) val.val[1], 1); + __builtin_aarch64_st2v16qi ((__builtin_aarch64_simd_qi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst2q_s16 (int16_t * __a, int16x8x2_t val) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv8hi (__o, (int16x8_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregoiv8hi (__o, (int16x8_t) val.val[1], 1); + __builtin_aarch64_st2v8hi ((__builtin_aarch64_simd_hi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst2q_p16 (poly16_t * __a, poly16x8x2_t val) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv8hi (__o, (int16x8_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregoiv8hi (__o, (int16x8_t) val.val[1], 1); + __builtin_aarch64_st2v8hi ((__builtin_aarch64_simd_hi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst2q_s32 (int32_t * __a, int32x4x2_t val) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv4si (__o, (int32x4_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregoiv4si (__o, (int32x4_t) val.val[1], 1); + __builtin_aarch64_st2v4si ((__builtin_aarch64_simd_si *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst2q_s64 (int64_t * __a, int64x2x2_t val) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv2di (__o, (int64x2_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregoiv2di (__o, (int64x2_t) val.val[1], 1); + __builtin_aarch64_st2v2di ((__builtin_aarch64_simd_di *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst2q_u8 (uint8_t * __a, uint8x16x2_t val) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t) val.val[1], 1); + __builtin_aarch64_st2v16qi ((__builtin_aarch64_simd_qi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst2q_u16 (uint16_t * __a, uint16x8x2_t val) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv8hi (__o, (int16x8_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregoiv8hi (__o, (int16x8_t) val.val[1], 1); + __builtin_aarch64_st2v8hi ((__builtin_aarch64_simd_hi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst2q_u32 (uint32_t * __a, uint32x4x2_t val) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv4si (__o, (int32x4_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregoiv4si (__o, (int32x4_t) val.val[1], 1); + __builtin_aarch64_st2v4si ((__builtin_aarch64_simd_si *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst2q_u64 (uint64_t * __a, uint64x2x2_t val) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv2di (__o, (int64x2_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregoiv2di (__o, (int64x2_t) val.val[1], 1); + __builtin_aarch64_st2v2di ((__builtin_aarch64_simd_di *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst2q_f16 (float16_t * __a, float16x8x2_t val) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv8hf (__o, val.val[0], 0); + __o = __builtin_aarch64_set_qregoiv8hf (__o, val.val[1], 1); + __builtin_aarch64_st2v8hf (__a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst2q_f32 (float32_t * __a, float32x4x2_t val) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv4sf (__o, (float32x4_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregoiv4sf (__o, (float32x4_t) val.val[1], 1); + __builtin_aarch64_st2v4sf ((__builtin_aarch64_simd_sf *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst2q_f64 (float64_t * __a, float64x2x2_t val) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv2df (__o, (float64x2_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregoiv2df (__o, (float64x2_t) val.val[1], 1); + __builtin_aarch64_st2v2df ((__builtin_aarch64_simd_df *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst2q_p64 (poly64_t * __a, poly64x2x2_t val) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv2di_ssps (__o, + (poly64x2_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregoiv2di_ssps (__o, + (poly64x2_t) val.val[1], 1); + __builtin_aarch64_st2v2di ((__builtin_aarch64_simd_di *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst3_s64 (int64_t * __a, int64x1x3_t val) +{ + __builtin_aarch64_simd_ci __o; + int64x2x3_t temp; + temp.val[0] = vcombine_s64 (val.val[0], vcreate_s64 (__AARCH64_INT64_C (0))); + temp.val[1] = vcombine_s64 (val.val[1], vcreate_s64 (__AARCH64_INT64_C (0))); + temp.val[2] = vcombine_s64 (val.val[2], vcreate_s64 (__AARCH64_INT64_C (0))); + __o = __builtin_aarch64_set_qregciv2di (__o, (int64x2_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregciv2di (__o, (int64x2_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregciv2di (__o, (int64x2_t) temp.val[2], 2); + __builtin_aarch64_st3di ((__builtin_aarch64_simd_di *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst3_u64 (uint64_t * __a, uint64x1x3_t val) +{ + __builtin_aarch64_simd_ci __o; + uint64x2x3_t temp; + temp.val[0] = vcombine_u64 (val.val[0], vcreate_u64 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_u64 (val.val[1], vcreate_u64 (__AARCH64_UINT64_C (0))); + temp.val[2] = vcombine_u64 (val.val[2], vcreate_u64 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregciv2di (__o, (int64x2_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregciv2di (__o, (int64x2_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregciv2di (__o, (int64x2_t) temp.val[2], 2); + __builtin_aarch64_st3di ((__builtin_aarch64_simd_di *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst3_f64 (float64_t * __a, float64x1x3_t val) +{ + __builtin_aarch64_simd_ci __o; + float64x2x3_t temp; + temp.val[0] = vcombine_f64 (val.val[0], vcreate_f64 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_f64 (val.val[1], vcreate_f64 (__AARCH64_UINT64_C (0))); + temp.val[2] = vcombine_f64 (val.val[2], vcreate_f64 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregciv2df (__o, (float64x2_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregciv2df (__o, (float64x2_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregciv2df (__o, (float64x2_t) temp.val[2], 2); + __builtin_aarch64_st3df ((__builtin_aarch64_simd_df *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst3_s8 (int8_t * __a, int8x8x3_t val) +{ + __builtin_aarch64_simd_ci __o; + int8x16x3_t temp; + temp.val[0] = vcombine_s8 (val.val[0], vcreate_s8 (__AARCH64_INT64_C (0))); + temp.val[1] = vcombine_s8 (val.val[1], vcreate_s8 (__AARCH64_INT64_C (0))); + temp.val[2] = vcombine_s8 (val.val[2], vcreate_s8 (__AARCH64_INT64_C (0))); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) temp.val[2], 2); + __builtin_aarch64_st3v8qi ((__builtin_aarch64_simd_qi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst3_p8 (poly8_t * __a, poly8x8x3_t val) +{ + __builtin_aarch64_simd_ci __o; + poly8x16x3_t temp; + temp.val[0] = vcombine_p8 (val.val[0], vcreate_p8 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_p8 (val.val[1], vcreate_p8 (__AARCH64_UINT64_C (0))); + temp.val[2] = vcombine_p8 (val.val[2], vcreate_p8 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) temp.val[2], 2); + __builtin_aarch64_st3v8qi ((__builtin_aarch64_simd_qi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst3_s16 (int16_t * __a, int16x4x3_t val) +{ + __builtin_aarch64_simd_ci __o; + int16x8x3_t temp; + temp.val[0] = vcombine_s16 (val.val[0], vcreate_s16 (__AARCH64_INT64_C (0))); + temp.val[1] = vcombine_s16 (val.val[1], vcreate_s16 (__AARCH64_INT64_C (0))); + temp.val[2] = vcombine_s16 (val.val[2], vcreate_s16 (__AARCH64_INT64_C (0))); + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) temp.val[2], 2); + __builtin_aarch64_st3v4hi ((__builtin_aarch64_simd_hi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst3_p16 (poly16_t * __a, poly16x4x3_t val) +{ + __builtin_aarch64_simd_ci __o; + poly16x8x3_t temp; + temp.val[0] = vcombine_p16 (val.val[0], vcreate_p16 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_p16 (val.val[1], vcreate_p16 (__AARCH64_UINT64_C (0))); + temp.val[2] = vcombine_p16 (val.val[2], vcreate_p16 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) temp.val[2], 2); + __builtin_aarch64_st3v4hi ((__builtin_aarch64_simd_hi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst3_s32 (int32_t * __a, int32x2x3_t val) +{ + __builtin_aarch64_simd_ci __o; + int32x4x3_t temp; + temp.val[0] = vcombine_s32 (val.val[0], vcreate_s32 (__AARCH64_INT64_C (0))); + temp.val[1] = vcombine_s32 (val.val[1], vcreate_s32 (__AARCH64_INT64_C (0))); + temp.val[2] = vcombine_s32 (val.val[2], vcreate_s32 (__AARCH64_INT64_C (0))); + __o = __builtin_aarch64_set_qregciv4si (__o, (int32x4_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregciv4si (__o, (int32x4_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregciv4si (__o, (int32x4_t) temp.val[2], 2); + __builtin_aarch64_st3v2si ((__builtin_aarch64_simd_si *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst3_u8 (uint8_t * __a, uint8x8x3_t val) +{ + __builtin_aarch64_simd_ci __o; + uint8x16x3_t temp; + temp.val[0] = vcombine_u8 (val.val[0], vcreate_u8 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_u8 (val.val[1], vcreate_u8 (__AARCH64_UINT64_C (0))); + temp.val[2] = vcombine_u8 (val.val[2], vcreate_u8 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) temp.val[2], 2); + __builtin_aarch64_st3v8qi ((__builtin_aarch64_simd_qi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst3_u16 (uint16_t * __a, uint16x4x3_t val) +{ + __builtin_aarch64_simd_ci __o; + uint16x8x3_t temp; + temp.val[0] = vcombine_u16 (val.val[0], vcreate_u16 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_u16 (val.val[1], vcreate_u16 (__AARCH64_UINT64_C (0))); + temp.val[2] = vcombine_u16 (val.val[2], vcreate_u16 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) temp.val[2], 2); + __builtin_aarch64_st3v4hi ((__builtin_aarch64_simd_hi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst3_u32 (uint32_t * __a, uint32x2x3_t val) +{ + __builtin_aarch64_simd_ci __o; + uint32x4x3_t temp; + temp.val[0] = vcombine_u32 (val.val[0], vcreate_u32 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_u32 (val.val[1], vcreate_u32 (__AARCH64_UINT64_C (0))); + temp.val[2] = vcombine_u32 (val.val[2], vcreate_u32 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregciv4si (__o, (int32x4_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregciv4si (__o, (int32x4_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregciv4si (__o, (int32x4_t) temp.val[2], 2); + __builtin_aarch64_st3v2si ((__builtin_aarch64_simd_si *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst3_f16 (float16_t * __a, float16x4x3_t val) +{ + __builtin_aarch64_simd_ci __o; + float16x8x3_t temp; + temp.val[0] = vcombine_f16 (val.val[0], vcreate_f16 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_f16 (val.val[1], vcreate_f16 (__AARCH64_UINT64_C (0))); + temp.val[2] = vcombine_f16 (val.val[2], vcreate_f16 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregciv8hf (__o, (float16x8_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregciv8hf (__o, (float16x8_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregciv8hf (__o, (float16x8_t) temp.val[2], 2); + __builtin_aarch64_st3v4hf ((__builtin_aarch64_simd_hf *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst3_f32 (float32_t * __a, float32x2x3_t val) +{ + __builtin_aarch64_simd_ci __o; + float32x4x3_t temp; + temp.val[0] = vcombine_f32 (val.val[0], vcreate_f32 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_f32 (val.val[1], vcreate_f32 (__AARCH64_UINT64_C (0))); + temp.val[2] = vcombine_f32 (val.val[2], vcreate_f32 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregciv4sf (__o, (float32x4_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregciv4sf (__o, (float32x4_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregciv4sf (__o, (float32x4_t) temp.val[2], 2); + __builtin_aarch64_st3v2sf ((__builtin_aarch64_simd_sf *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst3_p64 (poly64_t * __a, poly64x1x3_t val) +{ + __builtin_aarch64_simd_ci __o; + poly64x2x3_t temp; + temp.val[0] = vcombine_p64 (val.val[0], vcreate_p64 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_p64 (val.val[1], vcreate_p64 (__AARCH64_UINT64_C (0))); + temp.val[2] = vcombine_p64 (val.val[2], vcreate_p64 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregciv2di_ssps (__o, + (poly64x2_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregciv2di_ssps (__o, + (poly64x2_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregciv2di_ssps (__o, + (poly64x2_t) temp.val[2], 2); + __builtin_aarch64_st3di ((__builtin_aarch64_simd_di *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst3q_s8 (int8_t * __a, int8x16x3_t val) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) val.val[2], 2); + __builtin_aarch64_st3v16qi ((__builtin_aarch64_simd_qi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst3q_p8 (poly8_t * __a, poly8x16x3_t val) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) val.val[2], 2); + __builtin_aarch64_st3v16qi ((__builtin_aarch64_simd_qi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst3q_s16 (int16_t * __a, int16x8x3_t val) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) val.val[2], 2); + __builtin_aarch64_st3v8hi ((__builtin_aarch64_simd_hi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst3q_p16 (poly16_t * __a, poly16x8x3_t val) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) val.val[2], 2); + __builtin_aarch64_st3v8hi ((__builtin_aarch64_simd_hi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst3q_s32 (int32_t * __a, int32x4x3_t val) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv4si (__o, (int32x4_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregciv4si (__o, (int32x4_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregciv4si (__o, (int32x4_t) val.val[2], 2); + __builtin_aarch64_st3v4si ((__builtin_aarch64_simd_si *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst3q_s64 (int64_t * __a, int64x2x3_t val) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv2di (__o, (int64x2_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregciv2di (__o, (int64x2_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregciv2di (__o, (int64x2_t) val.val[2], 2); + __builtin_aarch64_st3v2di ((__builtin_aarch64_simd_di *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst3q_u8 (uint8_t * __a, uint8x16x3_t val) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t) val.val[2], 2); + __builtin_aarch64_st3v16qi ((__builtin_aarch64_simd_qi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst3q_u16 (uint16_t * __a, uint16x8x3_t val) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregciv8hi (__o, (int16x8_t) val.val[2], 2); + __builtin_aarch64_st3v8hi ((__builtin_aarch64_simd_hi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst3q_u32 (uint32_t * __a, uint32x4x3_t val) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv4si (__o, (int32x4_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregciv4si (__o, (int32x4_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregciv4si (__o, (int32x4_t) val.val[2], 2); + __builtin_aarch64_st3v4si ((__builtin_aarch64_simd_si *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst3q_u64 (uint64_t * __a, uint64x2x3_t val) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv2di (__o, (int64x2_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregciv2di (__o, (int64x2_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregciv2di (__o, (int64x2_t) val.val[2], 2); + __builtin_aarch64_st3v2di ((__builtin_aarch64_simd_di *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst3q_f16 (float16_t * __a, float16x8x3_t val) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv8hf (__o, (float16x8_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregciv8hf (__o, (float16x8_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregciv8hf (__o, (float16x8_t) val.val[2], 2); + __builtin_aarch64_st3v8hf ((__builtin_aarch64_simd_hf *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst3q_f32 (float32_t * __a, float32x4x3_t val) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv4sf (__o, (float32x4_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregciv4sf (__o, (float32x4_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregciv4sf (__o, (float32x4_t) val.val[2], 2); + __builtin_aarch64_st3v4sf ((__builtin_aarch64_simd_sf *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst3q_f64 (float64_t * __a, float64x2x3_t val) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv2df (__o, (float64x2_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregciv2df (__o, (float64x2_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregciv2df (__o, (float64x2_t) val.val[2], 2); + __builtin_aarch64_st3v2df ((__builtin_aarch64_simd_df *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst3q_p64 (poly64_t * __a, poly64x2x3_t val) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv2di_ssps (__o, + (poly64x2_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregciv2di_ssps (__o, + (poly64x2_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregciv2di_ssps (__o, + (poly64x2_t) val.val[2], 2); + __builtin_aarch64_st3v2di ((__builtin_aarch64_simd_di *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst4_s64 (int64_t * __a, int64x1x4_t val) +{ + __builtin_aarch64_simd_xi __o; + int64x2x4_t temp; + temp.val[0] = vcombine_s64 (val.val[0], vcreate_s64 (__AARCH64_INT64_C (0))); + temp.val[1] = vcombine_s64 (val.val[1], vcreate_s64 (__AARCH64_INT64_C (0))); + temp.val[2] = vcombine_s64 (val.val[2], vcreate_s64 (__AARCH64_INT64_C (0))); + temp.val[3] = vcombine_s64 (val.val[3], vcreate_s64 (__AARCH64_INT64_C (0))); + __o = __builtin_aarch64_set_qregxiv2di (__o, (int64x2_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregxiv2di (__o, (int64x2_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregxiv2di (__o, (int64x2_t) temp.val[2], 2); + __o = __builtin_aarch64_set_qregxiv2di (__o, (int64x2_t) temp.val[3], 3); + __builtin_aarch64_st4di ((__builtin_aarch64_simd_di *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst4_u64 (uint64_t * __a, uint64x1x4_t val) +{ + __builtin_aarch64_simd_xi __o; + uint64x2x4_t temp; + temp.val[0] = vcombine_u64 (val.val[0], vcreate_u64 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_u64 (val.val[1], vcreate_u64 (__AARCH64_UINT64_C (0))); + temp.val[2] = vcombine_u64 (val.val[2], vcreate_u64 (__AARCH64_UINT64_C (0))); + temp.val[3] = vcombine_u64 (val.val[3], vcreate_u64 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregxiv2di (__o, (int64x2_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregxiv2di (__o, (int64x2_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregxiv2di (__o, (int64x2_t) temp.val[2], 2); + __o = __builtin_aarch64_set_qregxiv2di (__o, (int64x2_t) temp.val[3], 3); + __builtin_aarch64_st4di ((__builtin_aarch64_simd_di *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst4_f64 (float64_t * __a, float64x1x4_t val) +{ + __builtin_aarch64_simd_xi __o; + float64x2x4_t temp; + temp.val[0] = vcombine_f64 (val.val[0], vcreate_f64 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_f64 (val.val[1], vcreate_f64 (__AARCH64_UINT64_C (0))); + temp.val[2] = vcombine_f64 (val.val[2], vcreate_f64 (__AARCH64_UINT64_C (0))); + temp.val[3] = vcombine_f64 (val.val[3], vcreate_f64 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregxiv2df (__o, (float64x2_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregxiv2df (__o, (float64x2_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregxiv2df (__o, (float64x2_t) temp.val[2], 2); + __o = __builtin_aarch64_set_qregxiv2df (__o, (float64x2_t) temp.val[3], 3); + __builtin_aarch64_st4df ((__builtin_aarch64_simd_df *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst4_s8 (int8_t * __a, int8x8x4_t val) +{ + __builtin_aarch64_simd_xi __o; + int8x16x4_t temp; + temp.val[0] = vcombine_s8 (val.val[0], vcreate_s8 (__AARCH64_INT64_C (0))); + temp.val[1] = vcombine_s8 (val.val[1], vcreate_s8 (__AARCH64_INT64_C (0))); + temp.val[2] = vcombine_s8 (val.val[2], vcreate_s8 (__AARCH64_INT64_C (0))); + temp.val[3] = vcombine_s8 (val.val[3], vcreate_s8 (__AARCH64_INT64_C (0))); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t) temp.val[2], 2); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t) temp.val[3], 3); + __builtin_aarch64_st4v8qi ((__builtin_aarch64_simd_qi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst4_p8 (poly8_t * __a, poly8x8x4_t val) +{ + __builtin_aarch64_simd_xi __o; + poly8x16x4_t temp; + temp.val[0] = vcombine_p8 (val.val[0], vcreate_p8 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_p8 (val.val[1], vcreate_p8 (__AARCH64_UINT64_C (0))); + temp.val[2] = vcombine_p8 (val.val[2], vcreate_p8 (__AARCH64_UINT64_C (0))); + temp.val[3] = vcombine_p8 (val.val[3], vcreate_p8 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t) temp.val[2], 2); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t) temp.val[3], 3); + __builtin_aarch64_st4v8qi ((__builtin_aarch64_simd_qi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst4_s16 (int16_t * __a, int16x4x4_t val) +{ + __builtin_aarch64_simd_xi __o; + int16x8x4_t temp; + temp.val[0] = vcombine_s16 (val.val[0], vcreate_s16 (__AARCH64_INT64_C (0))); + temp.val[1] = vcombine_s16 (val.val[1], vcreate_s16 (__AARCH64_INT64_C (0))); + temp.val[2] = vcombine_s16 (val.val[2], vcreate_s16 (__AARCH64_INT64_C (0))); + temp.val[3] = vcombine_s16 (val.val[3], vcreate_s16 (__AARCH64_INT64_C (0))); + __o = __builtin_aarch64_set_qregxiv8hi (__o, (int16x8_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregxiv8hi (__o, (int16x8_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregxiv8hi (__o, (int16x8_t) temp.val[2], 2); + __o = __builtin_aarch64_set_qregxiv8hi (__o, (int16x8_t) temp.val[3], 3); + __builtin_aarch64_st4v4hi ((__builtin_aarch64_simd_hi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst4_p16 (poly16_t * __a, poly16x4x4_t val) +{ + __builtin_aarch64_simd_xi __o; + poly16x8x4_t temp; + temp.val[0] = vcombine_p16 (val.val[0], vcreate_p16 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_p16 (val.val[1], vcreate_p16 (__AARCH64_UINT64_C (0))); + temp.val[2] = vcombine_p16 (val.val[2], vcreate_p16 (__AARCH64_UINT64_C (0))); + temp.val[3] = vcombine_p16 (val.val[3], vcreate_p16 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregxiv8hi (__o, (int16x8_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregxiv8hi (__o, (int16x8_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregxiv8hi (__o, (int16x8_t) temp.val[2], 2); + __o = __builtin_aarch64_set_qregxiv8hi (__o, (int16x8_t) temp.val[3], 3); + __builtin_aarch64_st4v4hi ((__builtin_aarch64_simd_hi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst4_s32 (int32_t * __a, int32x2x4_t val) +{ + __builtin_aarch64_simd_xi __o; + int32x4x4_t temp; + temp.val[0] = vcombine_s32 (val.val[0], vcreate_s32 (__AARCH64_INT64_C (0))); + temp.val[1] = vcombine_s32 (val.val[1], vcreate_s32 (__AARCH64_INT64_C (0))); + temp.val[2] = vcombine_s32 (val.val[2], vcreate_s32 (__AARCH64_INT64_C (0))); + temp.val[3] = vcombine_s32 (val.val[3], vcreate_s32 (__AARCH64_INT64_C (0))); + __o = __builtin_aarch64_set_qregxiv4si (__o, (int32x4_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregxiv4si (__o, (int32x4_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregxiv4si (__o, (int32x4_t) temp.val[2], 2); + __o = __builtin_aarch64_set_qregxiv4si (__o, (int32x4_t) temp.val[3], 3); + __builtin_aarch64_st4v2si ((__builtin_aarch64_simd_si *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst4_u8 (uint8_t * __a, uint8x8x4_t val) +{ + __builtin_aarch64_simd_xi __o; + uint8x16x4_t temp; + temp.val[0] = vcombine_u8 (val.val[0], vcreate_u8 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_u8 (val.val[1], vcreate_u8 (__AARCH64_UINT64_C (0))); + temp.val[2] = vcombine_u8 (val.val[2], vcreate_u8 (__AARCH64_UINT64_C (0))); + temp.val[3] = vcombine_u8 (val.val[3], vcreate_u8 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t) temp.val[2], 2); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t) temp.val[3], 3); + __builtin_aarch64_st4v8qi ((__builtin_aarch64_simd_qi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst4_u16 (uint16_t * __a, uint16x4x4_t val) +{ + __builtin_aarch64_simd_xi __o; + uint16x8x4_t temp; + temp.val[0] = vcombine_u16 (val.val[0], vcreate_u16 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_u16 (val.val[1], vcreate_u16 (__AARCH64_UINT64_C (0))); + temp.val[2] = vcombine_u16 (val.val[2], vcreate_u16 (__AARCH64_UINT64_C (0))); + temp.val[3] = vcombine_u16 (val.val[3], vcreate_u16 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregxiv8hi (__o, (int16x8_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregxiv8hi (__o, (int16x8_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregxiv8hi (__o, (int16x8_t) temp.val[2], 2); + __o = __builtin_aarch64_set_qregxiv8hi (__o, (int16x8_t) temp.val[3], 3); + __builtin_aarch64_st4v4hi ((__builtin_aarch64_simd_hi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst4_u32 (uint32_t * __a, uint32x2x4_t val) +{ + __builtin_aarch64_simd_xi __o; + uint32x4x4_t temp; + temp.val[0] = vcombine_u32 (val.val[0], vcreate_u32 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_u32 (val.val[1], vcreate_u32 (__AARCH64_UINT64_C (0))); + temp.val[2] = vcombine_u32 (val.val[2], vcreate_u32 (__AARCH64_UINT64_C (0))); + temp.val[3] = vcombine_u32 (val.val[3], vcreate_u32 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregxiv4si (__o, (int32x4_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregxiv4si (__o, (int32x4_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregxiv4si (__o, (int32x4_t) temp.val[2], 2); + __o = __builtin_aarch64_set_qregxiv4si (__o, (int32x4_t) temp.val[3], 3); + __builtin_aarch64_st4v2si ((__builtin_aarch64_simd_si *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst4_f16 (float16_t * __a, float16x4x4_t val) +{ + __builtin_aarch64_simd_xi __o; + float16x8x4_t temp; + temp.val[0] = vcombine_f16 (val.val[0], vcreate_f16 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_f16 (val.val[1], vcreate_f16 (__AARCH64_UINT64_C (0))); + temp.val[2] = vcombine_f16 (val.val[2], vcreate_f16 (__AARCH64_UINT64_C (0))); + temp.val[3] = vcombine_f16 (val.val[3], vcreate_f16 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregxiv8hf (__o, (float16x8_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregxiv8hf (__o, (float16x8_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregxiv8hf (__o, (float16x8_t) temp.val[2], 2); + __o = __builtin_aarch64_set_qregxiv8hf (__o, (float16x8_t) temp.val[3], 3); + __builtin_aarch64_st4v4hf ((__builtin_aarch64_simd_hf *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst4_f32 (float32_t * __a, float32x2x4_t val) +{ + __builtin_aarch64_simd_xi __o; + float32x4x4_t temp; + temp.val[0] = vcombine_f32 (val.val[0], vcreate_f32 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_f32 (val.val[1], vcreate_f32 (__AARCH64_UINT64_C (0))); + temp.val[2] = vcombine_f32 (val.val[2], vcreate_f32 (__AARCH64_UINT64_C (0))); + temp.val[3] = vcombine_f32 (val.val[3], vcreate_f32 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregxiv4sf (__o, (float32x4_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregxiv4sf (__o, (float32x4_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregxiv4sf (__o, (float32x4_t) temp.val[2], 2); + __o = __builtin_aarch64_set_qregxiv4sf (__o, (float32x4_t) temp.val[3], 3); + __builtin_aarch64_st4v2sf ((__builtin_aarch64_simd_sf *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst4_p64 (poly64_t * __a, poly64x1x4_t val) +{ + __builtin_aarch64_simd_xi __o; + poly64x2x4_t temp; + temp.val[0] = vcombine_p64 (val.val[0], vcreate_p64 (__AARCH64_UINT64_C (0))); + temp.val[1] = vcombine_p64 (val.val[1], vcreate_p64 (__AARCH64_UINT64_C (0))); + temp.val[2] = vcombine_p64 (val.val[2], vcreate_p64 (__AARCH64_UINT64_C (0))); + temp.val[3] = vcombine_p64 (val.val[3], vcreate_p64 (__AARCH64_UINT64_C (0))); + __o = __builtin_aarch64_set_qregxiv2di_ssps (__o, + (poly64x2_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregxiv2di_ssps (__o, + (poly64x2_t) temp.val[1], 1); + __o = __builtin_aarch64_set_qregxiv2di_ssps (__o, + (poly64x2_t) temp.val[2], 2); + __o = __builtin_aarch64_set_qregxiv2di_ssps (__o, + (poly64x2_t) temp.val[3], 3); + __builtin_aarch64_st4di ((__builtin_aarch64_simd_di *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst4q_s8 (int8_t * __a, int8x16x4_t val) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t) val.val[2], 2); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t) val.val[3], 3); + __builtin_aarch64_st4v16qi ((__builtin_aarch64_simd_qi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst4q_p8 (poly8_t * __a, poly8x16x4_t val) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t) val.val[2], 2); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t) val.val[3], 3); + __builtin_aarch64_st4v16qi ((__builtin_aarch64_simd_qi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst4q_s16 (int16_t * __a, int16x8x4_t val) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv8hi (__o, (int16x8_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregxiv8hi (__o, (int16x8_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregxiv8hi (__o, (int16x8_t) val.val[2], 2); + __o = __builtin_aarch64_set_qregxiv8hi (__o, (int16x8_t) val.val[3], 3); + __builtin_aarch64_st4v8hi ((__builtin_aarch64_simd_hi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst4q_p16 (poly16_t * __a, poly16x8x4_t val) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv8hi (__o, (int16x8_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregxiv8hi (__o, (int16x8_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregxiv8hi (__o, (int16x8_t) val.val[2], 2); + __o = __builtin_aarch64_set_qregxiv8hi (__o, (int16x8_t) val.val[3], 3); + __builtin_aarch64_st4v8hi ((__builtin_aarch64_simd_hi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst4q_s32 (int32_t * __a, int32x4x4_t val) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv4si (__o, (int32x4_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregxiv4si (__o, (int32x4_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregxiv4si (__o, (int32x4_t) val.val[2], 2); + __o = __builtin_aarch64_set_qregxiv4si (__o, (int32x4_t) val.val[3], 3); + __builtin_aarch64_st4v4si ((__builtin_aarch64_simd_si *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst4q_s64 (int64_t * __a, int64x2x4_t val) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv2di (__o, (int64x2_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregxiv2di (__o, (int64x2_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregxiv2di (__o, (int64x2_t) val.val[2], 2); + __o = __builtin_aarch64_set_qregxiv2di (__o, (int64x2_t) val.val[3], 3); + __builtin_aarch64_st4v2di ((__builtin_aarch64_simd_di *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst4q_u8 (uint8_t * __a, uint8x16x4_t val) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t) val.val[2], 2); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t) val.val[3], 3); + __builtin_aarch64_st4v16qi ((__builtin_aarch64_simd_qi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst4q_u16 (uint16_t * __a, uint16x8x4_t val) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv8hi (__o, (int16x8_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregxiv8hi (__o, (int16x8_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregxiv8hi (__o, (int16x8_t) val.val[2], 2); + __o = __builtin_aarch64_set_qregxiv8hi (__o, (int16x8_t) val.val[3], 3); + __builtin_aarch64_st4v8hi ((__builtin_aarch64_simd_hi *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst4q_u32 (uint32_t * __a, uint32x4x4_t val) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv4si (__o, (int32x4_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregxiv4si (__o, (int32x4_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregxiv4si (__o, (int32x4_t) val.val[2], 2); + __o = __builtin_aarch64_set_qregxiv4si (__o, (int32x4_t) val.val[3], 3); + __builtin_aarch64_st4v4si ((__builtin_aarch64_simd_si *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst4q_u64 (uint64_t * __a, uint64x2x4_t val) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv2di (__o, (int64x2_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregxiv2di (__o, (int64x2_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregxiv2di (__o, (int64x2_t) val.val[2], 2); + __o = __builtin_aarch64_set_qregxiv2di (__o, (int64x2_t) val.val[3], 3); + __builtin_aarch64_st4v2di ((__builtin_aarch64_simd_di *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst4q_f16 (float16_t * __a, float16x8x4_t val) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv8hf (__o, (float16x8_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregxiv8hf (__o, (float16x8_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregxiv8hf (__o, (float16x8_t) val.val[2], 2); + __o = __builtin_aarch64_set_qregxiv8hf (__o, (float16x8_t) val.val[3], 3); + __builtin_aarch64_st4v8hf ((__builtin_aarch64_simd_hf *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst4q_f32 (float32_t * __a, float32x4x4_t val) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv4sf (__o, (float32x4_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregxiv4sf (__o, (float32x4_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregxiv4sf (__o, (float32x4_t) val.val[2], 2); + __o = __builtin_aarch64_set_qregxiv4sf (__o, (float32x4_t) val.val[3], 3); + __builtin_aarch64_st4v4sf ((__builtin_aarch64_simd_sf *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst4q_f64 (float64_t * __a, float64x2x4_t val) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv2df (__o, (float64x2_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregxiv2df (__o, (float64x2_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregxiv2df (__o, (float64x2_t) val.val[2], 2); + __o = __builtin_aarch64_set_qregxiv2df (__o, (float64x2_t) val.val[3], 3); + __builtin_aarch64_st4v2df ((__builtin_aarch64_simd_df *) __a, __o); +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vst4q_p64 (poly64_t * __a, poly64x2x4_t val) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv2di_ssps (__o, + (poly64x2_t) val.val[0], 0); + __o = __builtin_aarch64_set_qregxiv2di_ssps (__o, + (poly64x2_t) val.val[1], 1); + __o = __builtin_aarch64_set_qregxiv2di_ssps (__o, + (poly64x2_t) val.val[2], 2); + __o = __builtin_aarch64_set_qregxiv2di_ssps (__o, + (poly64x2_t) val.val[3], 3); + __builtin_aarch64_st4v2di ((__builtin_aarch64_simd_di *) __a, __o); +} + +/* vsub */ + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubd_s64 (int64_t __a, int64_t __b) +{ + return __a - __b; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubd_u64 (uint64_t __a, uint64_t __b) +{ + return __a - __b; +} + +/* vtbx1 */ + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtbx1_s8 (int8x8_t __r, int8x8_t __tab, int8x8_t __idx) +{ + uint8x8_t __mask = vclt_u8 (vreinterpret_u8_s8 (__idx), + vmov_n_u8 (8)); + int8x8_t __tbl = vtbl1_s8 (__tab, __idx); + + return vbsl_s8 (__mask, __tbl, __r); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtbx1_u8 (uint8x8_t __r, uint8x8_t __tab, uint8x8_t __idx) +{ + uint8x8_t __mask = vclt_u8 (__idx, vmov_n_u8 (8)); + uint8x8_t __tbl = vtbl1_u8 (__tab, __idx); + + return vbsl_u8 (__mask, __tbl, __r); +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtbx1_p8 (poly8x8_t __r, poly8x8_t __tab, uint8x8_t __idx) +{ + uint8x8_t __mask = vclt_u8 (__idx, vmov_n_u8 (8)); + poly8x8_t __tbl = vtbl1_p8 (__tab, __idx); + + return vbsl_p8 (__mask, __tbl, __r); +} + +/* vtbx3 */ + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtbx3_s8 (int8x8_t __r, int8x8x3_t __tab, int8x8_t __idx) +{ + uint8x8_t __mask = vclt_u8 (vreinterpret_u8_s8 (__idx), + vmov_n_u8 (24)); + int8x8_t __tbl = vtbl3_s8 (__tab, __idx); + + return vbsl_s8 (__mask, __tbl, __r); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtbx3_u8 (uint8x8_t __r, uint8x8x3_t __tab, uint8x8_t __idx) +{ + uint8x8_t __mask = vclt_u8 (__idx, vmov_n_u8 (24)); + uint8x8_t __tbl = vtbl3_u8 (__tab, __idx); + + return vbsl_u8 (__mask, __tbl, __r); +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtbx3_p8 (poly8x8_t __r, poly8x8x3_t __tab, uint8x8_t __idx) +{ + uint8x8_t __mask = vclt_u8 (__idx, vmov_n_u8 (24)); + poly8x8_t __tbl = vtbl3_p8 (__tab, __idx); + + return vbsl_p8 (__mask, __tbl, __r); +} + +/* vtbx4 */ + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtbx4_s8 (int8x8_t __r, int8x8x4_t __tab, int8x8_t __idx) +{ + int8x8_t result; + int8x16x2_t temp; + __builtin_aarch64_simd_oi __o; + temp.val[0] = vcombine_s8 (__tab.val[0], __tab.val[1]); + temp.val[1] = vcombine_s8 (__tab.val[2], __tab.val[3]); + __o = __builtin_aarch64_set_qregoiv16qi (__o, + (int8x16_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, + (int8x16_t) temp.val[1], 1); + result = __builtin_aarch64_tbx4v8qi (__r, __o, __idx); + return result; +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtbx4_u8 (uint8x8_t __r, uint8x8x4_t __tab, uint8x8_t __idx) +{ + uint8x8_t result; + uint8x16x2_t temp; + __builtin_aarch64_simd_oi __o; + temp.val[0] = vcombine_u8 (__tab.val[0], __tab.val[1]); + temp.val[1] = vcombine_u8 (__tab.val[2], __tab.val[3]); + __o = __builtin_aarch64_set_qregoiv16qi (__o, + (int8x16_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, + (int8x16_t) temp.val[1], 1); + result = (uint8x8_t)__builtin_aarch64_tbx4v8qi ((int8x8_t)__r, __o, + (int8x8_t)__idx); + return result; +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtbx4_p8 (poly8x8_t __r, poly8x8x4_t __tab, uint8x8_t __idx) +{ + poly8x8_t result; + poly8x16x2_t temp; + __builtin_aarch64_simd_oi __o; + temp.val[0] = vcombine_p8 (__tab.val[0], __tab.val[1]); + temp.val[1] = vcombine_p8 (__tab.val[2], __tab.val[3]); + __o = __builtin_aarch64_set_qregoiv16qi (__o, + (int8x16_t) temp.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, + (int8x16_t) temp.val[1], 1); + result = (poly8x8_t)__builtin_aarch64_tbx4v8qi ((int8x8_t)__r, __o, + (int8x8_t)__idx); + return result; +} + +/* vtrn */ + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn1_f16 (float16x4_t __a, float16x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x4_t) {5, 1, 7, 3}); +#else + return __builtin_shuffle (__a, __b, (uint16x4_t) {0, 4, 2, 6}); +#endif +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn1_f32 (float32x2_t __a, float32x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x2_t) {3, 1}); +#else + return __builtin_shuffle (__a, __b, (uint32x2_t) {0, 2}); +#endif +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn1_p8 (poly8x8_t __a, poly8x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint8x8_t) {9, 1, 11, 3, 13, 5, 15, 7}); +#else + return __builtin_shuffle (__a, __b, (uint8x8_t) {0, 8, 2, 10, 4, 12, 6, 14}); +#endif +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn1_p16 (poly16x4_t __a, poly16x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x4_t) {5, 1, 7, 3}); +#else + return __builtin_shuffle (__a, __b, (uint16x4_t) {0, 4, 2, 6}); +#endif +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn1_s8 (int8x8_t __a, int8x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint8x8_t) {9, 1, 11, 3, 13, 5, 15, 7}); +#else + return __builtin_shuffle (__a, __b, (uint8x8_t) {0, 8, 2, 10, 4, 12, 6, 14}); +#endif +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn1_s16 (int16x4_t __a, int16x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x4_t) {5, 1, 7, 3}); +#else + return __builtin_shuffle (__a, __b, (uint16x4_t) {0, 4, 2, 6}); +#endif +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn1_s32 (int32x2_t __a, int32x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x2_t) {3, 1}); +#else + return __builtin_shuffle (__a, __b, (uint32x2_t) {0, 2}); +#endif +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn1_u8 (uint8x8_t __a, uint8x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint8x8_t) {9, 1, 11, 3, 13, 5, 15, 7}); +#else + return __builtin_shuffle (__a, __b, (uint8x8_t) {0, 8, 2, 10, 4, 12, 6, 14}); +#endif +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn1_u16 (uint16x4_t __a, uint16x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x4_t) {5, 1, 7, 3}); +#else + return __builtin_shuffle (__a, __b, (uint16x4_t) {0, 4, 2, 6}); +#endif +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn1_u32 (uint32x2_t __a, uint32x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x2_t) {3, 1}); +#else + return __builtin_shuffle (__a, __b, (uint32x2_t) {0, 2}); +#endif +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn1q_f16 (float16x8_t __a, float16x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x8_t) {9, 1, 11, 3, 13, 5, 15, 7}); +#else + return __builtin_shuffle (__a, __b, (uint16x8_t) {0, 8, 2, 10, 4, 12, 6, 14}); +#endif +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn1q_f32 (float32x4_t __a, float32x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x4_t) {5, 1, 7, 3}); +#else + return __builtin_shuffle (__a, __b, (uint32x4_t) {0, 4, 2, 6}); +#endif +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn1q_f64 (float64x2_t __a, float64x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint64x2_t) {3, 1}); +#else + return __builtin_shuffle (__a, __b, (uint64x2_t) {0, 2}); +#endif +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn1q_p8 (poly8x16_t __a, poly8x16_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, + (uint8x16_t) {17, 1, 19, 3, 21, 5, 23, 7, 25, 9, 27, 11, 29, 13, 31, 15}); +#else + return __builtin_shuffle (__a, __b, + (uint8x16_t) {0, 16, 2, 18, 4, 20, 6, 22, 8, 24, 10, 26, 12, 28, 14, 30}); +#endif +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn1q_p16 (poly16x8_t __a, poly16x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x8_t) {9, 1, 11, 3, 13, 5, 15, 7}); +#else + return __builtin_shuffle (__a, __b, (uint16x8_t) {0, 8, 2, 10, 4, 12, 6, 14}); +#endif +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn1q_s8 (int8x16_t __a, int8x16_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, + (uint8x16_t) {17, 1, 19, 3, 21, 5, 23, 7, 25, 9, 27, 11, 29, 13, 31, 15}); +#else + return __builtin_shuffle (__a, __b, + (uint8x16_t) {0, 16, 2, 18, 4, 20, 6, 22, 8, 24, 10, 26, 12, 28, 14, 30}); +#endif +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn1q_s16 (int16x8_t __a, int16x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x8_t) {9, 1, 11, 3, 13, 5, 15, 7}); +#else + return __builtin_shuffle (__a, __b, (uint16x8_t) {0, 8, 2, 10, 4, 12, 6, 14}); +#endif +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn1q_s32 (int32x4_t __a, int32x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x4_t) {5, 1, 7, 3}); +#else + return __builtin_shuffle (__a, __b, (uint32x4_t) {0, 4, 2, 6}); +#endif +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn1q_s64 (int64x2_t __a, int64x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint64x2_t) {3, 1}); +#else + return __builtin_shuffle (__a, __b, (uint64x2_t) {0, 2}); +#endif +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn1q_u8 (uint8x16_t __a, uint8x16_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, + (uint8x16_t) {17, 1, 19, 3, 21, 5, 23, 7, 25, 9, 27, 11, 29, 13, 31, 15}); +#else + return __builtin_shuffle (__a, __b, + (uint8x16_t) {0, 16, 2, 18, 4, 20, 6, 22, 8, 24, 10, 26, 12, 28, 14, 30}); +#endif +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn1q_u16 (uint16x8_t __a, uint16x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x8_t) {9, 1, 11, 3, 13, 5, 15, 7}); +#else + return __builtin_shuffle (__a, __b, (uint16x8_t) {0, 8, 2, 10, 4, 12, 6, 14}); +#endif +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn1q_u32 (uint32x4_t __a, uint32x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x4_t) {5, 1, 7, 3}); +#else + return __builtin_shuffle (__a, __b, (uint32x4_t) {0, 4, 2, 6}); +#endif +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn1q_u64 (uint64x2_t __a, uint64x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint64x2_t) {3, 1}); +#else + return __builtin_shuffle (__a, __b, (uint64x2_t) {0, 2}); +#endif +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn2_f16 (float16x4_t __a, float16x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x4_t) {4, 0, 6, 2}); +#else + return __builtin_shuffle (__a, __b, (uint16x4_t) {1, 5, 3, 7}); +#endif +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn2_f32 (float32x2_t __a, float32x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x2_t) {2, 0}); +#else + return __builtin_shuffle (__a, __b, (uint32x2_t) {1, 3}); +#endif +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn2_p8 (poly8x8_t __a, poly8x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint8x8_t) {8, 0, 10, 2, 12, 4, 14, 6}); +#else + return __builtin_shuffle (__a, __b, (uint8x8_t) {1, 9, 3, 11, 5, 13, 7, 15}); +#endif +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn2_p16 (poly16x4_t __a, poly16x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x4_t) {4, 0, 6, 2}); +#else + return __builtin_shuffle (__a, __b, (uint16x4_t) {1, 5, 3, 7}); +#endif +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn2_s8 (int8x8_t __a, int8x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint8x8_t) {8, 0, 10, 2, 12, 4, 14, 6}); +#else + return __builtin_shuffle (__a, __b, (uint8x8_t) {1, 9, 3, 11, 5, 13, 7, 15}); +#endif +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn2_s16 (int16x4_t __a, int16x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x4_t) {4, 0, 6, 2}); +#else + return __builtin_shuffle (__a, __b, (uint16x4_t) {1, 5, 3, 7}); +#endif +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn2_s32 (int32x2_t __a, int32x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x2_t) {2, 0}); +#else + return __builtin_shuffle (__a, __b, (uint32x2_t) {1, 3}); +#endif +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn2_u8 (uint8x8_t __a, uint8x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint8x8_t) {8, 0, 10, 2, 12, 4, 14, 6}); +#else + return __builtin_shuffle (__a, __b, (uint8x8_t) {1, 9, 3, 11, 5, 13, 7, 15}); +#endif +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn2_u16 (uint16x4_t __a, uint16x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x4_t) {4, 0, 6, 2}); +#else + return __builtin_shuffle (__a, __b, (uint16x4_t) {1, 5, 3, 7}); +#endif +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn2_u32 (uint32x2_t __a, uint32x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x2_t) {2, 0}); +#else + return __builtin_shuffle (__a, __b, (uint32x2_t) {1, 3}); +#endif +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn2q_f16 (float16x8_t __a, float16x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x8_t) {8, 0, 10, 2, 12, 4, 14, 6}); +#else + return __builtin_shuffle (__a, __b, (uint16x8_t) {1, 9, 3, 11, 5, 13, 7, 15}); +#endif +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn2q_f32 (float32x4_t __a, float32x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x4_t) {4, 0, 6, 2}); +#else + return __builtin_shuffle (__a, __b, (uint32x4_t) {1, 5, 3, 7}); +#endif +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn2q_f64 (float64x2_t __a, float64x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint64x2_t) {2, 0}); +#else + return __builtin_shuffle (__a, __b, (uint64x2_t) {1, 3}); +#endif +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn2q_p8 (poly8x16_t __a, poly8x16_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, + (uint8x16_t) {16, 0, 18, 2, 20, 4, 22, 6, 24, 8, 26, 10, 28, 12, 30, 14}); +#else + return __builtin_shuffle (__a, __b, + (uint8x16_t) {1, 17, 3, 19, 5, 21, 7, 23, 9, 25, 11, 27, 13, 29, 15, 31}); +#endif +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn2q_p16 (poly16x8_t __a, poly16x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x8_t) {8, 0, 10, 2, 12, 4, 14, 6}); +#else + return __builtin_shuffle (__a, __b, (uint16x8_t) {1, 9, 3, 11, 5, 13, 7, 15}); +#endif +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn2q_s8 (int8x16_t __a, int8x16_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, + (uint8x16_t) {16, 0, 18, 2, 20, 4, 22, 6, 24, 8, 26, 10, 28, 12, 30, 14}); +#else + return __builtin_shuffle (__a, __b, + (uint8x16_t) {1, 17, 3, 19, 5, 21, 7, 23, 9, 25, 11, 27, 13, 29, 15, 31}); +#endif +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn2q_s16 (int16x8_t __a, int16x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x8_t) {8, 0, 10, 2, 12, 4, 14, 6}); +#else + return __builtin_shuffle (__a, __b, (uint16x8_t) {1, 9, 3, 11, 5, 13, 7, 15}); +#endif +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn2q_s32 (int32x4_t __a, int32x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x4_t) {4, 0, 6, 2}); +#else + return __builtin_shuffle (__a, __b, (uint32x4_t) {1, 5, 3, 7}); +#endif +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn2q_s64 (int64x2_t __a, int64x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint64x2_t) {2, 0}); +#else + return __builtin_shuffle (__a, __b, (uint64x2_t) {1, 3}); +#endif +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn2q_u8 (uint8x16_t __a, uint8x16_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, + (uint8x16_t) {16, 0, 18, 2, 20, 4, 22, 6, 24, 8, 26, 10, 28, 12, 30, 14}); +#else + return __builtin_shuffle (__a, __b, + (uint8x16_t) {1, 17, 3, 19, 5, 21, 7, 23, 9, 25, 11, 27, 13, 29, 15, 31}); +#endif +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn2q_u16 (uint16x8_t __a, uint16x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x8_t) {8, 0, 10, 2, 12, 4, 14, 6}); +#else + return __builtin_shuffle (__a, __b, (uint16x8_t) {1, 9, 3, 11, 5, 13, 7, 15}); +#endif +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn2q_u32 (uint32x4_t __a, uint32x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x4_t) {4, 0, 6, 2}); +#else + return __builtin_shuffle (__a, __b, (uint32x4_t) {1, 5, 3, 7}); +#endif +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn2q_u64 (uint64x2_t __a, uint64x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint64x2_t) {2, 0}); +#else + return __builtin_shuffle (__a, __b, (uint64x2_t) {1, 3}); +#endif +} + +__extension__ extern __inline float16x4x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn_f16 (float16x4_t __a, float16x4_t __b) +{ + return (float16x4x2_t) {vtrn1_f16 (__a, __b), vtrn2_f16 (__a, __b)}; +} + +__extension__ extern __inline float32x2x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn_f32 (float32x2_t a, float32x2_t b) +{ + return (float32x2x2_t) {vtrn1_f32 (a, b), vtrn2_f32 (a, b)}; +} + +__extension__ extern __inline poly8x8x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn_p8 (poly8x8_t a, poly8x8_t b) +{ + return (poly8x8x2_t) {vtrn1_p8 (a, b), vtrn2_p8 (a, b)}; +} + +__extension__ extern __inline poly16x4x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn_p16 (poly16x4_t a, poly16x4_t b) +{ + return (poly16x4x2_t) {vtrn1_p16 (a, b), vtrn2_p16 (a, b)}; +} + +__extension__ extern __inline int8x8x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn_s8 (int8x8_t a, int8x8_t b) +{ + return (int8x8x2_t) {vtrn1_s8 (a, b), vtrn2_s8 (a, b)}; +} + +__extension__ extern __inline int16x4x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn_s16 (int16x4_t a, int16x4_t b) +{ + return (int16x4x2_t) {vtrn1_s16 (a, b), vtrn2_s16 (a, b)}; +} + +__extension__ extern __inline int32x2x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn_s32 (int32x2_t a, int32x2_t b) +{ + return (int32x2x2_t) {vtrn1_s32 (a, b), vtrn2_s32 (a, b)}; +} + +__extension__ extern __inline uint8x8x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn_u8 (uint8x8_t a, uint8x8_t b) +{ + return (uint8x8x2_t) {vtrn1_u8 (a, b), vtrn2_u8 (a, b)}; +} + +__extension__ extern __inline uint16x4x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn_u16 (uint16x4_t a, uint16x4_t b) +{ + return (uint16x4x2_t) {vtrn1_u16 (a, b), vtrn2_u16 (a, b)}; +} + +__extension__ extern __inline uint32x2x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrn_u32 (uint32x2_t a, uint32x2_t b) +{ + return (uint32x2x2_t) {vtrn1_u32 (a, b), vtrn2_u32 (a, b)}; +} + +__extension__ extern __inline float16x8x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrnq_f16 (float16x8_t __a, float16x8_t __b) +{ + return (float16x8x2_t) {vtrn1q_f16 (__a, __b), vtrn2q_f16 (__a, __b)}; +} + +__extension__ extern __inline float32x4x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrnq_f32 (float32x4_t a, float32x4_t b) +{ + return (float32x4x2_t) {vtrn1q_f32 (a, b), vtrn2q_f32 (a, b)}; +} + +__extension__ extern __inline poly8x16x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrnq_p8 (poly8x16_t a, poly8x16_t b) +{ + return (poly8x16x2_t) {vtrn1q_p8 (a, b), vtrn2q_p8 (a, b)}; +} + +__extension__ extern __inline poly16x8x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrnq_p16 (poly16x8_t a, poly16x8_t b) +{ + return (poly16x8x2_t) {vtrn1q_p16 (a, b), vtrn2q_p16 (a, b)}; +} + +__extension__ extern __inline int8x16x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrnq_s8 (int8x16_t a, int8x16_t b) +{ + return (int8x16x2_t) {vtrn1q_s8 (a, b), vtrn2q_s8 (a, b)}; +} + +__extension__ extern __inline int16x8x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrnq_s16 (int16x8_t a, int16x8_t b) +{ + return (int16x8x2_t) {vtrn1q_s16 (a, b), vtrn2q_s16 (a, b)}; +} + +__extension__ extern __inline int32x4x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrnq_s32 (int32x4_t a, int32x4_t b) +{ + return (int32x4x2_t) {vtrn1q_s32 (a, b), vtrn2q_s32 (a, b)}; +} + +__extension__ extern __inline uint8x16x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrnq_u8 (uint8x16_t a, uint8x16_t b) +{ + return (uint8x16x2_t) {vtrn1q_u8 (a, b), vtrn2q_u8 (a, b)}; +} + +__extension__ extern __inline uint16x8x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrnq_u16 (uint16x8_t a, uint16x8_t b) +{ + return (uint16x8x2_t) {vtrn1q_u16 (a, b), vtrn2q_u16 (a, b)}; +} + +__extension__ extern __inline uint32x4x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtrnq_u32 (uint32x4_t a, uint32x4_t b) +{ + return (uint32x4x2_t) {vtrn1q_u32 (a, b), vtrn2q_u32 (a, b)}; +} + +/* vtst */ + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtst_s8 (int8x8_t __a, int8x8_t __b) +{ + return (uint8x8_t) ((__a & __b) != 0); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtst_s16 (int16x4_t __a, int16x4_t __b) +{ + return (uint16x4_t) ((__a & __b) != 0); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtst_s32 (int32x2_t __a, int32x2_t __b) +{ + return (uint32x2_t) ((__a & __b) != 0); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtst_s64 (int64x1_t __a, int64x1_t __b) +{ + return (uint64x1_t) ((__a & __b) != __AARCH64_INT64_C (0)); +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtst_u8 (uint8x8_t __a, uint8x8_t __b) +{ + return ((__a & __b) != 0); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtst_u16 (uint16x4_t __a, uint16x4_t __b) +{ + return ((__a & __b) != 0); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtst_u32 (uint32x2_t __a, uint32x2_t __b) +{ + return ((__a & __b) != 0); +} + +__extension__ extern __inline uint64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtst_u64 (uint64x1_t __a, uint64x1_t __b) +{ + return ((__a & __b) != __AARCH64_UINT64_C (0)); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtstq_s8 (int8x16_t __a, int8x16_t __b) +{ + return (uint8x16_t) ((__a & __b) != 0); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtstq_s16 (int16x8_t __a, int16x8_t __b) +{ + return (uint16x8_t) ((__a & __b) != 0); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtstq_s32 (int32x4_t __a, int32x4_t __b) +{ + return (uint32x4_t) ((__a & __b) != 0); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtstq_s64 (int64x2_t __a, int64x2_t __b) +{ + return (uint64x2_t) ((__a & __b) != __AARCH64_INT64_C (0)); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtstq_u8 (uint8x16_t __a, uint8x16_t __b) +{ + return ((__a & __b) != 0); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtstq_u16 (uint16x8_t __a, uint16x8_t __b) +{ + return ((__a & __b) != 0); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtstq_u32 (uint32x4_t __a, uint32x4_t __b) +{ + return ((__a & __b) != 0); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtstq_u64 (uint64x2_t __a, uint64x2_t __b) +{ + return ((__a & __b) != __AARCH64_UINT64_C (0)); +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtstd_s64 (int64_t __a, int64_t __b) +{ + return (__a & __b) ? -1ll : 0ll; +} + +__extension__ extern __inline uint64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vtstd_u64 (uint64_t __a, uint64_t __b) +{ + return (__a & __b) ? -1ll : 0ll; +} + +/* vuqadd */ + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuqadd_s8 (int8x8_t __a, uint8x8_t __b) +{ + return __builtin_aarch64_suqaddv8qi_ssu (__a, __b); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuqadd_s16 (int16x4_t __a, uint16x4_t __b) +{ + return __builtin_aarch64_suqaddv4hi_ssu (__a, __b); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuqadd_s32 (int32x2_t __a, uint32x2_t __b) +{ + return __builtin_aarch64_suqaddv2si_ssu (__a, __b); +} + +__extension__ extern __inline int64x1_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuqadd_s64 (int64x1_t __a, uint64x1_t __b) +{ + return (int64x1_t) {__builtin_aarch64_suqadddi_ssu (__a[0], __b[0])}; +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuqaddq_s8 (int8x16_t __a, uint8x16_t __b) +{ + return __builtin_aarch64_suqaddv16qi_ssu (__a, __b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuqaddq_s16 (int16x8_t __a, uint16x8_t __b) +{ + return __builtin_aarch64_suqaddv8hi_ssu (__a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuqaddq_s32 (int32x4_t __a, uint32x4_t __b) +{ + return __builtin_aarch64_suqaddv4si_ssu (__a, __b); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuqaddq_s64 (int64x2_t __a, uint64x2_t __b) +{ + return __builtin_aarch64_suqaddv2di_ssu (__a, __b); +} + +__extension__ extern __inline int8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuqaddb_s8 (int8_t __a, uint8_t __b) +{ + return __builtin_aarch64_suqaddqi_ssu (__a, __b); +} + +__extension__ extern __inline int16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuqaddh_s16 (int16_t __a, uint16_t __b) +{ + return __builtin_aarch64_suqaddhi_ssu (__a, __b); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuqadds_s32 (int32_t __a, uint32_t __b) +{ + return __builtin_aarch64_suqaddsi_ssu (__a, __b); +} + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuqaddd_s64 (int64_t __a, uint64_t __b) +{ + return __builtin_aarch64_suqadddi_ssu (__a, __b); +} + +#define __DEFINTERLEAVE(op, rettype, intype, funcsuffix, Q) \ + __extension__ extern __inline rettype \ + __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) \ + v ## op ## Q ## _ ## funcsuffix (intype a, intype b) \ + { \ + return (rettype) {v ## op ## 1 ## Q ## _ ## funcsuffix (a, b), \ + v ## op ## 2 ## Q ## _ ## funcsuffix (a, b)}; \ + } + +#define __INTERLEAVE_LIST(op) \ + __DEFINTERLEAVE (op, float16x4x2_t, float16x4_t, f16,) \ + __DEFINTERLEAVE (op, float32x2x2_t, float32x2_t, f32,) \ + __DEFINTERLEAVE (op, poly8x8x2_t, poly8x8_t, p8,) \ + __DEFINTERLEAVE (op, poly16x4x2_t, poly16x4_t, p16,) \ + __DEFINTERLEAVE (op, int8x8x2_t, int8x8_t, s8,) \ + __DEFINTERLEAVE (op, int16x4x2_t, int16x4_t, s16,) \ + __DEFINTERLEAVE (op, int32x2x2_t, int32x2_t, s32,) \ + __DEFINTERLEAVE (op, uint8x8x2_t, uint8x8_t, u8,) \ + __DEFINTERLEAVE (op, uint16x4x2_t, uint16x4_t, u16,) \ + __DEFINTERLEAVE (op, uint32x2x2_t, uint32x2_t, u32,) \ + __DEFINTERLEAVE (op, float16x8x2_t, float16x8_t, f16, q) \ + __DEFINTERLEAVE (op, float32x4x2_t, float32x4_t, f32, q) \ + __DEFINTERLEAVE (op, poly8x16x2_t, poly8x16_t, p8, q) \ + __DEFINTERLEAVE (op, poly16x8x2_t, poly16x8_t, p16, q) \ + __DEFINTERLEAVE (op, int8x16x2_t, int8x16_t, s8, q) \ + __DEFINTERLEAVE (op, int16x8x2_t, int16x8_t, s16, q) \ + __DEFINTERLEAVE (op, int32x4x2_t, int32x4_t, s32, q) \ + __DEFINTERLEAVE (op, uint8x16x2_t, uint8x16_t, u8, q) \ + __DEFINTERLEAVE (op, uint16x8x2_t, uint16x8_t, u16, q) \ + __DEFINTERLEAVE (op, uint32x4x2_t, uint32x4_t, u32, q) + +/* vuzp */ + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp1_f16 (float16x4_t __a, float16x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x4_t) {5, 7, 1, 3}); +#else + return __builtin_shuffle (__a, __b, (uint16x4_t) {0, 2, 4, 6}); +#endif +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp1_f32 (float32x2_t __a, float32x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x2_t) {3, 1}); +#else + return __builtin_shuffle (__a, __b, (uint32x2_t) {0, 2}); +#endif +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp1_p8 (poly8x8_t __a, poly8x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint8x8_t) {9, 11, 13, 15, 1, 3, 5, 7}); +#else + return __builtin_shuffle (__a, __b, (uint8x8_t) {0, 2, 4, 6, 8, 10, 12, 14}); +#endif +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp1_p16 (poly16x4_t __a, poly16x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x4_t) {5, 7, 1, 3}); +#else + return __builtin_shuffle (__a, __b, (uint16x4_t) {0, 2, 4, 6}); +#endif +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp1_s8 (int8x8_t __a, int8x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint8x8_t) {9, 11, 13, 15, 1, 3, 5, 7}); +#else + return __builtin_shuffle (__a, __b, (uint8x8_t) {0, 2, 4, 6, 8, 10, 12, 14}); +#endif +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp1_s16 (int16x4_t __a, int16x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x4_t) {5, 7, 1, 3}); +#else + return __builtin_shuffle (__a, __b, (uint16x4_t) {0, 2, 4, 6}); +#endif +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp1_s32 (int32x2_t __a, int32x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x2_t) {3, 1}); +#else + return __builtin_shuffle (__a, __b, (uint32x2_t) {0, 2}); +#endif +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp1_u8 (uint8x8_t __a, uint8x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint8x8_t) {9, 11, 13, 15, 1, 3, 5, 7}); +#else + return __builtin_shuffle (__a, __b, (uint8x8_t) {0, 2, 4, 6, 8, 10, 12, 14}); +#endif +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp1_u16 (uint16x4_t __a, uint16x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x4_t) {5, 7, 1, 3}); +#else + return __builtin_shuffle (__a, __b, (uint16x4_t) {0, 2, 4, 6}); +#endif +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp1_u32 (uint32x2_t __a, uint32x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x2_t) {3, 1}); +#else + return __builtin_shuffle (__a, __b, (uint32x2_t) {0, 2}); +#endif +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp1q_f16 (float16x8_t __a, float16x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x8_t) {9, 11, 13, 15, 1, 3, 5, 7}); +#else + return __builtin_shuffle (__a, __b, (uint16x8_t) {0, 2, 4, 6, 8, 10, 12, 14}); +#endif +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp1q_f32 (float32x4_t __a, float32x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x4_t) {5, 7, 1, 3}); +#else + return __builtin_shuffle (__a, __b, (uint32x4_t) {0, 2, 4, 6}); +#endif +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp1q_f64 (float64x2_t __a, float64x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint64x2_t) {3, 1}); +#else + return __builtin_shuffle (__a, __b, (uint64x2_t) {0, 2}); +#endif +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp1q_p8 (poly8x16_t __a, poly8x16_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint8x16_t) + {17, 19, 21, 23, 25, 27, 29, 31, 1, 3, 5, 7, 9, 11, 13, 15}); +#else + return __builtin_shuffle (__a, __b, (uint8x16_t) + {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30}); +#endif +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp1q_p16 (poly16x8_t __a, poly16x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x8_t) {9, 11, 13, 15, 1, 3, 5, 7}); +#else + return __builtin_shuffle (__a, __b, (uint16x8_t) {0, 2, 4, 6, 8, 10, 12, 14}); +#endif +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp1q_s8 (int8x16_t __a, int8x16_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, + (uint8x16_t) {17, 19, 21, 23, 25, 27, 29, 31, 1, 3, 5, 7, 9, 11, 13, 15}); +#else + return __builtin_shuffle (__a, __b, + (uint8x16_t) {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30}); +#endif +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp1q_s16 (int16x8_t __a, int16x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x8_t) {9, 11, 13, 15, 1, 3, 5, 7}); +#else + return __builtin_shuffle (__a, __b, (uint16x8_t) {0, 2, 4, 6, 8, 10, 12, 14}); +#endif +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp1q_s32 (int32x4_t __a, int32x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x4_t) {5, 7, 1, 3}); +#else + return __builtin_shuffle (__a, __b, (uint32x4_t) {0, 2, 4, 6}); +#endif +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp1q_s64 (int64x2_t __a, int64x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint64x2_t) {3, 1}); +#else + return __builtin_shuffle (__a, __b, (uint64x2_t) {0, 2}); +#endif +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp1q_u8 (uint8x16_t __a, uint8x16_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, + (uint8x16_t) {17, 19, 21, 23, 25, 27, 29, 31, 1, 3, 5, 7, 9, 11, 13, 15}); +#else + return __builtin_shuffle (__a, __b, + (uint8x16_t) {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30}); +#endif +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp1q_u16 (uint16x8_t __a, uint16x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x8_t) {9, 11, 13, 15, 1, 3, 5, 7}); +#else + return __builtin_shuffle (__a, __b, (uint16x8_t) {0, 2, 4, 6, 8, 10, 12, 14}); +#endif +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp1q_u32 (uint32x4_t __a, uint32x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x4_t) {5, 7, 1, 3}); +#else + return __builtin_shuffle (__a, __b, (uint32x4_t) {0, 2, 4, 6}); +#endif +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp1q_u64 (uint64x2_t __a, uint64x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint64x2_t) {3, 1}); +#else + return __builtin_shuffle (__a, __b, (uint64x2_t) {0, 2}); +#endif +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp2_f16 (float16x4_t __a, float16x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x4_t) {4, 6, 0, 2}); +#else + return __builtin_shuffle (__a, __b, (uint16x4_t) {1, 3, 5, 7}); +#endif +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp2_f32 (float32x2_t __a, float32x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x2_t) {2, 0}); +#else + return __builtin_shuffle (__a, __b, (uint32x2_t) {1, 3}); +#endif +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp2_p8 (poly8x8_t __a, poly8x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint8x8_t) {8, 10, 12, 14, 0, 2, 4, 6}); +#else + return __builtin_shuffle (__a, __b, (uint8x8_t) {1, 3, 5, 7, 9, 11, 13, 15}); +#endif +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp2_p16 (poly16x4_t __a, poly16x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x4_t) {4, 6, 0, 2}); +#else + return __builtin_shuffle (__a, __b, (uint16x4_t) {1, 3, 5, 7}); +#endif +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp2_s8 (int8x8_t __a, int8x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint8x8_t) {8, 10, 12, 14, 0, 2, 4, 6}); +#else + return __builtin_shuffle (__a, __b, (uint8x8_t) {1, 3, 5, 7, 9, 11, 13, 15}); +#endif +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp2_s16 (int16x4_t __a, int16x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x4_t) {4, 6, 0, 2}); +#else + return __builtin_shuffle (__a, __b, (uint16x4_t) {1, 3, 5, 7}); +#endif +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp2_s32 (int32x2_t __a, int32x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x2_t) {2, 0}); +#else + return __builtin_shuffle (__a, __b, (uint32x2_t) {1, 3}); +#endif +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp2_u8 (uint8x8_t __a, uint8x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint8x8_t) {8, 10, 12, 14, 0, 2, 4, 6}); +#else + return __builtin_shuffle (__a, __b, (uint8x8_t) {1, 3, 5, 7, 9, 11, 13, 15}); +#endif +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp2_u16 (uint16x4_t __a, uint16x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x4_t) {4, 6, 0, 2}); +#else + return __builtin_shuffle (__a, __b, (uint16x4_t) {1, 3, 5, 7}); +#endif +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp2_u32 (uint32x2_t __a, uint32x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x2_t) {2, 0}); +#else + return __builtin_shuffle (__a, __b, (uint32x2_t) {1, 3}); +#endif +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp2q_f16 (float16x8_t __a, float16x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x8_t) {8, 10, 12, 14, 0, 2, 4, 6}); +#else + return __builtin_shuffle (__a, __b, (uint16x8_t) {1, 3, 5, 7, 9, 11, 13, 15}); +#endif +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp2q_f32 (float32x4_t __a, float32x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x4_t) {4, 6, 0, 2}); +#else + return __builtin_shuffle (__a, __b, (uint32x4_t) {1, 3, 5, 7}); +#endif +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp2q_f64 (float64x2_t __a, float64x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint64x2_t) {2, 0}); +#else + return __builtin_shuffle (__a, __b, (uint64x2_t) {1, 3}); +#endif +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp2q_p8 (poly8x16_t __a, poly8x16_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, + (uint8x16_t) {16, 18, 20, 22, 24, 26, 28, 30, 0, 2, 4, 6, 8, 10, 12, 14}); +#else + return __builtin_shuffle (__a, __b, + (uint8x16_t) {1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31}); +#endif +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp2q_p16 (poly16x8_t __a, poly16x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x8_t) {8, 10, 12, 14, 0, 2, 4, 6}); +#else + return __builtin_shuffle (__a, __b, (uint16x8_t) {1, 3, 5, 7, 9, 11, 13, 15}); +#endif +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp2q_s8 (int8x16_t __a, int8x16_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, + (uint8x16_t) {16, 18, 20, 22, 24, 26, 28, 30, 0, 2, 4, 6, 8, 10, 12, 14}); +#else + return __builtin_shuffle (__a, __b, + (uint8x16_t) {1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31}); +#endif +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp2q_s16 (int16x8_t __a, int16x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x8_t) {8, 10, 12, 14, 0, 2, 4, 6}); +#else + return __builtin_shuffle (__a, __b, (uint16x8_t) {1, 3, 5, 7, 9, 11, 13, 15}); +#endif +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp2q_s32 (int32x4_t __a, int32x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x4_t) {4, 6, 0, 2}); +#else + return __builtin_shuffle (__a, __b, (uint32x4_t) {1, 3, 5, 7}); +#endif +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp2q_s64 (int64x2_t __a, int64x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint64x2_t) {2, 0}); +#else + return __builtin_shuffle (__a, __b, (uint64x2_t) {1, 3}); +#endif +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp2q_u8 (uint8x16_t __a, uint8x16_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint8x16_t) + {16, 18, 20, 22, 24, 26, 28, 30, 0, 2, 4, 6, 8, 10, 12, 14}); +#else + return __builtin_shuffle (__a, __b, (uint8x16_t) + {1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31}); +#endif +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp2q_u16 (uint16x8_t __a, uint16x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x8_t) {8, 10, 12, 14, 0, 2, 4, 6}); +#else + return __builtin_shuffle (__a, __b, (uint16x8_t) {1, 3, 5, 7, 9, 11, 13, 15}); +#endif +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp2q_u32 (uint32x4_t __a, uint32x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x4_t) {4, 6, 0, 2}); +#else + return __builtin_shuffle (__a, __b, (uint32x4_t) {1, 3, 5, 7}); +#endif +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vuzp2q_u64 (uint64x2_t __a, uint64x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint64x2_t) {2, 0}); +#else + return __builtin_shuffle (__a, __b, (uint64x2_t) {1, 3}); +#endif +} + +__INTERLEAVE_LIST (uzp) + +/* vzip */ + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip1_f16 (float16x4_t __a, float16x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x4_t) {6, 2, 7, 3}); +#else + return __builtin_shuffle (__a, __b, (uint16x4_t) {0, 4, 1, 5}); +#endif +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip1_f32 (float32x2_t __a, float32x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x2_t) {3, 1}); +#else + return __builtin_shuffle (__a, __b, (uint32x2_t) {0, 2}); +#endif +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip1_p8 (poly8x8_t __a, poly8x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint8x8_t) {12, 4, 13, 5, 14, 6, 15, 7}); +#else + return __builtin_shuffle (__a, __b, (uint8x8_t) {0, 8, 1, 9, 2, 10, 3, 11}); +#endif +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip1_p16 (poly16x4_t __a, poly16x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x4_t) {6, 2, 7, 3}); +#else + return __builtin_shuffle (__a, __b, (uint16x4_t) {0, 4, 1, 5}); +#endif +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip1_s8 (int8x8_t __a, int8x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint8x8_t) {12, 4, 13, 5, 14, 6, 15, 7}); +#else + return __builtin_shuffle (__a, __b, (uint8x8_t) {0, 8, 1, 9, 2, 10, 3, 11}); +#endif +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip1_s16 (int16x4_t __a, int16x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x4_t) {6, 2, 7, 3}); +#else + return __builtin_shuffle (__a, __b, (uint16x4_t) {0, 4, 1, 5}); +#endif +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip1_s32 (int32x2_t __a, int32x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x2_t) {3, 1}); +#else + return __builtin_shuffle (__a, __b, (uint32x2_t) {0, 2}); +#endif +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip1_u8 (uint8x8_t __a, uint8x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint8x8_t) {12, 4, 13, 5, 14, 6, 15, 7}); +#else + return __builtin_shuffle (__a, __b, (uint8x8_t) {0, 8, 1, 9, 2, 10, 3, 11}); +#endif +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip1_u16 (uint16x4_t __a, uint16x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x4_t) {6, 2, 7, 3}); +#else + return __builtin_shuffle (__a, __b, (uint16x4_t) {0, 4, 1, 5}); +#endif +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip1_u32 (uint32x2_t __a, uint32x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x2_t) {3, 1}); +#else + return __builtin_shuffle (__a, __b, (uint32x2_t) {0, 2}); +#endif +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip1q_f16 (float16x8_t __a, float16x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, + (uint16x8_t) {12, 4, 13, 5, 14, 6, 15, 7}); +#else + return __builtin_shuffle (__a, __b, + (uint16x8_t) {0, 8, 1, 9, 2, 10, 3, 11}); +#endif +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip1q_f32 (float32x4_t __a, float32x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x4_t) {6, 2, 7, 3}); +#else + return __builtin_shuffle (__a, __b, (uint32x4_t) {0, 4, 1, 5}); +#endif +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip1q_f64 (float64x2_t __a, float64x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint64x2_t) {3, 1}); +#else + return __builtin_shuffle (__a, __b, (uint64x2_t) {0, 2}); +#endif +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip1q_p8 (poly8x16_t __a, poly8x16_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint8x16_t) + {24, 8, 25, 9, 26, 10, 27, 11, 28, 12, 29, 13, 30, 14, 31, 15}); +#else + return __builtin_shuffle (__a, __b, (uint8x16_t) + {0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23}); +#endif +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip1q_p16 (poly16x8_t __a, poly16x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x8_t) + {12, 4, 13, 5, 14, 6, 15, 7}); +#else + return __builtin_shuffle (__a, __b, (uint16x8_t) {0, 8, 1, 9, 2, 10, 3, 11}); +#endif +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip1q_s8 (int8x16_t __a, int8x16_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint8x16_t) + {24, 8, 25, 9, 26, 10, 27, 11, 28, 12, 29, 13, 30, 14, 31, 15}); +#else + return __builtin_shuffle (__a, __b, (uint8x16_t) + {0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23}); +#endif +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip1q_s16 (int16x8_t __a, int16x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x8_t) + {12, 4, 13, 5, 14, 6, 15, 7}); +#else + return __builtin_shuffle (__a, __b, (uint16x8_t) {0, 8, 1, 9, 2, 10, 3, 11}); +#endif +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip1q_s32 (int32x4_t __a, int32x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x4_t) {6, 2, 7, 3}); +#else + return __builtin_shuffle (__a, __b, (uint32x4_t) {0, 4, 1, 5}); +#endif +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip1q_s64 (int64x2_t __a, int64x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint64x2_t) {3, 1}); +#else + return __builtin_shuffle (__a, __b, (uint64x2_t) {0, 2}); +#endif +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip1q_u8 (uint8x16_t __a, uint8x16_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint8x16_t) + {24, 8, 25, 9, 26, 10, 27, 11, 28, 12, 29, 13, 30, 14, 31, 15}); +#else + return __builtin_shuffle (__a, __b, (uint8x16_t) + {0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23}); +#endif +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip1q_u16 (uint16x8_t __a, uint16x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x8_t) + {12, 4, 13, 5, 14, 6, 15, 7}); +#else + return __builtin_shuffle (__a, __b, (uint16x8_t) {0, 8, 1, 9, 2, 10, 3, 11}); +#endif +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip1q_u32 (uint32x4_t __a, uint32x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x4_t) {6, 2, 7, 3}); +#else + return __builtin_shuffle (__a, __b, (uint32x4_t) {0, 4, 1, 5}); +#endif +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip1q_u64 (uint64x2_t __a, uint64x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint64x2_t) {3, 1}); +#else + return __builtin_shuffle (__a, __b, (uint64x2_t) {0, 2}); +#endif +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip2_f16 (float16x4_t __a, float16x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x4_t) {4, 0, 5, 1}); +#else + return __builtin_shuffle (__a, __b, (uint16x4_t) {2, 6, 3, 7}); +#endif +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip2_f32 (float32x2_t __a, float32x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x2_t) {2, 0}); +#else + return __builtin_shuffle (__a, __b, (uint32x2_t) {1, 3}); +#endif +} + +__extension__ extern __inline poly8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip2_p8 (poly8x8_t __a, poly8x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint8x8_t) {8, 0, 9, 1, 10, 2, 11, 3}); +#else + return __builtin_shuffle (__a, __b, (uint8x8_t) {4, 12, 5, 13, 6, 14, 7, 15}); +#endif +} + +__extension__ extern __inline poly16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip2_p16 (poly16x4_t __a, poly16x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x4_t) {4, 0, 5, 1}); +#else + return __builtin_shuffle (__a, __b, (uint16x4_t) {2, 6, 3, 7}); +#endif +} + +__extension__ extern __inline int8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip2_s8 (int8x8_t __a, int8x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint8x8_t) {8, 0, 9, 1, 10, 2, 11, 3}); +#else + return __builtin_shuffle (__a, __b, (uint8x8_t) {4, 12, 5, 13, 6, 14, 7, 15}); +#endif +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip2_s16 (int16x4_t __a, int16x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x4_t) {4, 0, 5, 1}); +#else + return __builtin_shuffle (__a, __b, (uint16x4_t) {2, 6, 3, 7}); +#endif +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip2_s32 (int32x2_t __a, int32x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x2_t) {2, 0}); +#else + return __builtin_shuffle (__a, __b, (uint32x2_t) {1, 3}); +#endif +} + +__extension__ extern __inline uint8x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip2_u8 (uint8x8_t __a, uint8x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint8x8_t) {8, 0, 9, 1, 10, 2, 11, 3}); +#else + return __builtin_shuffle (__a, __b, (uint8x8_t) {4, 12, 5, 13, 6, 14, 7, 15}); +#endif +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip2_u16 (uint16x4_t __a, uint16x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x4_t) {4, 0, 5, 1}); +#else + return __builtin_shuffle (__a, __b, (uint16x4_t) {2, 6, 3, 7}); +#endif +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip2_u32 (uint32x2_t __a, uint32x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x2_t) {2, 0}); +#else + return __builtin_shuffle (__a, __b, (uint32x2_t) {1, 3}); +#endif +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip2q_f16 (float16x8_t __a, float16x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, + (uint16x8_t) {8, 0, 9, 1, 10, 2, 11, 3}); +#else + return __builtin_shuffle (__a, __b, + (uint16x8_t) {4, 12, 5, 13, 6, 14, 7, 15}); +#endif +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip2q_f32 (float32x4_t __a, float32x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x4_t) {4, 0, 5, 1}); +#else + return __builtin_shuffle (__a, __b, (uint32x4_t) {2, 6, 3, 7}); +#endif +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip2q_f64 (float64x2_t __a, float64x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint64x2_t) {2, 0}); +#else + return __builtin_shuffle (__a, __b, (uint64x2_t) {1, 3}); +#endif +} + +__extension__ extern __inline poly8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip2q_p8 (poly8x16_t __a, poly8x16_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint8x16_t) + {16, 0, 17, 1, 18, 2, 19, 3, 20, 4, 21, 5, 22, 6, 23, 7}); +#else + return __builtin_shuffle (__a, __b, (uint8x16_t) + {8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31}); +#endif +} + +__extension__ extern __inline poly16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip2q_p16 (poly16x8_t __a, poly16x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x8_t) {8, 0, 9, 1, 10, 2, 11, 3}); +#else + return __builtin_shuffle (__a, __b, (uint16x8_t) + {4, 12, 5, 13, 6, 14, 7, 15}); +#endif +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip2q_s8 (int8x16_t __a, int8x16_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint8x16_t) + {16, 0, 17, 1, 18, 2, 19, 3, 20, 4, 21, 5, 22, 6, 23, 7}); +#else + return __builtin_shuffle (__a, __b, (uint8x16_t) + {8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31}); +#endif +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip2q_s16 (int16x8_t __a, int16x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x8_t) {8, 0, 9, 1, 10, 2, 11, 3}); +#else + return __builtin_shuffle (__a, __b, (uint16x8_t) + {4, 12, 5, 13, 6, 14, 7, 15}); +#endif +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip2q_s32 (int32x4_t __a, int32x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x4_t) {4, 0, 5, 1}); +#else + return __builtin_shuffle (__a, __b, (uint32x4_t) {2, 6, 3, 7}); +#endif +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip2q_s64 (int64x2_t __a, int64x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint64x2_t) {2, 0}); +#else + return __builtin_shuffle (__a, __b, (uint64x2_t) {1, 3}); +#endif +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip2q_u8 (uint8x16_t __a, uint8x16_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint8x16_t) + {16, 0, 17, 1, 18, 2, 19, 3, 20, 4, 21, 5, 22, 6, 23, 7}); +#else + return __builtin_shuffle (__a, __b, (uint8x16_t) + {8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31}); +#endif +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip2q_u16 (uint16x8_t __a, uint16x8_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint16x8_t) {8, 0, 9, 1, 10, 2, 11, 3}); +#else + return __builtin_shuffle (__a, __b, (uint16x8_t) + {4, 12, 5, 13, 6, 14, 7, 15}); +#endif +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip2q_u32 (uint32x4_t __a, uint32x4_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint32x4_t) {4, 0, 5, 1}); +#else + return __builtin_shuffle (__a, __b, (uint32x4_t) {2, 6, 3, 7}); +#endif +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vzip2q_u64 (uint64x2_t __a, uint64x2_t __b) +{ +#ifdef __AARCH64EB__ + return __builtin_shuffle (__a, __b, (uint64x2_t) {2, 0}); +#else + return __builtin_shuffle (__a, __b, (uint64x2_t) {1, 3}); +#endif +} + +__INTERLEAVE_LIST (zip) + +#undef __INTERLEAVE_LIST +#undef __DEFINTERLEAVE + +/* End of optimal implementations in approved order. */ + +#pragma GCC pop_options + +/* ARMv8.2-A FP16 intrinsics. */ + +#include "arm_fp16.h" + +#pragma GCC push_options +#pragma GCC target ("arch=armv8.2-a+fp16") + +/* ARMv8.2-A FP16 one operand vector intrinsics. */ + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabs_f16 (float16x4_t __a) +{ + return __builtin_aarch64_absv4hf (__a); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabsq_f16 (float16x8_t __a) +{ + return __builtin_aarch64_absv8hf (__a); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqz_f16 (float16x4_t __a) +{ + return __builtin_aarch64_cmeqv4hf_uss (__a, vdup_n_f16 (0.0f)); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqzq_f16 (float16x8_t __a) +{ + return __builtin_aarch64_cmeqv8hf_uss (__a, vdupq_n_f16 (0.0f)); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgez_f16 (float16x4_t __a) +{ + return __builtin_aarch64_cmgev4hf_uss (__a, vdup_n_f16 (0.0f)); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgezq_f16 (float16x8_t __a) +{ + return __builtin_aarch64_cmgev8hf_uss (__a, vdupq_n_f16 (0.0f)); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgtz_f16 (float16x4_t __a) +{ + return __builtin_aarch64_cmgtv4hf_uss (__a, vdup_n_f16 (0.0f)); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgtzq_f16 (float16x8_t __a) +{ + return __builtin_aarch64_cmgtv8hf_uss (__a, vdupq_n_f16 (0.0f)); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclez_f16 (float16x4_t __a) +{ + return __builtin_aarch64_cmlev4hf_uss (__a, vdup_n_f16 (0.0f)); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclezq_f16 (float16x8_t __a) +{ + return __builtin_aarch64_cmlev8hf_uss (__a, vdupq_n_f16 (0.0f)); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcltz_f16 (float16x4_t __a) +{ + return __builtin_aarch64_cmltv4hf_uss (__a, vdup_n_f16 (0.0f)); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcltzq_f16 (float16x8_t __a) +{ + return __builtin_aarch64_cmltv8hf_uss (__a, vdupq_n_f16 (0.0f)); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_f16_s16 (int16x4_t __a) +{ + return __builtin_aarch64_floatv4hiv4hf (__a); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtq_f16_s16 (int16x8_t __a) +{ + return __builtin_aarch64_floatv8hiv8hf (__a); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_f16_u16 (uint16x4_t __a) +{ + return __builtin_aarch64_floatunsv4hiv4hf ((int16x4_t) __a); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtq_f16_u16 (uint16x8_t __a) +{ + return __builtin_aarch64_floatunsv8hiv8hf ((int16x8_t) __a); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_s16_f16 (float16x4_t __a) +{ + return __builtin_aarch64_lbtruncv4hfv4hi (__a); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtq_s16_f16 (float16x8_t __a) +{ + return __builtin_aarch64_lbtruncv8hfv8hi (__a); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_u16_f16 (float16x4_t __a) +{ + return __builtin_aarch64_lbtruncuv4hfv4hi_us (__a); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtq_u16_f16 (float16x8_t __a) +{ + return __builtin_aarch64_lbtruncuv8hfv8hi_us (__a); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvta_s16_f16 (float16x4_t __a) +{ + return __builtin_aarch64_lroundv4hfv4hi (__a); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtaq_s16_f16 (float16x8_t __a) +{ + return __builtin_aarch64_lroundv8hfv8hi (__a); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvta_u16_f16 (float16x4_t __a) +{ + return __builtin_aarch64_lrounduv4hfv4hi_us (__a); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtaq_u16_f16 (float16x8_t __a) +{ + return __builtin_aarch64_lrounduv8hfv8hi_us (__a); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtm_s16_f16 (float16x4_t __a) +{ + return __builtin_aarch64_lfloorv4hfv4hi (__a); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtmq_s16_f16 (float16x8_t __a) +{ + return __builtin_aarch64_lfloorv8hfv8hi (__a); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtm_u16_f16 (float16x4_t __a) +{ + return __builtin_aarch64_lflooruv4hfv4hi_us (__a); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtmq_u16_f16 (float16x8_t __a) +{ + return __builtin_aarch64_lflooruv8hfv8hi_us (__a); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtn_s16_f16 (float16x4_t __a) +{ + return __builtin_aarch64_lfrintnv4hfv4hi (__a); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtnq_s16_f16 (float16x8_t __a) +{ + return __builtin_aarch64_lfrintnv8hfv8hi (__a); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtn_u16_f16 (float16x4_t __a) +{ + return __builtin_aarch64_lfrintnuv4hfv4hi_us (__a); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtnq_u16_f16 (float16x8_t __a) +{ + return __builtin_aarch64_lfrintnuv8hfv8hi_us (__a); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtp_s16_f16 (float16x4_t __a) +{ + return __builtin_aarch64_lceilv4hfv4hi (__a); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtpq_s16_f16 (float16x8_t __a) +{ + return __builtin_aarch64_lceilv8hfv8hi (__a); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtp_u16_f16 (float16x4_t __a) +{ + return __builtin_aarch64_lceiluv4hfv4hi_us (__a); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtpq_u16_f16 (float16x8_t __a) +{ + return __builtin_aarch64_lceiluv8hfv8hi_us (__a); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vneg_f16 (float16x4_t __a) +{ + return -__a; +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vnegq_f16 (float16x8_t __a) +{ + return -__a; +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrecpe_f16 (float16x4_t __a) +{ + return __builtin_aarch64_frecpev4hf (__a); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrecpeq_f16 (float16x8_t __a) +{ + return __builtin_aarch64_frecpev8hf (__a); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrnd_f16 (float16x4_t __a) +{ + return __builtin_aarch64_btruncv4hf (__a); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndq_f16 (float16x8_t __a) +{ + return __builtin_aarch64_btruncv8hf (__a); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrnda_f16 (float16x4_t __a) +{ + return __builtin_aarch64_roundv4hf (__a); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndaq_f16 (float16x8_t __a) +{ + return __builtin_aarch64_roundv8hf (__a); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndi_f16 (float16x4_t __a) +{ + return __builtin_aarch64_nearbyintv4hf (__a); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndiq_f16 (float16x8_t __a) +{ + return __builtin_aarch64_nearbyintv8hf (__a); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndm_f16 (float16x4_t __a) +{ + return __builtin_aarch64_floorv4hf (__a); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndmq_f16 (float16x8_t __a) +{ + return __builtin_aarch64_floorv8hf (__a); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndn_f16 (float16x4_t __a) +{ + return __builtin_aarch64_frintnv4hf (__a); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndnq_f16 (float16x8_t __a) +{ + return __builtin_aarch64_frintnv8hf (__a); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndp_f16 (float16x4_t __a) +{ + return __builtin_aarch64_ceilv4hf (__a); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndpq_f16 (float16x8_t __a) +{ + return __builtin_aarch64_ceilv8hf (__a); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndx_f16 (float16x4_t __a) +{ + return __builtin_aarch64_rintv4hf (__a); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrndxq_f16 (float16x8_t __a) +{ + return __builtin_aarch64_rintv8hf (__a); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsqrte_f16 (float16x4_t a) +{ + return __builtin_aarch64_rsqrtev4hf (a); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsqrteq_f16 (float16x8_t a) +{ + return __builtin_aarch64_rsqrtev8hf (a); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsqrt_f16 (float16x4_t a) +{ + return __builtin_aarch64_sqrtv4hf (a); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsqrtq_f16 (float16x8_t a) +{ + return __builtin_aarch64_sqrtv8hf (a); +} + +/* ARMv8.2-A FP16 two operands vector intrinsics. */ + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vadd_f16 (float16x4_t __a, float16x4_t __b) +{ + return __a + __b; +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vaddq_f16 (float16x8_t __a, float16x8_t __b) +{ + return __a + __b; +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabd_f16 (float16x4_t a, float16x4_t b) +{ + return __builtin_aarch64_fabdv4hf (a, b); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabdq_f16 (float16x8_t a, float16x8_t b) +{ + return __builtin_aarch64_fabdv8hf (a, b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcage_f16 (float16x4_t __a, float16x4_t __b) +{ + return __builtin_aarch64_facgev4hf_uss (__a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcageq_f16 (float16x8_t __a, float16x8_t __b) +{ + return __builtin_aarch64_facgev8hf_uss (__a, __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcagt_f16 (float16x4_t __a, float16x4_t __b) +{ + return __builtin_aarch64_facgtv4hf_uss (__a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcagtq_f16 (float16x8_t __a, float16x8_t __b) +{ + return __builtin_aarch64_facgtv8hf_uss (__a, __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcale_f16 (float16x4_t __a, float16x4_t __b) +{ + return __builtin_aarch64_faclev4hf_uss (__a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcaleq_f16 (float16x8_t __a, float16x8_t __b) +{ + return __builtin_aarch64_faclev8hf_uss (__a, __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcalt_f16 (float16x4_t __a, float16x4_t __b) +{ + return __builtin_aarch64_facltv4hf_uss (__a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcaltq_f16 (float16x8_t __a, float16x8_t __b) +{ + return __builtin_aarch64_facltv8hf_uss (__a, __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceq_f16 (float16x4_t __a, float16x4_t __b) +{ + return __builtin_aarch64_cmeqv4hf_uss (__a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vceqq_f16 (float16x8_t __a, float16x8_t __b) +{ + return __builtin_aarch64_cmeqv8hf_uss (__a, __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcge_f16 (float16x4_t __a, float16x4_t __b) +{ + return __builtin_aarch64_cmgev4hf_uss (__a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgeq_f16 (float16x8_t __a, float16x8_t __b) +{ + return __builtin_aarch64_cmgev8hf_uss (__a, __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgt_f16 (float16x4_t __a, float16x4_t __b) +{ + return __builtin_aarch64_cmgtv4hf_uss (__a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcgtq_f16 (float16x8_t __a, float16x8_t __b) +{ + return __builtin_aarch64_cmgtv8hf_uss (__a, __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcle_f16 (float16x4_t __a, float16x4_t __b) +{ + return __builtin_aarch64_cmlev4hf_uss (__a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcleq_f16 (float16x8_t __a, float16x8_t __b) +{ + return __builtin_aarch64_cmlev8hf_uss (__a, __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vclt_f16 (float16x4_t __a, float16x4_t __b) +{ + return __builtin_aarch64_cmltv4hf_uss (__a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcltq_f16 (float16x8_t __a, float16x8_t __b) +{ + return __builtin_aarch64_cmltv8hf_uss (__a, __b); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_n_f16_s16 (int16x4_t __a, const int __b) +{ + return __builtin_aarch64_scvtfv4hi (__a, __b); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtq_n_f16_s16 (int16x8_t __a, const int __b) +{ + return __builtin_aarch64_scvtfv8hi (__a, __b); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_n_f16_u16 (uint16x4_t __a, const int __b) +{ + return __builtin_aarch64_ucvtfv4hi_sus (__a, __b); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtq_n_f16_u16 (uint16x8_t __a, const int __b) +{ + return __builtin_aarch64_ucvtfv8hi_sus (__a, __b); +} + +__extension__ extern __inline int16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_n_s16_f16 (float16x4_t __a, const int __b) +{ + return __builtin_aarch64_fcvtzsv4hf (__a, __b); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtq_n_s16_f16 (float16x8_t __a, const int __b) +{ + return __builtin_aarch64_fcvtzsv8hf (__a, __b); +} + +__extension__ extern __inline uint16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvt_n_u16_f16 (float16x4_t __a, const int __b) +{ + return __builtin_aarch64_fcvtzuv4hf_uss (__a, __b); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcvtq_n_u16_f16 (float16x8_t __a, const int __b) +{ + return __builtin_aarch64_fcvtzuv8hf_uss (__a, __b); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdiv_f16 (float16x4_t __a, float16x4_t __b) +{ + return __a / __b; +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdivq_f16 (float16x8_t __a, float16x8_t __b) +{ + return __a / __b; +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmax_f16 (float16x4_t __a, float16x4_t __b) +{ + return __builtin_aarch64_smax_nanv4hf (__a, __b); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxq_f16 (float16x8_t __a, float16x8_t __b) +{ + return __builtin_aarch64_smax_nanv8hf (__a, __b); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxnm_f16 (float16x4_t __a, float16x4_t __b) +{ + return __builtin_aarch64_fmaxv4hf (__a, __b); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxnmq_f16 (float16x8_t __a, float16x8_t __b) +{ + return __builtin_aarch64_fmaxv8hf (__a, __b); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmin_f16 (float16x4_t __a, float16x4_t __b) +{ + return __builtin_aarch64_smin_nanv4hf (__a, __b); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminq_f16 (float16x8_t __a, float16x8_t __b) +{ + return __builtin_aarch64_smin_nanv8hf (__a, __b); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminnm_f16 (float16x4_t __a, float16x4_t __b) +{ + return __builtin_aarch64_fminv4hf (__a, __b); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminnmq_f16 (float16x8_t __a, float16x8_t __b) +{ + return __builtin_aarch64_fminv8hf (__a, __b); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmul_f16 (float16x4_t __a, float16x4_t __b) +{ + return __a * __b; +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulq_f16 (float16x8_t __a, float16x8_t __b) +{ + return __a * __b; +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulx_f16 (float16x4_t __a, float16x4_t __b) +{ + return __builtin_aarch64_fmulxv4hf (__a, __b); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulxq_f16 (float16x8_t __a, float16x8_t __b) +{ + return __builtin_aarch64_fmulxv8hf (__a, __b); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpadd_f16 (float16x4_t a, float16x4_t b) +{ + return __builtin_aarch64_faddpv4hf (a, b); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpaddq_f16 (float16x8_t a, float16x8_t b) +{ + return __builtin_aarch64_faddpv8hf (a, b); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmax_f16 (float16x4_t a, float16x4_t b) +{ + return __builtin_aarch64_smax_nanpv4hf (a, b); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmaxq_f16 (float16x8_t a, float16x8_t b) +{ + return __builtin_aarch64_smax_nanpv8hf (a, b); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmaxnm_f16 (float16x4_t a, float16x4_t b) +{ + return __builtin_aarch64_smaxpv4hf (a, b); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmaxnmq_f16 (float16x8_t a, float16x8_t b) +{ + return __builtin_aarch64_smaxpv8hf (a, b); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpmin_f16 (float16x4_t a, float16x4_t b) +{ + return __builtin_aarch64_smin_nanpv4hf (a, b); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpminq_f16 (float16x8_t a, float16x8_t b) +{ + return __builtin_aarch64_smin_nanpv8hf (a, b); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpminnm_f16 (float16x4_t a, float16x4_t b) +{ + return __builtin_aarch64_sminpv4hf (a, b); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vpminnmq_f16 (float16x8_t a, float16x8_t b) +{ + return __builtin_aarch64_sminpv8hf (a, b); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrecps_f16 (float16x4_t __a, float16x4_t __b) +{ + return __builtin_aarch64_frecpsv4hf (__a, __b); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrecpsq_f16 (float16x8_t __a, float16x8_t __b) +{ + return __builtin_aarch64_frecpsv8hf (__a, __b); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsqrts_f16 (float16x4_t a, float16x4_t b) +{ + return __builtin_aarch64_rsqrtsv4hf (a, b); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrsqrtsq_f16 (float16x8_t a, float16x8_t b) +{ + return __builtin_aarch64_rsqrtsv8hf (a, b); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsub_f16 (float16x4_t __a, float16x4_t __b) +{ + return __a - __b; +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsubq_f16 (float16x8_t __a, float16x8_t __b) +{ + return __a - __b; +} + +/* ARMv8.2-A FP16 three operands vector intrinsics. */ + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfma_f16 (float16x4_t __a, float16x4_t __b, float16x4_t __c) +{ + return __builtin_aarch64_fmav4hf (__b, __c, __a); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmaq_f16 (float16x8_t __a, float16x8_t __b, float16x8_t __c) +{ + return __builtin_aarch64_fmav8hf (__b, __c, __a); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfms_f16 (float16x4_t __a, float16x4_t __b, float16x4_t __c) +{ + return __builtin_aarch64_fnmav4hf (__b, __c, __a); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmsq_f16 (float16x8_t __a, float16x8_t __b, float16x8_t __c) +{ + return __builtin_aarch64_fnmav8hf (__b, __c, __a); +} + +/* ARMv8.2-A FP16 lane vector intrinsics. */ + +__extension__ extern __inline float16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmah_lane_f16 (float16_t __a, float16_t __b, + float16x4_t __c, const int __lane) +{ + return vfmah_f16 (__a, __b, __aarch64_vget_lane_any (__c, __lane)); +} + +__extension__ extern __inline float16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmah_laneq_f16 (float16_t __a, float16_t __b, + float16x8_t __c, const int __lane) +{ + return vfmah_f16 (__a, __b, __aarch64_vget_lane_any (__c, __lane)); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfma_lane_f16 (float16x4_t __a, float16x4_t __b, + float16x4_t __c, const int __lane) +{ + return vfma_f16 (__a, __b, __aarch64_vdup_lane_f16 (__c, __lane)); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmaq_lane_f16 (float16x8_t __a, float16x8_t __b, + float16x4_t __c, const int __lane) +{ + return vfmaq_f16 (__a, __b, __aarch64_vdupq_lane_f16 (__c, __lane)); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfma_laneq_f16 (float16x4_t __a, float16x4_t __b, + float16x8_t __c, const int __lane) +{ + return vfma_f16 (__a, __b, __aarch64_vdup_laneq_f16 (__c, __lane)); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmaq_laneq_f16 (float16x8_t __a, float16x8_t __b, + float16x8_t __c, const int __lane) +{ + return vfmaq_f16 (__a, __b, __aarch64_vdupq_laneq_f16 (__c, __lane)); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfma_n_f16 (float16x4_t __a, float16x4_t __b, float16_t __c) +{ + return vfma_f16 (__a, __b, vdup_n_f16 (__c)); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmaq_n_f16 (float16x8_t __a, float16x8_t __b, float16_t __c) +{ + return vfmaq_f16 (__a, __b, vdupq_n_f16 (__c)); +} + +__extension__ extern __inline float16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmsh_lane_f16 (float16_t __a, float16_t __b, + float16x4_t __c, const int __lane) +{ + return vfmsh_f16 (__a, __b, __aarch64_vget_lane_any (__c, __lane)); +} + +__extension__ extern __inline float16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmsh_laneq_f16 (float16_t __a, float16_t __b, + float16x8_t __c, const int __lane) +{ + return vfmsh_f16 (__a, __b, __aarch64_vget_lane_any (__c, __lane)); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfms_lane_f16 (float16x4_t __a, float16x4_t __b, + float16x4_t __c, const int __lane) +{ + return vfms_f16 (__a, __b, __aarch64_vdup_lane_f16 (__c, __lane)); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmsq_lane_f16 (float16x8_t __a, float16x8_t __b, + float16x4_t __c, const int __lane) +{ + return vfmsq_f16 (__a, __b, __aarch64_vdupq_lane_f16 (__c, __lane)); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfms_laneq_f16 (float16x4_t __a, float16x4_t __b, + float16x8_t __c, const int __lane) +{ + return vfms_f16 (__a, __b, __aarch64_vdup_laneq_f16 (__c, __lane)); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmsq_laneq_f16 (float16x8_t __a, float16x8_t __b, + float16x8_t __c, const int __lane) +{ + return vfmsq_f16 (__a, __b, __aarch64_vdupq_laneq_f16 (__c, __lane)); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfms_n_f16 (float16x4_t __a, float16x4_t __b, float16_t __c) +{ + return vfms_f16 (__a, __b, vdup_n_f16 (__c)); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmsq_n_f16 (float16x8_t __a, float16x8_t __b, float16_t __c) +{ + return vfmsq_f16 (__a, __b, vdupq_n_f16 (__c)); +} + +__extension__ extern __inline float16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulh_lane_f16 (float16_t __a, float16x4_t __b, const int __lane) +{ + return __a * __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmul_lane_f16 (float16x4_t __a, float16x4_t __b, const int __lane) +{ + return vmul_f16 (__a, vdup_n_f16 (__aarch64_vget_lane_any (__b, __lane))); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulq_lane_f16 (float16x8_t __a, float16x4_t __b, const int __lane) +{ + return vmulq_f16 (__a, vdupq_n_f16 (__aarch64_vget_lane_any (__b, __lane))); +} + +__extension__ extern __inline float16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulh_laneq_f16 (float16_t __a, float16x8_t __b, const int __lane) +{ + return __a * __aarch64_vget_lane_any (__b, __lane); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmul_laneq_f16 (float16x4_t __a, float16x8_t __b, const int __lane) +{ + return vmul_f16 (__a, vdup_n_f16 (__aarch64_vget_lane_any (__b, __lane))); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulq_laneq_f16 (float16x8_t __a, float16x8_t __b, const int __lane) +{ + return vmulq_f16 (__a, vdupq_n_f16 (__aarch64_vget_lane_any (__b, __lane))); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmul_n_f16 (float16x4_t __a, float16_t __b) +{ + return vmul_lane_f16 (__a, vdup_n_f16 (__b), 0); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulq_n_f16 (float16x8_t __a, float16_t __b) +{ + return vmulq_laneq_f16 (__a, vdupq_n_f16 (__b), 0); +} + +__extension__ extern __inline float16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulxh_lane_f16 (float16_t __a, float16x4_t __b, const int __lane) +{ + return vmulxh_f16 (__a, __aarch64_vget_lane_any (__b, __lane)); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulx_lane_f16 (float16x4_t __a, float16x4_t __b, const int __lane) +{ + return vmulx_f16 (__a, __aarch64_vdup_lane_f16 (__b, __lane)); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulxq_lane_f16 (float16x8_t __a, float16x4_t __b, const int __lane) +{ + return vmulxq_f16 (__a, __aarch64_vdupq_lane_f16 (__b, __lane)); +} + +__extension__ extern __inline float16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulxh_laneq_f16 (float16_t __a, float16x8_t __b, const int __lane) +{ + return vmulxh_f16 (__a, __aarch64_vget_lane_any (__b, __lane)); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulx_laneq_f16 (float16x4_t __a, float16x8_t __b, const int __lane) +{ + return vmulx_f16 (__a, __aarch64_vdup_laneq_f16 (__b, __lane)); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulxq_laneq_f16 (float16x8_t __a, float16x8_t __b, const int __lane) +{ + return vmulxq_f16 (__a, __aarch64_vdupq_laneq_f16 (__b, __lane)); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulx_n_f16 (float16x4_t __a, float16_t __b) +{ + return vmulx_f16 (__a, vdup_n_f16 (__b)); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmulxq_n_f16 (float16x8_t __a, float16_t __b) +{ + return vmulxq_f16 (__a, vdupq_n_f16 (__b)); +} + +/* ARMv8.2-A FP16 reduction vector intrinsics. */ + +__extension__ extern __inline float16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxv_f16 (float16x4_t __a) +{ + return __builtin_aarch64_reduc_smax_nan_scal_v4hf (__a); +} + +__extension__ extern __inline float16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxvq_f16 (float16x8_t __a) +{ + return __builtin_aarch64_reduc_smax_nan_scal_v8hf (__a); +} + +__extension__ extern __inline float16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminv_f16 (float16x4_t __a) +{ + return __builtin_aarch64_reduc_smin_nan_scal_v4hf (__a); +} + +__extension__ extern __inline float16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminvq_f16 (float16x8_t __a) +{ + return __builtin_aarch64_reduc_smin_nan_scal_v8hf (__a); +} + +__extension__ extern __inline float16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxnmv_f16 (float16x4_t __a) +{ + return __builtin_aarch64_reduc_smax_scal_v4hf (__a); +} + +__extension__ extern __inline float16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vmaxnmvq_f16 (float16x8_t __a) +{ + return __builtin_aarch64_reduc_smax_scal_v8hf (__a); +} + +__extension__ extern __inline float16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminnmv_f16 (float16x4_t __a) +{ + return __builtin_aarch64_reduc_smin_scal_v4hf (__a); +} + +__extension__ extern __inline float16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vminnmvq_f16 (float16x8_t __a) +{ + return __builtin_aarch64_reduc_smin_scal_v8hf (__a); +} + +#pragma GCC pop_options + +/* AdvSIMD Dot Product intrinsics. */ + +#pragma GCC push_options +#pragma GCC target ("arch=armv8.2-a+dotprod") + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdot_u32 (uint32x2_t __r, uint8x8_t __a, uint8x8_t __b) +{ + return __builtin_aarch64_udotv8qi_uuuu (__r, __a, __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdotq_u32 (uint32x4_t __r, uint8x16_t __a, uint8x16_t __b) +{ + return __builtin_aarch64_udotv16qi_uuuu (__r, __a, __b); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdot_s32 (int32x2_t __r, int8x8_t __a, int8x8_t __b) +{ + return __builtin_aarch64_sdotv8qi (__r, __a, __b); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdotq_s32 (int32x4_t __r, int8x16_t __a, int8x16_t __b) +{ + return __builtin_aarch64_sdotv16qi (__r, __a, __b); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdot_lane_u32 (uint32x2_t __r, uint8x8_t __a, uint8x8_t __b, const int __index) +{ + return __builtin_aarch64_udot_lanev8qi_uuuus (__r, __a, __b, __index); +} + +__extension__ extern __inline uint32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdot_laneq_u32 (uint32x2_t __r, uint8x8_t __a, uint8x16_t __b, + const int __index) +{ + return __builtin_aarch64_udot_laneqv8qi_uuuus (__r, __a, __b, __index); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdotq_lane_u32 (uint32x4_t __r, uint8x16_t __a, uint8x8_t __b, + const int __index) +{ + return __builtin_aarch64_udot_lanev16qi_uuuus (__r, __a, __b, __index); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdotq_laneq_u32 (uint32x4_t __r, uint8x16_t __a, uint8x16_t __b, + const int __index) +{ + return __builtin_aarch64_udot_laneqv16qi_uuuus (__r, __a, __b, __index); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdot_lane_s32 (int32x2_t __r, int8x8_t __a, int8x8_t __b, const int __index) +{ + return __builtin_aarch64_sdot_lanev8qi (__r, __a, __b, __index); +} + +__extension__ extern __inline int32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdot_laneq_s32 (int32x2_t __r, int8x8_t __a, int8x16_t __b, const int __index) +{ + return __builtin_aarch64_sdot_laneqv8qi (__r, __a, __b, __index); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdotq_lane_s32 (int32x4_t __r, int8x16_t __a, int8x8_t __b, const int __index) +{ + return __builtin_aarch64_sdot_lanev16qi (__r, __a, __b, __index); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vdotq_laneq_s32 (int32x4_t __r, int8x16_t __a, int8x16_t __b, const int __index) +{ + return __builtin_aarch64_sdot_laneqv16qi (__r, __a, __b, __index); +} +#pragma GCC pop_options + +#pragma GCC push_options +#pragma GCC target ("arch=armv8.2-a+sm4") + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsm3ss1q_u32 (uint32x4_t __a, uint32x4_t __b, uint32x4_t __c) +{ + return __builtin_aarch64_sm3ss1qv4si_uuuu (__a, __b, __c); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsm3tt1aq_u32 (uint32x4_t __a, uint32x4_t __b, uint32x4_t __c, const int __imm2) +{ + return __builtin_aarch64_sm3tt1aqv4si_uuuus (__a, __b, __c, __imm2); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsm3tt1bq_u32 (uint32x4_t __a, uint32x4_t __b, uint32x4_t __c, const int __imm2) +{ + return __builtin_aarch64_sm3tt1bqv4si_uuuus (__a, __b, __c, __imm2); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsm3tt2aq_u32 (uint32x4_t __a, uint32x4_t __b, uint32x4_t __c, const int __imm2) +{ + return __builtin_aarch64_sm3tt2aqv4si_uuuus (__a, __b, __c, __imm2); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsm3tt2bq_u32 (uint32x4_t __a, uint32x4_t __b, uint32x4_t __c, const int __imm2) +{ + return __builtin_aarch64_sm3tt2bqv4si_uuuus (__a, __b, __c, __imm2); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsm3partw1q_u32 (uint32x4_t __a, uint32x4_t __b, uint32x4_t __c) +{ + return __builtin_aarch64_sm3partw1qv4si_uuuu (__a, __b, __c); +} +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsm3partw2q_u32 (uint32x4_t __a, uint32x4_t __b, uint32x4_t __c) +{ + return __builtin_aarch64_sm3partw2qv4si_uuuu (__a, __b, __c); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsm4eq_u32 (uint32x4_t __a, uint32x4_t __b) +{ + return __builtin_aarch64_sm4eqv4si_uuu (__a, __b); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsm4ekeyq_u32 (uint32x4_t __a, uint32x4_t __b) +{ + return __builtin_aarch64_sm4ekeyqv4si_uuu (__a, __b); +} + +#pragma GCC pop_options + +#pragma GCC push_options +#pragma GCC target ("arch=armv8.2-a+sha3") + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsha512hq_u64 (uint64x2_t __a, uint64x2_t __b, uint64x2_t __c) +{ + return __builtin_aarch64_crypto_sha512hqv2di_uuuu (__a, __b, __c); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsha512h2q_u64 (uint64x2_t __a, uint64x2_t __b, uint64x2_t __c) +{ + return __builtin_aarch64_crypto_sha512h2qv2di_uuuu (__a, __b, __c); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsha512su0q_u64 (uint64x2_t __a, uint64x2_t __b) +{ + return __builtin_aarch64_crypto_sha512su0qv2di_uuu (__a, __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vsha512su1q_u64 (uint64x2_t __a, uint64x2_t __b, uint64x2_t __c) +{ + return __builtin_aarch64_crypto_sha512su1qv2di_uuuu (__a, __b, __c); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +veor3q_u8 (uint8x16_t __a, uint8x16_t __b, uint8x16_t __c) +{ + return __builtin_aarch64_eor3qv16qi_uuuu (__a, __b, __c); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +veor3q_u16 (uint16x8_t __a, uint16x8_t __b, uint16x8_t __c) +{ + return __builtin_aarch64_eor3qv8hi_uuuu (__a, __b, __c); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +veor3q_u32 (uint32x4_t __a, uint32x4_t __b, uint32x4_t __c) +{ + return __builtin_aarch64_eor3qv4si_uuuu (__a, __b, __c); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +veor3q_u64 (uint64x2_t __a, uint64x2_t __b, uint64x2_t __c) +{ + return __builtin_aarch64_eor3qv2di_uuuu (__a, __b, __c); +} + + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +veor3q_s8 (int8x16_t __a, int8x16_t __b, int8x16_t __c) +{ + return __builtin_aarch64_eor3qv16qi (__a, __b, __c); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +veor3q_s16 (int16x8_t __a, int16x8_t __b, int16x8_t __c) +{ + return __builtin_aarch64_eor3qv8hi (__a, __b, __c); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +veor3q_s32 (int32x4_t __a, int32x4_t __b, int32x4_t __c) +{ + return __builtin_aarch64_eor3qv4si (__a, __b, __c); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +veor3q_s64 (int64x2_t __a, int64x2_t __b, int64x2_t __c) +{ + return __builtin_aarch64_eor3qv2di (__a, __b, __c); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vrax1q_u64 (uint64x2_t __a, uint64x2_t __b) +{ + return __builtin_aarch64_rax1qv2di_uuu (__a, __b); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vxarq_u64 (uint64x2_t __a, uint64x2_t __b, const int imm6) +{ + return __builtin_aarch64_xarqv2di_uuus (__a, __b,imm6); +} + +__extension__ extern __inline uint8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbcaxq_u8 (uint8x16_t __a, uint8x16_t __b, uint8x16_t __c) +{ + return __builtin_aarch64_bcaxqv16qi_uuuu (__a, __b, __c); +} + +__extension__ extern __inline uint16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbcaxq_u16 (uint16x8_t __a, uint16x8_t __b, uint16x8_t __c) +{ + return __builtin_aarch64_bcaxqv8hi_uuuu (__a, __b, __c); +} + +__extension__ extern __inline uint32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbcaxq_u32 (uint32x4_t __a, uint32x4_t __b, uint32x4_t __c) +{ + return __builtin_aarch64_bcaxqv4si_uuuu (__a, __b, __c); +} + +__extension__ extern __inline uint64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbcaxq_u64 (uint64x2_t __a, uint64x2_t __b, uint64x2_t __c) +{ + return __builtin_aarch64_bcaxqv2di_uuuu (__a, __b, __c); +} + +__extension__ extern __inline int8x16_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbcaxq_s8 (int8x16_t __a, int8x16_t __b, int8x16_t __c) +{ + return __builtin_aarch64_bcaxqv16qi (__a, __b, __c); +} + +__extension__ extern __inline int16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbcaxq_s16 (int16x8_t __a, int16x8_t __b, int16x8_t __c) +{ + return __builtin_aarch64_bcaxqv8hi (__a, __b, __c); +} + +__extension__ extern __inline int32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbcaxq_s32 (int32x4_t __a, int32x4_t __b, int32x4_t __c) +{ + return __builtin_aarch64_bcaxqv4si (__a, __b, __c); +} + +__extension__ extern __inline int64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vbcaxq_s64 (int64x2_t __a, int64x2_t __b, int64x2_t __c) +{ + return __builtin_aarch64_bcaxqv2di (__a, __b, __c); +} + +#pragma GCC pop_options + +/* AdvSIMD Complex numbers intrinsics. */ + +#pragma GCC push_options +#pragma GCC target ("arch=armv8.3-a") + +#pragma GCC push_options +#pragma GCC target ("+fp16") +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcadd_rot90_f16 (float16x4_t __a, float16x4_t __b) +{ + return __builtin_aarch64_fcadd90v4hf (__a, __b); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcaddq_rot90_f16 (float16x8_t __a, float16x8_t __b) +{ + return __builtin_aarch64_fcadd90v8hf (__a, __b); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcadd_rot270_f16 (float16x4_t __a, float16x4_t __b) +{ + return __builtin_aarch64_fcadd270v4hf (__a, __b); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcaddq_rot270_f16 (float16x8_t __a, float16x8_t __b) +{ + return __builtin_aarch64_fcadd270v8hf (__a, __b); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmla_f16 (float16x4_t __r, float16x4_t __a, float16x4_t __b) +{ + return __builtin_aarch64_fcmla0v4hf (__r, __a, __b); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmlaq_f16 (float16x8_t __r, float16x8_t __a, float16x8_t __b) +{ + return __builtin_aarch64_fcmla0v8hf (__r, __a, __b); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmla_lane_f16 (float16x4_t __r, float16x4_t __a, float16x4_t __b, + const int __index) +{ + return __builtin_aarch64_fcmla_lane0v4hf (__r, __a, __b, __index); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmla_laneq_f16 (float16x4_t __r, float16x4_t __a, float16x8_t __b, + const int __index) +{ + return __builtin_aarch64_fcmla_laneq0v4hf (__r, __a, __b, __index); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmlaq_lane_f16 (float16x8_t __r, float16x8_t __a, float16x4_t __b, + const int __index) +{ + return __builtin_aarch64_fcmlaq_lane0v8hf (__r, __a, __b, __index); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmlaq_rot90_lane_f16 (float16x8_t __r, float16x8_t __a, float16x4_t __b, + const int __index) +{ + return __builtin_aarch64_fcmlaq_lane90v8hf (__r, __a, __b, __index); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmla_rot90_laneq_f16 (float16x4_t __r, float16x4_t __a, float16x8_t __b, + const int __index) +{ + return __builtin_aarch64_fcmla_laneq90v4hf (__r, __a, __b, __index); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmla_rot90_lane_f16 (float16x4_t __r, float16x4_t __a, float16x4_t __b, + const int __index) +{ + return __builtin_aarch64_fcmla_lane90v4hf (__r, __a, __b, __index); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmlaq_rot90_f16 (float16x8_t __r, float16x8_t __a, float16x8_t __b) +{ + return __builtin_aarch64_fcmla90v8hf (__r, __a, __b); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmla_rot90_f16 (float16x4_t __r, float16x4_t __a, float16x4_t __b) +{ + return __builtin_aarch64_fcmla90v4hf (__r, __a, __b); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmlaq_laneq_f16 (float16x8_t __r, float16x8_t __a, float16x8_t __b, + const int __index) +{ + return __builtin_aarch64_fcmla_lane0v8hf (__r, __a, __b, __index); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmla_rot180_laneq_f16 (float16x4_t __r, float16x4_t __a, float16x8_t __b, + const int __index) +{ + return __builtin_aarch64_fcmla_laneq180v4hf (__r, __a, __b, __index); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmla_rot180_lane_f16 (float16x4_t __r, float16x4_t __a, float16x4_t __b, + const int __index) +{ + return __builtin_aarch64_fcmla_lane180v4hf (__r, __a, __b, __index); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmlaq_rot180_f16 (float16x8_t __r, float16x8_t __a, float16x8_t __b) +{ + return __builtin_aarch64_fcmla180v8hf (__r, __a, __b); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmla_rot180_f16 (float16x4_t __r, float16x4_t __a, float16x4_t __b) +{ + return __builtin_aarch64_fcmla180v4hf (__r, __a, __b); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmlaq_rot90_laneq_f16 (float16x8_t __r, float16x8_t __a, float16x8_t __b, + const int __index) +{ + return __builtin_aarch64_fcmla_lane90v8hf (__r, __a, __b, __index); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmlaq_rot270_laneq_f16 (float16x8_t __r, float16x8_t __a, float16x8_t __b, + const int __index) +{ + return __builtin_aarch64_fcmla_lane270v8hf (__r, __a, __b, __index); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmlaq_rot270_lane_f16 (float16x8_t __r, float16x8_t __a, float16x4_t __b, + const int __index) +{ + return __builtin_aarch64_fcmlaq_lane270v8hf (__r, __a, __b, __index); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmla_rot270_laneq_f16 (float16x4_t __r, float16x4_t __a, float16x8_t __b, + const int __index) +{ + return __builtin_aarch64_fcmla_laneq270v4hf (__r, __a, __b, __index); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmlaq_rot270_f16 (float16x8_t __r, float16x8_t __a, float16x8_t __b) +{ + return __builtin_aarch64_fcmla270v8hf (__r, __a, __b); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmla_rot270_f16 (float16x4_t __r, float16x4_t __a, float16x4_t __b) +{ + return __builtin_aarch64_fcmla270v4hf (__r, __a, __b); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmlaq_rot180_laneq_f16 (float16x8_t __r, float16x8_t __a, float16x8_t __b, + const int __index) +{ + return __builtin_aarch64_fcmla_lane180v8hf (__r, __a, __b, __index); +} + +__extension__ extern __inline float16x8_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmlaq_rot180_lane_f16 (float16x8_t __r, float16x8_t __a, float16x4_t __b, + const int __index) +{ + return __builtin_aarch64_fcmlaq_lane180v8hf (__r, __a, __b, __index); +} + +__extension__ extern __inline float16x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmla_rot270_lane_f16 (float16x4_t __r, float16x4_t __a, float16x4_t __b, + const int __index) +{ + return __builtin_aarch64_fcmla_lane270v4hf (__r, __a, __b, __index); +} +#pragma GCC pop_options + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcadd_rot90_f32 (float32x2_t __a, float32x2_t __b) +{ + return __builtin_aarch64_fcadd90v2sf (__a, __b); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcaddq_rot90_f32 (float32x4_t __a, float32x4_t __b) +{ + return __builtin_aarch64_fcadd90v4sf (__a, __b); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcaddq_rot90_f64 (float64x2_t __a, float64x2_t __b) +{ + return __builtin_aarch64_fcadd90v2df (__a, __b); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcadd_rot270_f32 (float32x2_t __a, float32x2_t __b) +{ + return __builtin_aarch64_fcadd270v2sf (__a, __b); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcaddq_rot270_f32 (float32x4_t __a, float32x4_t __b) +{ + return __builtin_aarch64_fcadd270v4sf (__a, __b); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcaddq_rot270_f64 (float64x2_t __a, float64x2_t __b) +{ + return __builtin_aarch64_fcadd270v2df (__a, __b); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmla_f32 (float32x2_t __r, float32x2_t __a, float32x2_t __b) +{ + return __builtin_aarch64_fcmla0v2sf (__r, __a, __b); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmlaq_f32 (float32x4_t __r, float32x4_t __a, float32x4_t __b) +{ + return __builtin_aarch64_fcmla0v4sf (__r, __a, __b); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmlaq_f64 (float64x2_t __r, float64x2_t __a, float64x2_t __b) +{ + return __builtin_aarch64_fcmla0v2df (__r, __a, __b); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmla_lane_f32 (float32x2_t __r, float32x2_t __a, float32x2_t __b, + const int __index) +{ + return __builtin_aarch64_fcmla_lane0v2sf (__r, __a, __b, __index); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmla_laneq_f32 (float32x2_t __r, float32x2_t __a, float32x4_t __b, + const int __index) +{ + return __builtin_aarch64_fcmla_laneq0v2sf (__r, __a, __b, __index); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmlaq_lane_f32 (float32x4_t __r, float32x4_t __a, float32x2_t __b, + const int __index) +{ + return __builtin_aarch64_fcmlaq_lane0v4sf (__r, __a, __b, __index); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmlaq_laneq_f32 (float32x4_t __r, float32x4_t __a, float32x4_t __b, + const int __index) +{ + return __builtin_aarch64_fcmla_lane0v4sf (__r, __a, __b, __index); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmla_rot90_f32 (float32x2_t __r, float32x2_t __a, float32x2_t __b) +{ + return __builtin_aarch64_fcmla90v2sf (__r, __a, __b); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmlaq_rot90_f32 (float32x4_t __r, float32x4_t __a, float32x4_t __b) +{ + return __builtin_aarch64_fcmla90v4sf (__r, __a, __b); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmlaq_rot90_f64 (float64x2_t __r, float64x2_t __a, float64x2_t __b) +{ + return __builtin_aarch64_fcmla90v2df (__r, __a, __b); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmla_rot90_lane_f32 (float32x2_t __r, float32x2_t __a, float32x2_t __b, + const int __index) +{ + return __builtin_aarch64_fcmla_lane90v2sf (__r, __a, __b, __index); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmla_rot90_laneq_f32 (float32x2_t __r, float32x2_t __a, float32x4_t __b, + const int __index) +{ + return __builtin_aarch64_fcmla_laneq90v2sf (__r, __a, __b, __index); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmlaq_rot90_lane_f32 (float32x4_t __r, float32x4_t __a, float32x2_t __b, + const int __index) +{ + return __builtin_aarch64_fcmlaq_lane90v4sf (__r, __a, __b, __index); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmlaq_rot90_laneq_f32 (float32x4_t __r, float32x4_t __a, float32x4_t __b, + const int __index) +{ + return __builtin_aarch64_fcmla_lane90v4sf (__r, __a, __b, __index); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmla_rot180_f32 (float32x2_t __r, float32x2_t __a, float32x2_t __b) +{ + return __builtin_aarch64_fcmla180v2sf (__r, __a, __b); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmlaq_rot180_f32 (float32x4_t __r, float32x4_t __a, float32x4_t __b) +{ + return __builtin_aarch64_fcmla180v4sf (__r, __a, __b); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmlaq_rot180_f64 (float64x2_t __r, float64x2_t __a, float64x2_t __b) +{ + return __builtin_aarch64_fcmla180v2df (__r, __a, __b); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmla_rot180_lane_f32 (float32x2_t __r, float32x2_t __a, float32x2_t __b, + const int __index) +{ + return __builtin_aarch64_fcmla_lane180v2sf (__r, __a, __b, __index); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmla_rot180_laneq_f32 (float32x2_t __r, float32x2_t __a, float32x4_t __b, + const int __index) +{ + return __builtin_aarch64_fcmla_laneq180v2sf (__r, __a, __b, __index); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmlaq_rot180_lane_f32 (float32x4_t __r, float32x4_t __a, float32x2_t __b, + const int __index) +{ + return __builtin_aarch64_fcmlaq_lane180v4sf (__r, __a, __b, __index); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmlaq_rot180_laneq_f32 (float32x4_t __r, float32x4_t __a, float32x4_t __b, + const int __index) +{ + return __builtin_aarch64_fcmla_lane180v4sf (__r, __a, __b, __index); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmla_rot270_f32 (float32x2_t __r, float32x2_t __a, float32x2_t __b) +{ + return __builtin_aarch64_fcmla270v2sf (__r, __a, __b); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmlaq_rot270_f32 (float32x4_t __r, float32x4_t __a, float32x4_t __b) +{ + return __builtin_aarch64_fcmla270v4sf (__r, __a, __b); +} + +__extension__ extern __inline float64x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmlaq_rot270_f64 (float64x2_t __r, float64x2_t __a, float64x2_t __b) +{ + return __builtin_aarch64_fcmla270v2df (__r, __a, __b); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmla_rot270_lane_f32 (float32x2_t __r, float32x2_t __a, float32x2_t __b, + const int __index) +{ + return __builtin_aarch64_fcmla_lane270v2sf (__r, __a, __b, __index); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmla_rot270_laneq_f32 (float32x2_t __r, float32x2_t __a, float32x4_t __b, + const int __index) +{ + return __builtin_aarch64_fcmla_laneq270v2sf (__r, __a, __b, __index); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmlaq_rot270_lane_f32 (float32x4_t __r, float32x4_t __a, float32x2_t __b, + const int __index) +{ + return __builtin_aarch64_fcmlaq_lane270v4sf (__r, __a, __b, __index); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vcmlaq_rot270_laneq_f32 (float32x4_t __r, float32x4_t __a, float32x4_t __b, + const int __index) +{ + return __builtin_aarch64_fcmla_lane270v4sf (__r, __a, __b, __index); +} + +#pragma GCC pop_options + +#pragma GCC push_options +#pragma GCC target ("arch=armv8.2-a+fp16fml") + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmlal_low_f16 (float32x2_t __r, float16x4_t __a, float16x4_t __b) +{ + return __builtin_aarch64_fmlal_lowv2sf (__r, __a, __b); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmlsl_low_f16 (float32x2_t __r, float16x4_t __a, float16x4_t __b) +{ + return __builtin_aarch64_fmlsl_lowv2sf (__r, __a, __b); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmlalq_low_f16 (float32x4_t __r, float16x8_t __a, float16x8_t __b) +{ + return __builtin_aarch64_fmlalq_lowv4sf (__r, __a, __b); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmlslq_low_f16 (float32x4_t __r, float16x8_t __a, float16x8_t __b) +{ + return __builtin_aarch64_fmlslq_lowv4sf (__r, __a, __b); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmlal_high_f16 (float32x2_t __r, float16x4_t __a, float16x4_t __b) +{ + return __builtin_aarch64_fmlal_highv2sf (__r, __a, __b); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmlsl_high_f16 (float32x2_t __r, float16x4_t __a, float16x4_t __b) +{ + return __builtin_aarch64_fmlsl_highv2sf (__r, __a, __b); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmlalq_high_f16 (float32x4_t __r, float16x8_t __a, float16x8_t __b) +{ + return __builtin_aarch64_fmlalq_highv4sf (__r, __a, __b); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmlslq_high_f16 (float32x4_t __r, float16x8_t __a, float16x8_t __b) +{ + return __builtin_aarch64_fmlslq_highv4sf (__r, __a, __b); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmlal_lane_low_f16 (float32x2_t __r, float16x4_t __a, float16x4_t __b, + const int __lane) +{ + return __builtin_aarch64_fmlal_lane_lowv2sf (__r, __a, __b, __lane); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmlsl_lane_low_f16 (float32x2_t __r, float16x4_t __a, float16x4_t __b, + const int __lane) +{ + return __builtin_aarch64_fmlsl_lane_lowv2sf (__r, __a, __b, __lane); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmlal_laneq_low_f16 (float32x2_t __r, float16x4_t __a, float16x8_t __b, + const int __lane) +{ + return __builtin_aarch64_fmlal_laneq_lowv2sf (__r, __a, __b, __lane); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmlsl_laneq_low_f16 (float32x2_t __r, float16x4_t __a, float16x8_t __b, + const int __lane) +{ + return __builtin_aarch64_fmlsl_laneq_lowv2sf (__r, __a, __b, __lane); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmlalq_lane_low_f16 (float32x4_t __r, float16x8_t __a, float16x4_t __b, + const int __lane) +{ + return __builtin_aarch64_fmlalq_lane_lowv4sf (__r, __a, __b, __lane); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmlslq_lane_low_f16 (float32x4_t __r, float16x8_t __a, float16x4_t __b, + const int __lane) +{ + return __builtin_aarch64_fmlslq_lane_lowv4sf (__r, __a, __b, __lane); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmlalq_laneq_low_f16 (float32x4_t __r, float16x8_t __a, float16x8_t __b, + const int __lane) +{ + return __builtin_aarch64_fmlalq_laneq_lowv4sf (__r, __a, __b, __lane); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmlslq_laneq_low_f16 (float32x4_t __r, float16x8_t __a, float16x8_t __b, + const int __lane) +{ + return __builtin_aarch64_fmlslq_laneq_lowv4sf (__r, __a, __b, __lane); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmlal_lane_high_f16 (float32x2_t __r, float16x4_t __a, float16x4_t __b, + const int __lane) +{ + return __builtin_aarch64_fmlal_lane_highv2sf (__r, __a, __b, __lane); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmlsl_lane_high_f16 (float32x2_t __r, float16x4_t __a, float16x4_t __b, + const int __lane) +{ + return __builtin_aarch64_fmlsl_lane_highv2sf (__r, __a, __b, __lane); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmlal_laneq_high_f16 (float32x2_t __r, float16x4_t __a, float16x8_t __b, + const int __lane) +{ + return __builtin_aarch64_fmlal_laneq_highv2sf (__r, __a, __b, __lane); +} + +__extension__ extern __inline float32x2_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmlsl_laneq_high_f16 (float32x2_t __r, float16x4_t __a, float16x8_t __b, + const int __lane) +{ + return __builtin_aarch64_fmlsl_laneq_highv2sf (__r, __a, __b, __lane); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmlalq_lane_high_f16 (float32x4_t __r, float16x8_t __a, float16x4_t __b, + const int __lane) +{ + return __builtin_aarch64_fmlalq_lane_highv4sf (__r, __a, __b, __lane); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmlslq_lane_high_f16 (float32x4_t __r, float16x8_t __a, float16x4_t __b, + const int __lane) +{ + return __builtin_aarch64_fmlslq_lane_highv4sf (__r, __a, __b, __lane); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmlalq_laneq_high_f16 (float32x4_t __r, float16x8_t __a, float16x8_t __b, + const int __lane) +{ + return __builtin_aarch64_fmlalq_laneq_highv4sf (__r, __a, __b, __lane); +} + +__extension__ extern __inline float32x4_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vfmlslq_laneq_high_f16 (float32x4_t __r, float16x8_t __a, float16x8_t __b, + const int __lane) +{ + return __builtin_aarch64_fmlslq_laneq_highv4sf (__r, __a, __b, __lane); +} + +#pragma GCC pop_options + +#undef __aarch64_vget_lane_any + +#undef __aarch64_vdup_lane_any +#undef __aarch64_vdup_lane_f16 +#undef __aarch64_vdup_lane_f32 +#undef __aarch64_vdup_lane_f64 +#undef __aarch64_vdup_lane_p8 +#undef __aarch64_vdup_lane_p16 +#undef __aarch64_vdup_lane_s8 +#undef __aarch64_vdup_lane_s16 +#undef __aarch64_vdup_lane_s32 +#undef __aarch64_vdup_lane_s64 +#undef __aarch64_vdup_lane_u8 +#undef __aarch64_vdup_lane_u16 +#undef __aarch64_vdup_lane_u32 +#undef __aarch64_vdup_lane_u64 +#undef __aarch64_vdup_laneq_f16 +#undef __aarch64_vdup_laneq_f32 +#undef __aarch64_vdup_laneq_f64 +#undef __aarch64_vdup_laneq_p8 +#undef __aarch64_vdup_laneq_p16 +#undef __aarch64_vdup_laneq_s8 +#undef __aarch64_vdup_laneq_s16 +#undef __aarch64_vdup_laneq_s32 +#undef __aarch64_vdup_laneq_s64 +#undef __aarch64_vdup_laneq_u8 +#undef __aarch64_vdup_laneq_u16 +#undef __aarch64_vdup_laneq_u32 +#undef __aarch64_vdup_laneq_u64 +#undef __aarch64_vdupq_lane_f16 +#undef __aarch64_vdupq_lane_f32 +#undef __aarch64_vdupq_lane_f64 +#undef __aarch64_vdupq_lane_p8 +#undef __aarch64_vdupq_lane_p16 +#undef __aarch64_vdupq_lane_s8 +#undef __aarch64_vdupq_lane_s16 +#undef __aarch64_vdupq_lane_s32 +#undef __aarch64_vdupq_lane_s64 +#undef __aarch64_vdupq_lane_u8 +#undef __aarch64_vdupq_lane_u16 +#undef __aarch64_vdupq_lane_u32 +#undef __aarch64_vdupq_lane_u64 +#undef __aarch64_vdupq_laneq_f16 +#undef __aarch64_vdupq_laneq_f32 +#undef __aarch64_vdupq_laneq_f64 +#undef __aarch64_vdupq_laneq_p8 +#undef __aarch64_vdupq_laneq_p16 +#undef __aarch64_vdupq_laneq_s8 +#undef __aarch64_vdupq_laneq_s16 +#undef __aarch64_vdupq_laneq_s32 +#undef __aarch64_vdupq_laneq_s64 +#undef __aarch64_vdupq_laneq_u8 +#undef __aarch64_vdupq_laneq_u16 +#undef __aarch64_vdupq_laneq_u32 +#undef __aarch64_vdupq_laneq_u64 + +#endif \ No newline at end of file diff --git a/CNN/HighPerformanceComputing/doc/arm_neon_intrinsics_ref.pdf b/CNN/HighPerformanceComputing/doc/arm_neon_intrinsics_ref.pdf new file mode 100644 index 00000000..7a6cf68e Binary files /dev/null and b/CNN/HighPerformanceComputing/doc/arm_neon_intrinsics_ref.pdf differ diff --git "a/CNN/HighPerformanceComputing/doc/neon_programmers_\347\274\226\347\250\213\346\211\213\345\206\214.pdf" "b/CNN/HighPerformanceComputing/doc/neon_programmers_\347\274\226\347\250\213\346\211\213\345\206\214.pdf" new file mode 100644 index 00000000..92577cce Binary files /dev/null and "b/CNN/HighPerformanceComputing/doc/neon_programmers_\347\274\226\347\250\213\346\211\213\345\206\214.pdf" differ diff --git a/CNN/HighPerformanceComputing/doc/readme.md b/CNN/HighPerformanceComputing/doc/readme.md new file mode 100644 index 00000000..f483c8c5 --- /dev/null +++ b/CNN/HighPerformanceComputing/doc/readme.md @@ -0,0 +1 @@ +# 一些 高性能计算的论文和资料 diff --git a/CNN/HighPerformanceComputing/example/model/readme.md b/CNN/HighPerformanceComputing/example/model/readme.md index 1803c8e3..95614e1c 100644 --- a/CNN/HighPerformanceComputing/example/model/readme.md +++ b/CNN/HighPerformanceComputing/example/model/readme.md @@ -1 +1,3 @@ # 转换好的模型 + +[原模型可以再 TF处下载]() diff --git "a/CNN/HighPerformanceComputing/example/ncnn_\346\272\220\347\240\201\345\210\206\346\236\220.md" "b/CNN/HighPerformanceComputing/example/ncnn_\346\272\220\347\240\201\345\210\206\346\236\220.md" index 1da77fd7..aca61287 100644 --- "a/CNN/HighPerformanceComputing/example/ncnn_\346\272\220\347\240\201\345\210\206\346\236\220.md" +++ "b/CNN/HighPerformanceComputing/example/ncnn_\346\272\220\347\240\201\345\210\206\346\236\220.md" @@ -206,10 +206,11 @@ int ParamDict::load_param_bin(FILE* fp) [padding] (optional 可选) flag : unsigned int, little-endian, indicating the weight storage type, - 0 => float32, + 0 => float32, 0x01306B47 => float16, - otherwise => quantized int8, - may be omitted if the layer implementation forced the storage type explicitly。 + 0x000D4B38 => int8, + 0x0002C056 => raw data with extra scaling 带有尺度信息的 float32 + 其他 非0 => quantized data 256个量化数 和 索引表 raw data : raw weight data, little-endian, float32 data or float16 data or quantized table and indexes depending on the storage type flag。 @@ -1029,6 +1030,22 @@ v8: } ``` + +[Neon 指令集 ARMv7/v8 对比](https://blog.csdn.net/zsc09_leaf/article/details/45825015) + +V7a 有32个64位的D寄存器[D0-D31], 16个128位的Q寄存器 [Q0-Q15] ,一个Q对应2个D(2个D公用Q的高64位和低64位)。 + +q0(低64位 d0, 高64位 d1) q1(低64位 d2, 高64位 d3) q2(低64位 d4, 高64位 d5) ... q15(低64位 d30, 高64位 d31) + +ARMv8 有31 个64位寄存器,1个不同名字的特殊寄存器,用途取决于上下文, 因此我们可以看成 31个64位的X寄存器或者31个32位的W寄存器(X寄存器的低32位) + +x0(低32位 w0) x1(低32位 w1) ... x30(低32位 w30) + +ARMv8有32个128位的V寄存器,相似的,我们同样可以看成是32个32位的S寄存器或者32个64位的D寄存器。 + +v0(低64位 d0, 低32位 s0) v1(低64位 d1, 低32位 s1) v2(低64位 d2, 低32位 s2) ... v31(低64位 d31, 低32位 s31) + + ## 2. 值大小前topk层 argmax layer ### 普通c++版本 ```c diff --git a/CNN/HighPerformanceComputing/example/readme.md b/CNN/HighPerformanceComputing/example/readme.md index cf98153b..c882bdbc 100644 --- a/CNN/HighPerformanceComputing/example/readme.md +++ b/CNN/HighPerformanceComputing/example/readme.md @@ -1,9 +1,60 @@ -# ncnn 使用 +# ncnn + +> 架构: + +1.图像预处理 ncnn::Mat + + 1.1 from_pixels_resize() 生成目标尺寸大小的网络输入Mat mat_pixel.cpp + 双线性插值图像形变 resize_bilinear_c1/c2/c3/4 1通道/2通道/3通道/4通道 图像变形算法 mat_pixel_resize.cpp + 像素图像 转换成ncnn::Mat Mat::from_pixels() >>> 不同类型 from_rgb() + 像素数据指针rgb间隔 依次赋值给Mat的三个通道的指针 mat_pixel.cpp + 1.2 substract_mean_normalize() 去均值并归一化图像 mat.cpp + 有均值参数 + 创建 偏置层 ncnn::create_layer(ncnn::LayerType::Bias); 载入层参数 op->load_param(pd); 3通道 + 载入层权重数据 op->load_model(ncnn::ModelBinFromMatArray(weights)); -均值参数 + 运行层 op->forward_inplace(*this); + 有归一化参数 + 创建 尺度层 ncnn::create_layer(ncnn::LayerType::Scale); 载入层参数 op->load_param(pd); 3通道 + 载入层权重数据 op->load_model(ncnn::ModelBinFromMatArray(weights)); 尺度参数 + 运行层 op->forward_inplace(*this); + 有均值和归一化参数 + 创建 尺度层 ncnn::create_layer(ncnn::LayerType::Scale); 载入层参数 op->load_param(pd); 3通道 + 载入层权重数据 op->load_model(ncnn::ModelBinFromMatArray(weights)); -均值参数 和 尺度参数 + 运行层 op->forward_inplace(*this); + +2.模型解析 ncnn::Net + + 2.1 Net::load_param 载入网络参数文件 proto net.cpp + 文件头魔术数(版本?) 层类型 层名字 创建层 create_layer()/ net::create_custom_layer() 层输入blob数量 输出blob数量 + 读取输入blob 与层挂钩; 读取输出blob与层挂钩;解析层特殊参数(参数字典) paramDict::load_param(fp); 按照 id=参数/参数数组 解析 + 每一层 的 特殊参数不一样 https://github.com/Tencent/ncnn/wiki/operation-param-weight-table + 层载入解析得到的层特殊参数 layer->load_param(pd) 每一层特有的参数 + + 2.2 Net::load_model 载入网络模型文件 bin 权重数据 net.cpp + 1.创建 ModelBinFromStdio 对象 提供载入参数的接口函数 ModelBinFromStdio::load() src/modelbin.cpp + 根据 权重数据开始的一个四字节数据类型参数(float32/float16/int8等) 和 指定的参数数量 读取数据到 Mat 并返回Mat + 2.根据load_param 获取到的网络层信息 便利每一层 载入每一层的模型数据 layer->load_model() 每一层特有函数 + 3.部分层需要 根据层实际参数 调整运行流水线 layer->create_pipeline 例如卷积层和全连接层 + 4.量化的网络需要融合 Net::fuse_network() + +3.网络运行 ncnn::Extractor + + 3.1 创建网络提取器 Extractor Net::create_extractor 提供设置网络输入 获取网络输出 设置网络运行线程参数的接口 + 3.2 设置线程参数 Extractor::set_num_threads 设置网络输入 Extractor::input + 3.3 提取网络输出 Extractor::extract 运行网络前向运行函数 net->forward_layer + 会根据层类型(单输入单输出/其他) blob类型(可本地修改(在输入直接修改)/不可本地修改)执行每一次的前向运行函数 + 当输入blob为空时,会递归调用 网络前向运行函数 net->forward_layer 获取前置层的输出blob + + +# 编译 + [源码仓库](https://github.com/Tencent/ncnn) -安装编译: +[NCNN 在 window linux android平台下的部署](https://github.com/scutan90/DeepLearning-500-questions/blob/master/ch17_%E6%A8%A1%E5%9E%8B%E5%8E%8B%E7%BC%A9%E3%80%81%E5%8A%A0%E9%80%9F%E5%8F%8A%E7%A7%BB%E5%8A%A8%E7%AB%AF%E9%83%A8%E7%BD%B2/17.8.1%20NCNN%E9%83%A8%E7%BD%B2.md) + +linux 安装编译: - git clone https://github.com/Tencent/ncnn.git + git \ https://github.com/Tencent/ncnn.git cd ncnn gedit CMakeLists.txt 拉到最后 @@ -18,6 +69,7 @@ cmake .. make +[Windows NCNN\protobuf 编译](https://blog.csdn.net/ycdhqzhiai/article/details/80738987) # 1. 图像分类网络 diff --git a/CNN/HighPerformanceComputing/img/Large-Arrays.jpg b/CNN/HighPerformanceComputing/img/Large-Arrays.jpg new file mode 100644 index 00000000..8213d87b Binary files /dev/null and b/CNN/HighPerformanceComputing/img/Large-Arrays.jpg differ diff --git a/CNN/HighPerformanceComputing/img/Overlapping.jpg b/CNN/HighPerformanceComputing/img/Overlapping.jpg new file mode 100644 index 00000000..93999077 Binary files /dev/null and b/CNN/HighPerformanceComputing/img/Overlapping.jpg differ diff --git a/CNN/HighPerformanceComputing/img/Single-Elements.jpg b/CNN/HighPerformanceComputing/img/Single-Elements.jpg new file mode 100644 index 00000000..6561f581 Binary files /dev/null and b/CNN/HighPerformanceComputing/img/Single-Elements.jpg differ diff --git a/CNN/HighPerformanceComputing/img/data-range.PNG b/CNN/HighPerformanceComputing/img/data-range.PNG new file mode 100644 index 00000000..b2305faa Binary files /dev/null and b/CNN/HighPerformanceComputing/img/data-range.PNG differ diff --git a/CNN/HighPerformanceComputing/img/dtypr.PNG b/CNN/HighPerformanceComputing/img/dtypr.PNG new file mode 100644 index 00000000..75e799e2 Binary files /dev/null and b/CNN/HighPerformanceComputing/img/dtypr.PNG differ diff --git a/CNN/HighPerformanceComputing/img/extern-regest.PNG b/CNN/HighPerformanceComputing/img/extern-regest.PNG new file mode 100644 index 00000000..fb42a7ac Binary files /dev/null and b/CNN/HighPerformanceComputing/img/extern-regest.PNG differ diff --git a/CNN/HighPerformanceComputing/img/long.PNG b/CNN/HighPerformanceComputing/img/long.PNG new file mode 100644 index 00000000..ba022cc8 Binary files /dev/null and b/CNN/HighPerformanceComputing/img/long.PNG differ diff --git a/CNN/HighPerformanceComputing/img/matrixMul.PNG b/CNN/HighPerformanceComputing/img/matrixMul.PNG new file mode 100644 index 00000000..6e2ffca0 Binary files /dev/null and b/CNN/HighPerformanceComputing/img/matrixMul.PNG differ diff --git a/CNN/HighPerformanceComputing/img/matrixMul_COL.PNG b/CNN/HighPerformanceComputing/img/matrixMul_COL.PNG new file mode 100644 index 00000000..63facc0b Binary files /dev/null and b/CNN/HighPerformanceComputing/img/matrixMul_COL.PNG differ diff --git a/CNN/HighPerformanceComputing/img/narrow.PNG b/CNN/HighPerformanceComputing/img/narrow.PNG new file mode 100644 index 00000000..fd408d24 Binary files /dev/null and b/CNN/HighPerformanceComputing/img/narrow.PNG differ diff --git a/CNN/HighPerformanceComputing/img/neon-regest.PNG b/CNN/HighPerformanceComputing/img/neon-regest.PNG new file mode 100644 index 00000000..75a3be48 Binary files /dev/null and b/CNN/HighPerformanceComputing/img/neon-regest.PNG differ diff --git a/CNN/HighPerformanceComputing/img/neon.PNG b/CNN/HighPerformanceComputing/img/neon.PNG new file mode 100644 index 00000000..371d2948 Binary files /dev/null and b/CNN/HighPerformanceComputing/img/neon.PNG differ diff --git a/CNN/HighPerformanceComputing/img/readme.md b/CNN/HighPerformanceComputing/img/readme.md new file mode 100644 index 00000000..33a32a6a --- /dev/null +++ b/CNN/HighPerformanceComputing/img/readme.md @@ -0,0 +1 @@ +# 图片 diff --git a/CNN/HighPerformanceComputing/img/register.PNG b/CNN/HighPerformanceComputing/img/register.PNG new file mode 100644 index 00000000..601f614a Binary files /dev/null and b/CNN/HighPerformanceComputing/img/register.PNG differ diff --git a/CNN/HighPerformanceComputing/img/rgb-3.PNG b/CNN/HighPerformanceComputing/img/rgb-3.PNG new file mode 100644 index 00000000..c60c628f Binary files /dev/null and b/CNN/HighPerformanceComputing/img/rgb-3.PNG differ diff --git a/CNN/HighPerformanceComputing/img/rgb-bgr.jpg b/CNN/HighPerformanceComputing/img/rgb-bgr.jpg new file mode 100644 index 00000000..25a0021c Binary files /dev/null and b/CNN/HighPerformanceComputing/img/rgb-bgr.jpg differ diff --git a/CNN/HighPerformanceComputing/img/rgb-store.PNG b/CNN/HighPerformanceComputing/img/rgb-store.PNG new file mode 100644 index 00000000..96ead614 Binary files /dev/null and b/CNN/HighPerformanceComputing/img/rgb-store.PNG differ diff --git a/CNN/HighPerformanceComputing/img/rgb.PNG b/CNN/HighPerformanceComputing/img/rgb.PNG new file mode 100644 index 00000000..a8d2a7e9 Binary files /dev/null and b/CNN/HighPerformanceComputing/img/rgb.PNG differ diff --git a/CNN/HighPerformanceComputing/img/simd.PNG b/CNN/HighPerformanceComputing/img/simd.PNG new file mode 100644 index 00000000..83f7c67d Binary files /dev/null and b/CNN/HighPerformanceComputing/img/simd.PNG differ diff --git a/CNN/HighPerformanceComputing/img/simd_add-op.PNG b/CNN/HighPerformanceComputing/img/simd_add-op.PNG new file mode 100644 index 00000000..dc9936ca Binary files /dev/null and b/CNN/HighPerformanceComputing/img/simd_add-op.PNG differ diff --git a/CNN/HighPerformanceComputing/img/wide.PNG b/CNN/HighPerformanceComputing/img/wide.PNG new file mode 100644 index 00000000..4f556a12 Binary files /dev/null and b/CNN/HighPerformanceComputing/img/wide.PNG differ diff --git a/CNN/HighPerformanceComputing/mnn/readme.md b/CNN/HighPerformanceComputing/mnn/readme.md new file mode 100644 index 00000000..8f24dc11 --- /dev/null +++ b/CNN/HighPerformanceComputing/mnn/readme.md @@ -0,0 +1,229 @@ + +# MNN 阿里 + +[MNN 模型优化转换 算子图构建 MNN执行流程 推荐](https://zhuanlan.zhihu.com/c_1222854653945319424) + +MNN 是一个轻量级的深度学习端侧推理引擎,核心解决深度神经网络模型在端侧推理运行问题,涵盖深度神经网络模型的优化、转换和推理。 +目前,MNN已经在手淘、手猫、优酷、聚划算、UC、飞猪、千牛等 20 多个 App 中使用, +覆盖直播、短视频、搜索推荐、商品图像搜索、互动营销、权益发放、安全风控等场景,每天稳定运行上亿次。 +此外,菜鸟自提柜等 IoT 设备中也有应用。在 2018 年双十一购物节中,MNN 在天猫晚会笑脸红包、扫一扫、明星猜拳大战等场景中使用。 + +[MNN-APPLICATIONS ](https://github.com/xindongzhang/MNN-APPLICATIONS) + + +[主仓库](https://github.com/Ewenwan/MNN) + +[浅淡深度学习的发机机——张量计算](https://blog.csdn.net/jxt1234and2010/article/details/103595866) + +MNN整体架构 + +离线模型转换和图优化 + 在线预推理搜索最优策略+多终端op执行器 + +# MNN 提出了三大核心创新: + +[参考](https://www.toutiao.com/a6808767557319787012/) + + 1.运行时半自动搜索架构 + 2.卷积算法优化创新 + 3.异构设备混合调度 + +## 1.运行时半自动搜索架构 + +半自动搜索,是在模型结构已知的情况下,在已有的高性能计算模块中,按照一定规则,搜索、组合出最适应该模型的计算方案。它是介于以 TVM 为代表的的全自动搜索(i.e. 自动调优)和以 NCNN 为代表的全手动搜索(i.e. 手工实现每个 case)之间一种新颖的设计思想。它的核心洞察在于,TVM 的自动编译优化,难以匹敌针对硬件特性和算子的手写汇编;同时,模型算子、参数的 case 组合无穷多,无法针对每个 case 进行优化。在最后的「数据论证」部分,我们会用实验数据展示 MNN 相对于全自动搜索(TVM)和全手动搜索(NCNN)的优势。 + +为了支撑运行时半自动搜索的能力,MNN 提出了一个特殊的处理过程,称为「预推理」。预推理过程中,会提前进行算子的计算策略选择和资源分配。 + +一般情况下深度学习的应用输入尺寸变动的频率比较小或者可以经过特定的预处理阶段变成相对归一的尺寸。而在输入尺寸确定的情况下,我们可以对模型中每个 Op,计算出它的输出大小以及不同计算策略的消耗以及资源需求量,并以此为依据决定每个 Op 的计算策略,提前进行资源的分配。 + + +> 计算策略选择 + +算子的计算策略,包含算法与运行后端的选择。每种算子可以有多种计算策略,不同计算策略适用于不同的输入尺寸,MNN 采用 Cost 计算的方式,去决定计算策略的选取。算法的 Cost 与运行后端的调度 Cost 共同决定了一种计算策略的 Cost。 + +运行后端的调度 Cost,我们通过在大量实际的机器上测试获得。而需要重点关注的是不同算法实现的 Cost。 + +算法cost 主要体现在 卷积的不同实现方法的不同复杂度 + +滑窗/矩阵乘的 Cost ,参数定了,cost固定;Winograd 算法因为可以选择分成不同数量的块进行计算,而cost有多种,块数n 增大时,前后变换耗时增加,中间的乘法数减少,因此总cost会先降后升,需要找最小值。 + +对于不同的卷积情况,从 滑窗/矩阵乘方法和多种Winograd 算法策略中选择最小cost的方法,利用优化技术(SIMD(c_NEON/asm_NEON) 、OMP、数据重排、指令流水线),实现高效的op。 + +> 资源预分配 + +不采用统计计算大块内存,后分配的策略(不易扩展,不同算法选择),而采用内存池资源管理的办法(tensor引用计数,为0则清理) + +## 2.卷积算法优化创新 + +NC4HW4 格式数据排列,方便向量化运算,降低cache miss + +Winograd 算法创新(内置 Winograd 因子生成器,方便产生所有可能的情况,源变换——重排——矩阵乘——重排——目标变换 ), + +> Strassen 算法创新 + +对于大矩阵乘 C=AB 的计算,学界很早就有 Strassen 算法,其思路是把 A, B 等分拆成 4 个小块,进行一系列的加减计算后,进行 7 次小块矩阵乘,再经过一系列加减计算组装成 C。这样,原本需要 8 次小矩阵乘,现在只需要 7 次,就减少了 1 次矩阵乘。 + +## 3.异构设备混合调度 + +MNN 后端 API 的设计理念的独特性在于两点: + +MNN 后端 API 帮助实现异构设备的「混合调度」:TFLite 这样的后端 Delegate,会在遇到不支持的算子的时候,回退到算子的 CPU 实现。可以说,TFLite 后端设计是「被动式」的。与 TFLite 这样的后端 Delegate 不同,MNN 的异构调度是「主动式」的,我们称之为「混合调度」:MNN 在创建推理会话时,可以针对算子配置后端,且配置多于一个后端时,会根据后端实现动态选择对性能最优的后端。同时,会话负责衔接后端间的数据拷贝,单一后端仅需实现到数据缓存区域的读写,而无需感知其他后端的存在。这样,就可以在单会话内或多会话间实现后端的自由组合。在后端不支持或性能不适合实现特定算子时,就可以借助其他后端的实现,完成整个推理过程。 + +MNN 后端 API 的为算子抽象级别,而非例如 TFLite 的子图抽象级别。也就是说,在 MNN 的后端实现中,每个算子是单独实现的,后端实现不需要考虑子图的拓扑结构与优化。这一点,与前文所提的「半自动搜索」有关:在预处理过程中,整个计算图的图优化已经统一提前完成,所以不需要在后端子图实现。另外,算子级别的后端抽象,也极大的提高了后端实现的可调试性:可以将实现有误的后端算子快速定位。 + +MNN 通过半自动搜索,卷积算法优化创新和异构设备的混合调度,达到了在绝大多数情况下,领先于业界的性能。我们意识到性能是端侧智能应用非常重要的一环,会在未来持续投入更多创新性的性能优化方案,比如把半自动搜索应用于 MNN 正在建设的动态图训练能力中,让动态搭建的计算图可以选择出最适合当前参数的算子实现。另外,我们还看到端智能应用场景正在往 NLP 和 IOT 方向飞速发展。由于 NLP 的模型普遍较大,IOT 设备相比于移动端算力受限,这些都对模型压缩提出了更高的要求。所以,MNN 在未来除了投资性能优化以外,还会致力于研究更大压缩比、更好性能提升的模型压缩算法,让 MNN 成为端侧推理性能、压缩能力最好的深度学习引擎。 + +# 代码分析 + +read model-->create Net(Interpreter) --> 配置backend --> create session --> config input and output --> run session -->(Pipeline --> Unit-->op-->Execution(调用不同后端算子))--> finished + +[作者|MNN团队 +出品|阿里巴巴新零售淘系技术部](https://www.zhihu.com/search?q=mnn&type=content&range=3m) + +# 简介 + +MNN 作为阿里巴巴开源的端侧推理引擎,已经支撑了两届淘宝双十一。我们以轻量级的推理引擎和配套工具,支持 Caffe、TensorFlow、PyTorch 训练框架和端侧 CPU、GPU、NPU 上的高效推理。 + +手机淘宝中有许多对实时性和精度要求都比较高业务,例如视频流检测、拍立淘等等。在算力有限的情况下,性能和精度往往不可兼得 —— 要么接受更慢的响应速度,保障精度,例如放弃视频流,只支持图片;要么舍弃一部分精度,用更小的模型换取更快的速度。 + +HiAI 是华为端侧 AI 能力开放平台,通过 HiAI Foundation 芯片能力开放,可以借助异构调度和 NPU 加速, 获得更佳的性能和功耗,有了这样性能和功耗同时得以提升的方案, MNN 就可以在配备了 NPU 的设备上启用那个名场面 —— 我全都要! + + +那么,究竟要怎么做呢?毕竟NPU是完全不同于CPU和GPU的计算设备。在这里,就需要简单回顾一下 MNN 对计算设备的抽象了。 + +计算设备在 MNN 中,被抽象为 Backend ,即后端;每一种后端都有三种职责:计算资源的分配、计算任务的调度、数据拷贝(含必要的格式转换)。 MNN 在实现对华为 NPU 支持的时候,就依赖了这种抽象设计。 + +具体来说,创建会话阶段,我们会在 NPUExecution 的 onCreate 方法中,将 MNN 的 Op 转换为 HiAI 的 OM Op ,逐步构建出 OM 的模型图;资源分配阶段,我们会在 NPUBackend 的 onResizeEnd 方法中,编译 OM 的模型图,生成 NPU 可用的 IR 模型,并预留出输入输出相关的 AI Tensor ;在推理运行阶段,我们会借助 NPUBackend 的 onCopyBuffer 方法,将输入数据从 MNN Tensor 拷贝到 AITensor ,而后利用华为 NPU 执行推理计算,再将结果从 AITensor 拷贝到 MNN Tensor。 + +整个过程看上去还是非常复杂的,但是 MNN 把绝大部分复杂的工作隐藏在了后端的抽象设计中。用户在使用的时候,只需要将 backend 的 type 设置为 NPU ,就可以实现对 NPU 的调用。同时,如果设备不支持 NPU ,还可以自动将计算回退到 CPU 上来实现。 + +# 寄望未来 + +笔者和 Apple、Arm、华为等公司的工程师都有过交流,大家对 XPU 的未来都一致看好。虽然 APU、TPU、NPU 间的乱战可能还要持续上三五年,但在深度学习应用领域,它们逐步从云端走向终端,逐步替代 CPU、GPU 应当是大势所趋。 + +端智能行业是一个飞速发展的行业,我们在这样的大环境下,不进则退。在这里,把我们平时做的调研总结一下,说4个趋势: + + 端上推理的重要性高于训练,但是补齐端上训练能力也有价值。 + 后摩尔时代到来,XPU 百花齐放。 + NLP 逐步走向成熟。 + 从手机端到AIOT端。 + +为了满足新模型对算力的要求,出现了许多针对AI特殊加速的“XPU”。比如Google的TPU、Edge TPU,华为的麒麟NPU等。 + +未来的几年是NLP的广泛应用的几年。目前,最小的ALBERT模型大约47MB。这个大小已经适合在手机端上运行了。 + +“端智能”中所谓的“端”,不局限于手机端。未来的几年,将属于AIOT (Artificial Intelligence of Things)。未来的几年,全球手机的出货量不会再像往年那样大幅增长,而是平稳甚至下滑,而以智能音箱为代表的AIOT设备的出货量正在处于一个飞速发展的时期。 + + +## 特点:端侧推理引擎面临的挑战中,碎片化是最为显著的,这种碎片化是多层次、多维度的 + +> 训练框架上 + +Caffe 、 TensorFlow 、 PyTorch 、 MXNet 在训练模型时都很常用; +> 计算设备上 + +CPU 、 GPU 已是主流, NPU 、 TPU 渐渐成为标配, DSP 、 FPGA 在 IoT上也很常见; + +> 算子层面上 + +众多参数会形成不同的组合,从而对应出不同的优化方式,轻量化和通用化需要取舍; + +一款优秀的端侧推理引擎,就需要在这样碎片化的环境下,利用设备有限的资源,尽可能发挥出设备的性能。为此,也需要在转换、调度、执行上加入相应的优化策略。下文,会就其中的部分展开说明。 + + +## 1. 转换工具 +### 1.1 模型优化 + +在模型优化中,MNN 引入了前端的概念来统一训练框架。不同的前端负责加载不同训练框架的模型,统一转换为 MNN 的模型格式。对于最常用的训练框架 TensorFlow 和 Caffe ,我们提供了独立的前端;其他训练框架,比如 MXNet ,则需要先将模型转换为 ONNX ,再通过 ONNX 前端加载。这里,由于 TensorFlow 的算子颗粒度相比 Caffe 和 ONNX 要更小,我们引入了图优化的模块来对齐算子之间的颗粒度。模型转换之后,会经过优化器优化,包含**图优化、算子融合、算子替换、布局调整**等等。之后,可以选择对浮点模型执行量化压缩。目前模型压缩的模块还没有开源,我们会在完善之后,将相关代码开源。这些步骤都完成之后,会使用 flatbuffer 来保存部署模型。 + +### 图优化 TensorFlow +这里以 RNN-GRU cell 为例,说明一下图优化。 +左图是 RNN-GRU cell 在 TensorBoard 中的可视化描述。它足足包含了 3584 个节点,而每一个节点都代表了一定的数据读写或运算,累积起来的总量非常大。然而,所有这些节点可以打包使用一个大颗粒的算子来替代。这不仅大幅降低了部署模型的大小,还可以在大颗粒算子的实现中聚合大量的计算,避免不必要的数据读写。 + + +### 算子融合 + +以 Convolution、Batchnorm、Scale、ReLU 为例说明优化器中的算子融合。 +首先融合 Convolution 和 Batchnorm,Convolution 的 weight 等于 weight 乘 alpha ,而 bias 等于 bias 乘 alpha 再加 beta ;而后融合 Convolution 和 Scale ,融合过程和 Batchnorm 类似;最后融合 Convolution 和 ReLU ,在输出结果前,计算激活函数 ReLU 即可。 + +这样,四个算子就可以合并成一个算子。融合的过程避免了三次 tensor 读写、两次 tensor 乘加。 + + +### 模型压缩 量化 + +模型转换好之后,可以使用 MNN 的量化工具对模型进行压缩。目前,MNN支持 post-training quantization(无训练量化)。后续 MNN 会支持 quantization-aware training(带训练量化),以获得更好的准确率和更低比特的压缩。 + +MNN的量化方案是自己实现的,它目前有ADMM和KL散度两种方案。也就是说,“源头”的预训练好的模型需要是浮点的。ADMM量化方案,是MNN根据达摩院的Paper “Extremely Low Bit Neural Network: Squeeze the Last Bit Out with ADMM” [3] 实现的。它与KL散度的区别在于:ADMM是基于数学优化的方法,只需要几十个数据点即可,但是计算较慢。而KL散度是基于概率统计的方法,需要较多的数据(500到1000个数据点),计算较快。实际操作上来说,对特征的量化,ADMM和KL散度没有巨大的差距;对权重的量化,推荐使用ADMM。 + +NLP 应用是未来的一大趋势。而 NLP 的模型普遍大于 CV 模型。在这个时候,大幅度地压缩模型,能够让之前只能在服务器运行的模型放到端上运行。所以未来的 MNN ,会提供更好的模型压缩。 + +## 2. 智能调度 + +在调度上, MNN 将每一类计算设备抽象为一个后端,将算子在特定后端上的实现抽象为执行器。后端负责特定设备上的资源分配和计算调度,执行器负责具体的实现。后端和算子的添加都通过注册表来实现,这是一个双层注册表结构,拓展起来就相对灵活。 + +调度时,可以为子图选择相应的后端,再由后端创建出相应的执行器,组成管线;也可以为子图选择后端组,实现混合调度。比如,在 GPU 上不宜实现排序算子时,可以回退到 CPU 来执行。 + +目前, MNN 在 CPU 上实现了 76 个算子, Metal 上有 55 个, OpenGL 覆盖了基础的 CNN 网络, OpenCL 和 Vulkan 分别有 29 和 31 个。 + +### 2.1缓存管理 + +在创建完执行器之后,子图和管线已经就绪。下来,需要计算出所有tensor的形状,在相应的后端上完成内存的分配。而后,在准备执行器时,再为所有的执行器预先在后端上申请好必要的buffer。运行结束后,返回tensor即可。 + +由于推理所需的所有内存在准备期就已经申请完毕,在后续推理时,如果输入的形状不变,就可以复用tensor和buffer,从而避免频繁地申请、释放内存;只有输入形状改变的时候,才需要从形状计算开始,调整一次内存分配。同时,由于使用后端统一管理缓存,后端内的执行器之间,缓存就可以充分复用的,这就大大减少了内存的需求量。此外,MNN分配内存时,默认按照32位对齐,内存对齐有利于数据读写。 + +## 3. 执行优化 +### 3.1 数据布局与滑窗卷积 + +数据布局对性能影响巨大。(cache相关) + +先来看一看在 NCHW 的布局下,怎么利用 SIMD 加速 3x3 的 depth-wise 卷积。 + +首先,读取数据时,需要一次性读取四个 float 作为第一行的数据,后两行的读取也是相似的;此时,读取出的三行数据已经足够计算两列输出,即,可以复用部分数据;而后,为了提高数据复用,会再读取出第四行数据,一次计算两行两列,即,可以引入循环展开;然而,残留的 5~25 和 21~25 亮度眼边界无法利用 SIMD 计算,只能逐一循环读写完成计算;按照这样的方式,就可以相应完成后几个通道的计算。 + +但是, NCHW 布局下,无法充分利用 SIMD 进行加速,同时,实现优化分支越多,占用包大小也就越多。 + + + +再来看一看 NC/4HW4 布局下,利用 SIMD 加速的情况又是怎样的。 +这里的 "C/4" 指的是按照 4 个通道对齐的方式重排数据。重排所有输入和权重数据后,每次 SIMD 读写都天然是 4 个通道的输入数据和 4 个通道的权重数据。这样,不论 kernel、stride、dilation 怎么变化,我们都可以简单地使用 for 循环和 SIMD 的一套通用优化完成卷积计算。既不会有边缘数据无法加速的问题,也不会对包大小造成影响。 + + +### Winograd卷积 + +对于对于 KxK 卷积,可以使用 Winograd 算法进一步加速。 MNN 中支持 2x2 到 7x7 的 Winograd 实现。 Winograd 计算时,需要把输出拆分成 NxN 的小块,把输入拆分成 (N+K-1)x(N+K-1) 的小块。这样,问题就可以简化为两个小矩阵的卷积。 + +再套用 Winograd 的公式,将矩阵间的卷积运算转换为矩阵点乘运算。在这个过程中,除了矩阵点乘外,还引入三个矩阵转换,分别是输入矩阵 d 、权重矩阵 g 和结果矩阵 Y’ 的转换。其中,权重转换时, G 矩阵可以利用中国剩余数定理计算, GgGT 就可以在准备执行器时提前计算;输入转换和输出转换时用到的 A 和 B 矩阵需要根据 N 和 K 计算,我们在代码中内置了几种优化后的组合,所以实际计算时,这两个转换并不需要经过复杂的矩阵乘法。 + +这样,原来矩阵卷积所需要的 9x4 次乘法计算就可以用矩阵点乘的 4x4 次乘法计算代替。只考虑乘法耗时的话,加速了 2.25 倍。示例中, K=3,N=2 ,但实际使用时,可以选择更大的 N 值,获取高的加速倍数,但也要相应消耗更多的内存。 + + +### Strassen卷积 + +MNN 可能是端侧推理引擎中,第一个应用 Strassen 算法优化矩阵乘法的。 + +Strassen 在计算矩阵乘法时,首先需要将矩阵平均拆分成四个小矩阵。这里使用 a11 ~ a22、b11 ~ b22、c11 ~ c22 代表四个小矩阵,计算过程一共需要8次小矩阵乘法运算。 + +这里可以引入中间小矩阵, s1 ~ s4、t1 ~ t4、m1 ~ m7、u1 ~ u7 。其中,只有 m1 ~ m7 包含小矩阵乘法,一共 7 次小矩阵乘法运算。而其他的,只包含小矩阵的加减法。也就是说,通过 4 + 4 + 7 次小矩阵加减法,替代了一次小矩阵乘法。 + +与原来的矩阵乘法相比, Strassen 的时间复杂度从 n 的 3 次方,降低到 n 的 2.81 次方。在矩阵较大时,矩阵乘法远远慢于矩阵加减法,收益就更明显。 + +在 MNN 中,我们会递归使用 Strassen 。也就是说,递归拆分矩阵。在矩阵足够大时,继续拆分;在矩阵不够大时,使用普通的矩阵算法。这里使用减免的矩阵乘法开销作为收益,使用小矩阵 s 、小矩阵 t 、小矩阵 u 矩阵的加减法开销之和作为代价,收益大于代价时,就可以考虑使用 Strassen 算法。 + + + +### 链路优化 预处理优化库 + +链路优化可以举一个 19 年春节淘宝扫年货的例子。在获得手机相机输入后,每一帧的图像首先需要经过一次预处理,将图片缩放到年货检测模型的输入大小上,然而再经过推理,判定图像有没有年货,如果有,就发放相关权益。这个过程中,图片预处理的耗时也不容忽视。降低这个耗时,就可以帮助我们提升帧率,从而改进用户体验。为此,我们引入了一个轻量级的 2D 图片处理库,可以高效地完成色值变化、色彩空间的转换或者仿射变换等。这样, MNN 的用户就不再需要为图片处理引入 libyuv 或者 opencv 了。 + + + + + + + + + + + + + + diff --git "a/CNN/HighPerformanceComputing/neon_\345\206\205\347\275\256\345\207\275\346\225\260\346\200\273\347\273\223.md" "b/CNN/HighPerformanceComputing/neon_\345\206\205\347\275\256\345\207\275\346\225\260\346\200\273\347\273\223.md" new file mode 100644 index 00000000..93426b59 --- /dev/null +++ "b/CNN/HighPerformanceComputing/neon_\345\206\205\347\275\256\345\207\275\346\225\260\346\200\273\347\273\223.md" @@ -0,0 +1,389 @@ +# neon_内置函数总结 + +## 初始化寄存器 +```c +vcreate_type: 将一个64bit的数据装入vector中,并返回元素类型为type的vector。r=a +vdup_n_type/vmov_n_type: 用类型为type的数值,初始化一个元素类型为type的新vector的所有元素。ri=a +vdupq_n_type/vmovq_n_type: 128位寄存器 +vdup_lane_type: 用元素类型为type的vector的某个元素,初始化一个元素类型为type的新vector的所有元素。ri=a[b] +vdupq_lane_type: +vmovl_type: 将vector的元素bit位扩大到原来的两倍,元素值不变。 +vmovn_type: 用旧vector创建一个新vector,新vector的元素bit位是旧vector的一半。新vector元素只保留旧vector元素的低半部分。 +vqmovn_type: 用旧vector创建一个新vector,新vector的元素bit位是旧vector的一半。如果旧vector元素的值超过新vector元素的最大值,则新vector元素就取最大值。否则新vector元素就等于旧vector元素的值。 +vqmovun_type: 作用与vqmovn_type类似,但它输入的是有符号vector,输出的是无符号vector。 + +``` + + +## 从内存加载数据进neon寄存器 +```c +vld1_type: 按顺序将内存的数据装入neon寄存器,并返回元素类型为type格式的vector +vld1q_type: 128位 +vld1_lane_type:用旧vector创建一个同类型的新vector,同时将新vector中指定元素的值改为内存中的值。 +vld1q_lane_type: +vld1_dup_type:用type类型的内存中第一个值,初始化一个元素类型为type的新vector的所有元素。 +vld1q_dup_type: +vld2_type: 按交叉顺序将内存的数据装入2个neon寄存器(内存第1个数据放入第1个neon寄存器的第1个通道,内存第2个数据放入第2个neon寄存器的第1个通道,内存第3个数据放入第1个neon寄存器的第2个通道,内存第4个数据放入第2个neon寄存器的第2个通道。。。)。并返回有两个vector的结构体 +vld2q_type: +vld2_lane_type: +vld2q_lane_type: +vld2_dup_type: 用type类型的内存中第一个值,初始化第一个新vector的所有元素,用内存中第二个值,初始化第二个新vector的所有元素。 +vld3_type: 交叉存放,本质上与vld2_type类似,只是这里装载3个neon寄存器 +vld3q_type: +vld3_lane_type: +vld3q_lane_type: +vld3_dup_type: 本质上与vld2_dup_type类似 +vld4_type: 交叉存放,本质上与vld2_type类似,只是这里装载4个neon寄存器 +vld4q_type: +vld4_lane_type: +vld4q_lane_type: +vld4q_dup_type: 本质上与vld2_dup_type类似 +``` + + +## 从neon寄存器加载数据进内存 +```c +vst1_type: 将元素类型为type格式的vector的所有元素装入内存 +vst1q_type: +vst1_lane_type: 将元素类型为type格式的vector中指定的某个元素装入内存 +vst1q_lane_type: +vst2_type: 交叉存放,vld2_type的逆过程 +vst2q_type: +vst2_lane_type: +vst2q_lane_type: +vst3_type: 交叉存放,vld3_type的逆过程 +vst3q_type: +vst3_lane_type: +vst3q_lane_type: +vst4_type: 交叉存放,vld4_type的逆过程 +vst4q_type: +vst4_lane_type: +vst4q_lane_type: +``` +## 直接获取neon寄存器某个通道的值 +```c +vget_low_type: 获取128bit vector的低半部分元素,输出的是元素类型相同的64bit vector。 +vget_high_type: 获取128bit vector的高半部分元素,输出的是元素类型相同的64bit vector。 +vget_lane_type: 获取元素类型为type的vector中指定的某个元素值。 +vgetq_lane_type: +``` +## 直接设置neon寄存器某个通道的值 +```c +vset_lane_type: 设置元素类型为type的vector中指定的某个元素的值,并返回新vector。 +vsetq_lane_type: +``` +## 寄存器数据重排 +```c +vext_type: 取第2个输入vector的低n个元素放入新vector的高位,新vector剩下的元素取自第1个输入vector最高的几个元素(可实现vector内元素位置的移动) +vextq_type: +如:src1 = {1,2,3,4,5,6,7,8} +       src2 = {9,10,11,12,13,14,15,16} +       dst = vext_type(src1,src2,3)时,则dst = {4,5,6,7,8, 9,10,11} + +vtbl1_type: 第二个vector是索引,根据索引去第一个vector(相当于数组)中搜索相应的元素,并输出新的vector,超过范围的索引返回的是0. +如:src1 = {1,2,3,4,5,6,7,8} +       src2 = {0,0,1,1,2,2,7,8} +       dst = vtbl1_u8(src1,src2)时,则dst = {1,1,2,2,3,3,8,0} + +vtbl2_type: 数组长度扩大到2个vector +如:src.val[0] = {1,2,3,4,5,6,7,8} +       src.val[1] = {9,10,11,12,13,14,15,16} +       src2 = {0,0,1,1,2,2,8,10} +       dst = vtbl2_u8(src,src2)时,则dst = {1,1,2,2,3,3,9,11} + +vtbl3_type: +vtbl4_type: +vtbx1_type: 根vtbl1_type功能一样,不过搜索到的元素是用来替换第一个vector中的元素,并输出替换后的新vector,当索引超出范围时,则不替换第一个vector中相应的元素。 +vtbx2_type: +vtbx3_type: +vtbx4_type: +vrev16_type: 将vector中的元素位置反转 + +vrev16q_type: +如:src1 = {1,2,3,4,5,6,7,8} +       dst = vrev16_u8(src1)时,则dst = {2,1,4,3,6,5,8,7} + +vrev32_type: + +vrev32q_type: +如:src1 = {1,2,3,4,5,6,7,8} +       dst = vrev32_u8(src1)时,则dst = {4,3,2,1,8,7,6,5} +vrev64_type: + +vrev64q_type: +如:src1 = {1,2,3,4,5,6,7,8} +       dst = vrev32_u8(src1)时,则dst = {8,7,6,5,4,3,2,1} + +vtrn_type: 将两个输入vector的元素通过转置生成一个有两个vector的矩阵 +vtrnq_type: +如:src.val[0] = {1,2,3,4,5,6,7,8} +       src.val[1] = {9,10,11,12,13,14,15,16} +       dst = vtrn_u8(src.val[0], src.val[1])时, +       则 dst.val[0] = {1,9, 3,11,5,13,7,15} +           dst.val[1] = {2,10,4,12,6,14,8,16} + +vzip_type: 将两个输入vector的元素通过交叉生成一个有两个vector的矩阵 +vzipq_type: +如:src.val[0] = {1,2,3,4,5,6,7,8} +       src.val[1] = {9,10,11,12,13,14,15,16} +       dst = vzip_u8(src.val[0], src.val[1])时, +       则dst.val[0] = {1,9, 2,10,3,11,4,12} +           dst.val[1] = {5,13,6,14,7,15,8,16} + +vuzp_type: 将两个输入vector的元素通过反交叉生成一个有两个vector的矩阵(通过这个可实现n-way 交织) +vuzpq_type: +如:src.val[0] = {1,2,3,4,5,6,7,8} +       src.val[1] = {9,10,11,12,13,14,15,16} +       dst = vuzp_u8(src.val[0], src.val[1])时, +       则dst.val[0] = {1,3,5,7,9, 11,13,15} +           dst.val[1] = {2,4,6,8,10,12,14,16} + +vcombine_type: 将两个元素类型相同的输入vector拼接成一个同类型但大小是输入vector两倍的新vector。新vector中低部分元素存放的是第一个输入vector元素。 +vbsl_type:按位选择,参数为(mask, src1, src2)。mask的某个bit为1,则选择src1中对应的bit,为0,则选择src2中对应的bit。 +vbslq_type: +``` + +## 加法 +```c +vadd_type: ri = ai + bi +vaddq_type: +vaddl_type: 变长加法运算,为了防止溢出 +vaddw_type: 第一个vector元素宽度大于第二个vector元素 +vaddhn_type: 结果vector元素的类型大小是输入vector元素的一半 +vqadd_type: ri = sat(ai + bi) 饱和指令,相加结果超出元素的最大值时,元素就取最大值。 +vqaddq_type: +vhadd_type: 相加结果再除2。ri = (ai + bi) >> 1; +vhaddq_type: +vrhadd_type: 相加结果再除2(四舍五入)。ri = (ai + bi + 1) >> 1 +vrhaddq_type: +vpadd_type: r0 = a0 + a1, ..., r3 = a6 + a7, r4 = b0 + b1, ..., r7 = b6 + b7 +vpaddl_type: r0 = a0 + a1, ..., r3 = a6 + a7; +vpaddlq_type: +vpadal_type: r0 = a0 + (b0 + b1), ..., r3 = a3 + (b6 + b7); +``` +## 减法 +```c +vsub_type: ri = ai - bi +vsubq_type: +vsubl_type: +vsubw_type: +vsubhn_type: +vqsub_type: 饱和指令 ri = sat(ai - bi) +vqsubq_type: +vhsub_type: 相减结果再除2。ri = (ai - bi) >> 1 +vhsubq_type: +vrsubhn_type: 相减结果再除2(四舍五入)。ri = (ai - bi + 1) >> 1 +``` +## 乘法 +```c +vmul_type: ri = ai * bi +vmulq_type: +vmul_n_type: ri = ai * b +vmulq_n_type: +vmul_lane_type: ri = ai * b[c] +vmulq_lane_type: +vmull_type: 变长乘法运算,为了防止溢出 +vmull_n_type: +vmull_lane_type: +vqdmull_type: 变长乘法运算,参与运算的值是有符号数(所以可能溢出),当结果溢出时,取饱和值 +vqdmull_n_type: +vqdmull_lane_type: +vqdmulh_type: +vqdmulhq_type: +vqdmulh_n_type: +vqdmulhq_n_type: +vqdmulh_lane_type: +vqdmulhq_lane_type: +vqrdmulh_type: +vqrdmulhq_type: +vqrdmulh_n_type: +vqrdmulhq_n_type: +vqrdmulh_lane_type: +vqrdmulhq_lane_type: +``` +## 乘加组合运算 +```c +vmla_type: ri = ai + bi * ci +vmlaq_type: +vmla_n_type: ri = ai + bi * c +vmlaq_n_type: +vmla_lane_type: ri = ai + bi * c[d] +vmlaq_lane_type: +vmlal_type: 长指令 ri = ai + bi * ci +vmlal_n_type: +vmlal_lane_type: +vfma_f32:ri = ai + bi * ci 在加法之前,bi、ci相乘的结果不会被四舍五入 +vqdmlal_type: ri = sat(ai + bi * ci)  bi/ci的元素大小是ai的一半 +vqdmlal_n_type: ri = sat(ai + bi * c) +vqdmlal_lane_type: ri = sat(ai + bi * c[d]) +``` +## 乘减组合运算 +```c +vmls_type: ri = ai - bi * ci +vmlsq_type: +vmls_n_type: ri = ai - bi * c +vmlsq_n_type: +vmls_lane_type: ri = ai - bi * c[d] +vmlsq_lane_type: +vmlsl_type: 长指令 ri = ai - bi * ci +vmlsl_n_type: +vmlsl_lane_type: +vfms_f32:ri = ai - bi * ci 在减法之前,bi、ci相乘的结果不会被四舍五入 +vqdmlsl_type: ri = sat(ai - bi * ci) bi/ci的元素大小是ai的一半 +vqdmlsl_n_type: ri = sat(ai - bi * c) +vqdmlsl_lane_type: ri = sat(ai - bi * c[d]) +``` +## 取整 +```c +vrndn_f32: to nearest, ties to even +vrndqn_f32: +vrnda_f32: to nearest, ties away from zero +vrndqa_f32: +vrndp_f32: towards +Inf +vrndqp_f32: +vrndm_f32: towards -Inf +vrndqm_f32: +vrnd_f32: towards 0 +vrnqd_f32: +``` +## 比较运算 +```c +(结果为true,则所有的bit位被设置为1) + +vceq_type: ri = ai == bi ? 1...1 : 0...0 +vceqq_type: +vcge_type: ri = ai >= bi ? 1...1:0...0 +vcgeq_type: +vcle_type: ri = ai <= bi ? 1...1:0...0 +vcleq_type: +vcgt_type: ri = ai > bi ? 1...1:0...0 +vcgtq_type: +vclt_type: ri = ai < bi ? 1...1:0...0 +vcltq_type: +vcage_f32: ri = |ai| >= |bi| ? 1...1:0...0 +vcageq_f32: +vcale_f32: ri = |ai| <= |bi| ? 1...1:0...0 +vcaleq_f32: +vcagt_f32: ri = |ai| > |bi| ? 1...1:0...0 +vcagtq_f32: +vcalt_f32: ri = |ai| < |bi| ? 1...1:0...0 +vcaltq_f32: +vtst_type: ri = (ai & bi != 0) ? 1...1:0...0  +vtstq_type: +``` +## 绝对值 +```c +vabs_type: ri = |ai| +vabsq_type: +vqabs_type: ri = sat(|ai|) +vqabsq_type: +vabd_type: ri = |ai - bi| +vabdq_type: +vabdl_type: 长指令 +vaba_type: ri = ai + |bi - ci| +vabaq_type: +vabal_type: 长指令 +``` +## 取最大最小值 +```c +vmax_type: ri = ai >= bi ? ai : bi +vmaxq_type: +vpmax_type: r0 = a0 >= a1 ? a0 : a1, ..., r4 = b0 >= b1 ? b0 : b1, ... +vmin_type: ri = ai <= bi ? ai : bi +vminq_type: +vpmin_type: r0 = a0 <= a1 ? a0 : a1, ..., r4 = b0 <= b1 ? b0 : b1, ... +```c +## 倒数 +```c +vrecpe_type: 求近似倒数,type是f32或者u32 +vrecpeq_type: +vrecps_f32:(牛顿 - 拉夫逊迭代) +vrecpsq_f32 +注:vrecpe_type计算倒数能保证千分之一左右的精度,如1.0的倒数为0.998047。执行完如下语句后能提高百万分之一精度 +float32x4_t recip = vrecpeq_f32(src);此时能达到千分之一左右的精度,如1.0的倒数为0.998047 +recip = vmulq_f32 (vrecpsq_f32 (src, rec), rec);执行后能达到百万分之一左右的精度,如1.0的倒数为0.999996 +recip = vmulq_f32 (vrecpsq_f32 (src, rec), rec);再次执行后能基本能达到完全精度,如1.0的倒数为1.000000 +``` +## 平方根倒数 +```c +vrsqrte_type: 计算输入值的平方根的倒数,type是f32或者u32。输入值不能是负数,否则计算出来的值是nan。 +vrsqrteq_type: +vrsqrts_f32 +vrsqrtsq_f32 +``` +## 移位运算 +```c +vshl_type: ri = ai << bi 如果bi是负数,则变成右移 +vshlq_type: +vshl_n_type: ri = ai << b 这里b是常数,如果传入的不是常数(即在编译的时候就要知道b的值),编译时会报错 +vshlq_n_type: +vqshl_type: ri = sat(ai << bi) +vqshlq_type: +vrshl_type: ri = round(ai << bi) +vrshlq_type: +vqrshl_type: ri = sat&round(ai << bi) +vqrshlq_type: +vqshl_n_type: ri = sat(ai << b) +vqshlq_n_type: +vqshlu_n_type: ri = ai << b 输入vector是有符号,输出vector是无符号 +vqshluq_n_type: +vshll_n_type: + +vshr_n_type: ri = ai >> b +vshrq_n_type: +vrshr_n_type: ri = round(ai >> b) +vrshrq_n_type: +vsra_n_type: ri = (ai >> c) + (bi >> c) +vsraq_n_type: +vrsra_n_type: ri = round((ai >> c) + (bi >> c)) +vrsraq_n_type: +vshrn_n_type:  窄指令ri = ai >> b +vqshrun_n_type: +vqrshrun_n_type: +vqshrn_n_type: +vrshrn_n_type: +vqrshrn_n_type: + +vsri_n_type: +vsriq_n_type: +vsli_n_type: +vsliq_n_type: +``` +## 取负 +```c +vneg_type: ri = -ai +vnegq_type: +vqneg_type: ri = sat(-ai) +vqnegq_type: +``` +## 按位运算 +```c +vmvn_type: ri = ~ai +vmvnq_type: +vand_type: ri = ai & bi +vandq_type: +vorr_type: ri = ai | bi +vorrq_type: +veor_type: ri = ai ^ bi +veorq_type: +vbic_type: ri = ~ai & bi +vbicq_type: +vorn_type: ri = ai | (~bi) +vornq_type: +``` +## 统计 +```c +vcls_type: +vclz_type: +vcnt_type: 统计向量每个元素有多少bit位是1 +vcntq_type: +``` +## 数据类型转换 +```c +vcvt_type1_type2: f32、u32、s32之间的转换。在f32转到u32时,是向下取整,且如果是负数,则转换后为0 +vcvtq_type1_type2: +vcvt_n_type1_type2: +vcvtq_n_type1_type2: +vreinterpret_type1_type2: 将元素类型为type2的vector转换为元素类型为type1的vector。数据重新解析 +vreinterpretq_type1_type2: +``` diff --git a/CNN/HighPerformanceComputing/readme.md b/CNN/HighPerformanceComputing/readme.md index c21324d4..84003a4e 100644 --- a/CNN/HighPerformanceComputing/readme.md +++ b/CNN/HighPerformanceComputing/readme.md @@ -7,9 +7,116 @@ 基本的网络拓扑和组织可以使用一个简单的总线拓扑, 在性能很高的环境中,网状网络系统在主机之间提供较短的潜伏期, 所以可改善总体网络性能和传输速率。 +[让深度学习更高效运行的两个视角 | 计算量和访存](https://zhuanlan.zhihu.com/p/33693725) + +[海思NNIE之Mobilefacenet量化部署](https://github.com/Ewenwan/nniefacelib) + +[斯坦福大学Fall 2018课程-机器学习硬件加速器 cs217](https://cs217.stanford.edu/) [浮点运算和代码优化, 并行计算, Optimizer软件](http://antkillerfarm.github.io/ai/2015/10/12/float.html) +[第十七章 模型压缩及移动端部署](https://github.com/scutan90/DeepLearning-500-questions/blob/master/ch17_%E6%A8%A1%E5%9E%8B%E5%8E%8B%E7%BC%A9%E3%80%81%E5%8A%A0%E9%80%9F%E5%8F%8A%E7%A7%BB%E5%8A%A8%E7%AB%AF%E9%83%A8%E7%BD%B2/%E7%AC%AC%E5%8D%81%E4%B8%83%E7%AB%A0_%E6%A8%A1%E5%9E%8B%E5%8E%8B%E7%BC%A9%E3%80%81%E5%8A%A0%E9%80%9F%E5%8F%8A%E7%A7%BB%E5%8A%A8%E7%AB%AF%E9%83%A8%E7%BD%B2.md) + +# 相关 库 + 0、小米 mace +[代码](https://github.com/Ewenwan/mace) + + Mobile AI Compute Engine (MACE) 是一个专为移动端异构计算平台优化的神经网络计算框架。 + +mace是基于opencl开发的,mace框架出来得比较早,当然没有比arm的computelibrary早。很多框架的GPU推理实现都或多或少的参考了computeLibrary。 + + 1、OpenVINO intel cpu 核显 优化加速 + Intel推出OpenVINO工具包,将计算机视觉带到物联网终端 + OpenVINO(开放的视觉推理和神经网络优化)工具包 + 使开发人员能够在云上(如TensorFlow,MXNet和Caffe等流行款框架)构建和训练人工智能模型, + 并将其部署到各种产品中。 + Windows* + Linux* (supports Ubuntu*, CentOS*, and Yocto Project*) + Linux for FPGA +[英特尔推深度学习加速工具包 OpenVINO](https://github.com/Ewenwan/dldt) + + + 2、腾讯NCNN框架入门到应用 + +[代码](https://github.com/Ewenwan/ncnn) + +腾讯的ncnn:使用vulkan,支持跨平台ios,android。不过ios需要通过第三方的SDK才能使用vulkan。苹果自己开发了一套metal的gpu编程API。以后ios上什么opencl,opengles,vulkan都不再是官方原生支持的GPU编程api了。 + + + 3、FeatherCNN +[代码](https://github.com/Ewenwan/FeatherCNN) + + 4、Tengine 高性能神经网络推理引擎 +[代码](https://github.com/Ewenwan/Tengine) + + 5、百度MDL +[代码](https://github.com/Ewenwan/paddle-mobile) + +百度的paddle-lite:使用vulkan开发安卓版本的GPU推理,使用metal开发IOS版本的GPU推理 + + 6、九言科技 绝影(Prestissimo) +[代码](https://github.com/Ewenwan/In-Prestissimo) + + 7、Google量化方法 r=S(q-Z) tflite TensorFlow Lite +[代码](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/lite) + + 8、英伟达 TensorRT , NVIDIA TensorRT是一种高性能神经网络推理(Inference)引擎 +[代码](https://github.com/Ewenwan/TensorRT_Tutorial) + +[英伟达 CUDA 和 TensorRT 代码实验](https://github.com/Ewenwan/CUDA_Test) + + 9、FaceBOOK caffe2 pytorch QNNPACK uint8量化 +[QNNPACK uint8量化 ](https://github.com/Ewenwan/QNNPACK) + + +[深度学习框架的并行优化方法小结](https://github.com/DragonFive/myblog/blob/master/source/_posts/mpi_parallel.md) + + + 10、阿里的mnn + +使用opencl,opengles,vulkan,metal四种GPU编程API开发了这个推理框架。据说很多公司开始把mnn纳入到公司内部的推理框架进行二次开发,估计更全面的GPU编程API支持是其一个最大优势。 + + 11、谷歌的tflite: + +使用opengles的compute shader实现了安卓版本的GPU推理,对于IOS版本则是使用metal开发。 + + 12、arm中国的tengine: + +tengine使用的是arm compute library框架作为底层GPU实现,据了解tengine在cpu端的优化下了很大功夫,当然作为ARM旗下的推理框架,自然对arm的架构和ISA指令更加了解。 + +arm compute library:这个框架是使用opencl和opengles来实现GPU推理的。该框架做得比较早。是armnn的底层推理实现。因为arm独特的ip授权模式,armnn是为了让半导体公司能直接打通安卓的android-nn框架。 + +13、 闭源的高通SNPE。 + +snpe是高通开发的一个推理框架,支持GPU推理,之前尝试分析过,一些调试数据看,内部必然存在opencl实现。 + + +当然,这些框架为了兼容性,都实现了CPU的推理功能。毕竟cpu推理兼容性更好,特别是现阶段几乎所有的手机端都是采用ARM的cpu。因此使用cpu的推理方案兼容性会更好。 + +# 背景 + +Roofline Model。 + +这个Model是指计算机上的一个应用,它占用了两类最主要的资源:算术逻辑单元的计算资源,存储器的带宽资源。这里的计算资源以FLOPS来表示;带宽资源以byte/s表示。 + +Roofline model是说什么呢?横轴是Operational Intensity,就是计算的密度,单位是FLOPS/byte;纵轴是performance,也就是性能,单位是FLOPS。 + +图中有一条折线,这个折线开始的时候是随着计算密度的增加而增加,最终会稳定在一个固定的performance上。这个意思是:当这个应用程序的计算密度大于一定值之后,将会变成一个受算术逻辑单元的计算量所限制的程序;而这个计算密度如果小于一定值,将会变成一个受存储器带宽所限制的程序。 + +这里折线的拐点非常重要。这个拐点跟硬件很相关,它实际上表示的是硬件的理论计算能力和它的内存带宽之间的一个比值。 + +举两个具体的例子,第一个是矩阵乘矩阵,矩阵C等于A乘B,而A跟B分别是一千乘一千的矩阵。假设存储和计算都是用float 32位来表示,这样一个计算将会做1000乘1000乘1000的浮点乘加,也就是2G FLOPS的运算。我们要读取A和B,然后计算出来C,把它写回去,最少的存储器访问就是三个矩阵的大小,也就是12个MB。 + +另外一个是矩阵乘向量,也就是矩阵A乘向量B,等于向量C,这时候维度还是1000的情况下,它的计算量就是1000乘1000的浮点乘加,也就是2M。而存储器访问的话最少大约是1000乘于1000个浮点数,也就是4MB。 + +可以明显地看到上面乘矩阵的操作,它的计算量是2G,访存量是12M,那么它的这个计算量除以访存量,也就是刚刚提到的计算密度,大概是200左右。下面这个矩阵和向量中,它的计算量是2M,访存量是4M,那它的计算量除以访存量大约就只有0.5,显然这两个就是非常不同的程序。 + +上面矩阵乘矩阵,是一个典型的受计算量约束的程序;而下面矩阵乘向量则是一个典型的受存储器带宽所约束的程序。 + +小模型部署在这些硬件上,通常都是被存储带宽所限制住了,而不是被计算量所限制住。 + + + ## 卷积计算优化 目前,卷积的计算大多采用间接计算的方式,主要有以下三种实现方式: @@ -18,8 +125,8 @@ 原因是将问题转化为矩阵乘法后可以方便的使用很多矩阵运算库(如MKL、openblas、Eigen等)。 [openblas](https://www.leiphone.com/news/201704/Puevv3ZWxn0heoEv.html) -[GEMM 普通矩阵乘法(General Matrix Multiplication)](https://github.com/flame/how-to-optimize-gemm/wiki) - +[GEMM 普通矩阵乘法(General Matrix Multiplication)多种优化](https://github.com/flame/how-to-optimize-gemm/wiki) + 2、FFT变换。 时域卷积等于频域相乘,因此可将问题转化为简单的乘法问题。 @@ -48,16 +155,30 @@ ![](https://static.leiphone.com/uploads/new/article/740_740/201704/58f08bf33fabd.png?imageMogr2/format/jpg/quality/90) +BLAS是 Basic Linear Algebra Subprograms (基本线性代数子程序)的首字母缩写,主要用来做基础的矩阵计算,或者是向量计算。它分为三级: + + BLAS 1级,主要做向量与向量间的dot或乘加运算,对应元素的计算; + BLAS 2级,主要做矩阵和向量,就类似PPT中蓝色部分所示,矩阵A*向量x, 得到一个向量y。除此之外,可能还会有对称的矩阵变形; + BLAS 3级,主要是矩阵和矩阵的计算,最典型的是A矩阵*B矩阵,得到一个C矩阵。由矩阵的宽、高,得到一个m*n的C矩阵。 + + 最原始3个for循环 (矩阵比较小的时候,速度还能快一些,当矩阵大了的时候,一定会跌下去,cache缓存问题): ![](https://static.leiphone.com/uploads/new/article/740_740/201704/58f08d87a8397.png?imageMogr2/format/jpg/quality/90) -矩阵分块,块复用,减少仿存,相当于减少内存访问: +矩阵分块,块复用,减少仿存,相当于减少内存访问,提高Cache利用率: ![](https://static.leiphone.com/uploads/new/article/740_740/201704/58f08dd7b16d4.png?imageMogr2/format/jpg/quality/90) ![](https://static.leiphone.com/uploads/new/article/740_740/201704/58f08e08680b9.png?imageMogr2/format/jpg/quality/90) +核心汇编优化: + +* 寄存器分块 +* SIMD指令 +* 指令流水线优化,循环展开,重排,预取 + + 操作寄存器,不是操作内存: 我可以申请一堆C 00,01这样的寄存器变量,在C语言中是register double,还有矩阵A的部分,也用寄存器变量。 @@ -87,47 +208,3 @@ B矩阵仿存,使用指针访问, 之后可以使用更大的分块,在进行寄存器,指针,展开优化。 -# 在深度神经网络中 特指提高卷积计算方式的方法 - 0、小米 mace -[代码](https://github.com/Ewenwan/mace) - - Mobile AI Compute Engine (MACE) 是一个专为移动端异构计算平台优化的神经网络计算框架。 - - 1、OpenVINO - Intel推出OpenVINO工具包,将计算机视觉带到物联网终端 - OpenVINO(开放的视觉推理和神经网络优化)工具包 - 使开发人员能够在云上(如TensorFlow,MXNet和Caffe等流行款框架)构建和训练人工智能模型, - 并将其部署到各种产品中。 - Windows* - Linux* (supports Ubuntu*, CentOS*, and Yocto Project*) - Linux for FPGA - - - 2、腾讯NCNN框架入门到应用 - -[代码](https://github.com/Ewenwan/ncnn) - - 3、FeatherCNN -[代码](https://github.com/Ewenwan/FeatherCNN) - - 4、Tengine 高性能神经网络推理引擎 -[代码](https://github.com/Ewenwan/Tengine) - - 5、百度MDL -[代码](https://github.com/Ewenwan/paddle-mobile) - - 6、九言科技 绝影(Prestissimo) -[代码](https://github.com/Ewenwan/In-Prestissimo) - - 7、Google量化方法 r=S(q-Z) tflite TensorFlow Lite -[代码](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/lite) - - 8、英伟达 TensorRT , NVIDIA TensorRT是一种高性能神经网络推理(Inference)引擎 -[代码](https://github.com/Ewenwan/TensorRT_Tutorial) - -[英伟达 CUDA 和 TensorRT 代码实验](https://github.com/Ewenwan/CUDA_Test) - - 9、FaceBOOK caffe2 pytorch QNNPACK uint8量化 -[QNNPACK uint8量化 ](https://github.com/Ewenwan/QNNPACK) - -[深度学习框架的并行优化方法小结](https://github.com/DragonFive/myblog/blob/master/source/_posts/mpi_parallel.md) diff --git a/CNN/HighPerformanceComputing/snpe/readme.md b/CNN/HighPerformanceComputing/snpe/readme.md new file mode 100644 index 00000000..5c2a973c --- /dev/null +++ b/CNN/HighPerformanceComputing/snpe/readme.md @@ -0,0 +1,96 @@ +# 高通SNPE 神经网络处理引擎(SNPE) + +[snpe-1.6.0/helper.md ](https://github.com/RuiZeWu/Android-OpenPose/blob/master/snpe-1.6.0/helper.md) + + +可运行于搭载了高通Zeroth机器智能平台的820芯片处理器,开发者可以在SNPE上搭建自己的深度学习网络模型。更详细的介绍可以登录高通SNPE相关网页了解:https://developer.qualcomm.com/software/snapdragon-neural-processing-engine + +高通提供了用户定义层(UDL)功能,通过回调函数可以自定义算子,并通过重编译C++代码将自定义文件编译到可执行文件中。如果开发就是使用的C++,那比较容易实现用户定义层,但如果是运行在Android上就比较麻烦了,上层java代码需要通过JNI来调用snpe原生的C++编译好的.so文件,因为用户定义层的代码是不可能预先编译到snpe原生.so文件中的,所以用snpe提供的Java + API是无法获得用户定义层的功能的,所以,必须重新开发SNPE的JNI。 + + +> 使用SNPE,用户可以: + +1.执行任意深度的神经网络 +2.在SnapdragonTM CPU,AdrenoTM GPU或HexagonTM DSP上执行网络。 +3.在x86 Ubuntu Linux上调试网络执行 +4.将Caffe,Caffe2,ONNXTM和TensorFlowTM模型转换为SNPE深度学习容器(DLC)文件 +5.将DLC文件量化为8位定点,以便在Hexagon DSP上运行 +6.使用SNPE工具调试和分析网络性能 +7.通过C ++或Java将网络集成到应用程序和其他代码中 + + +模型训练在流行的深度学习框架上进行(SNPE支持Caffe,Caffe2,ONNX和TensorFlow模型。)训练完成后,训练的模型将转换为可加载到SNPE运行时的DLC文件。 然后,可以使用此DLC文件使用其中一个Snapdragon加速计算核心执行前向推断传递。 + +> 基本的SNPE工作流程只包含几个步骤: + +1.将网络模型转换为可由SNPE加载的DLC文件。 +2.可选择量化DLC文件以在Hexagon DSP上运行。 +3.准备模型的输入数据。 +4.使用SNPE运行时加载并执行模型。 + + +> 配置环境,用Snapdragon NPE SDK进行人工智能的开发需要满足一些先决条件的,具体如下所述: + +1.需要运行一个卷积模型的一个或多个垂直行业,包括手机、汽车、物联网、AR,机器人,和机器人 +2.知道怎样去设置并且训练一个模型或者已经有一个训练好的模型文件。 +3.选择的framework应该是Caffe/Caffe2或者TensorFlow +4.你做Android 的JAVA APPs或者使用Android或LInux本地的应用。 +5.需要有ubuntu 14.04的开发环境 +6.有一个支持的设备用来检测应用。 + + +构建示例Android APP + +Android APP结合了Snapdragon NPE运行环境(/android/snpe-release.aar Android库提供)和 上述Caffe Alexnet示例生成的DLC模型。 + +1.复制运行环境和模型,为构建APP作好准备 + +•cd $SNPE_ROOT/examples/android/image-classifiers +•cp ../../../android/snpe- release.aar ./app/libs # copies the NPE runtime library +•bash ./setup_models.sh # packages the Alexnet example (DLC, labels, imputs) as an Android resource file + +选项A:从Android studio构建Android APK: + +1.启动Android Studio。 +2.打开~/snpe-sdk/examples/android/image- classifiers文件夹中的项目。 +3.如有的话,接受Android Studio建议,升级 构建系统组件。 +4.按下“运行应用”按钮,构建并运行APK。 + +选项B:从命令行构建Android APK: + +•sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386 lib32z1 +•libbz2-1.0:i386 # Android SDK build dependencies on ubuntu +•./gradlew assembleDebug # build the APK + +上述命令可能需要将ANDROID_HOME和JAVA_HOME 设置为系统中的Android SDK和JRE/JDK所在位置。 +## linux 下开发 + +一、下载地址 + + https://developer.qualcomm.com/software/qualcomm-neural-processing-sdk + +二、配置步骤 + + 2.1 $ unzip -X snpe-X.Y.Z.zip + + 2.2 $ source snpe-X.Y.Z/bin/dependencies.sh + + 2.3 $ source snpe-X.Y.Z/bin/check_python_depends.sh + + 2.4 下载caffe + + $ git clone https://github.com/BVLC/caffe.git + + $ git checkout d8f79537977f9dbcc2b7054a9e95be00eb6f26d0 (切换到这个分支,SNPE文档如此提示) + + 2.4 指定PYTHONPATH路径 + + export SNPE_ROOT=/home/pengcuo/work/snpe/snpe-1.19.2 + export ANDROID_NDK_ROOT=/home/pengcuo/buff/android-ndk-r17 + export PYTHONPATH=/home/pengcuo/work/snpe/snpe-1.19.2/lib/python:/home/pengcuo/work/caffe/python:$PYTHONPATH + +三、生成dlc文件 + + $ ./bin/x86_64-linux-clang/snpe-caffe-to-dlc -c small.prototxt + diff --git "a/CNN/HighPerformanceComputing/\346\225\260\345\255\246\344\274\230\345\214\226ensmallen\345\210\206\346\236\220.md" "b/CNN/HighPerformanceComputing/\346\225\260\345\255\246\344\274\230\345\214\226ensmallen\345\210\206\346\236\220.md" new file mode 100644 index 00000000..49910d2d --- /dev/null +++ "b/CNN/HighPerformanceComputing/\346\225\260\345\255\246\344\274\230\345\214\226ensmallen\345\210\206\346\236\220.md" @@ -0,0 +1,2 @@ +# 数学优化ensmallen分析 +[源码](https://github.com/Ewenwan/ensmallen) diff --git a/CNN/Semantic_Segmentation/readme.md b/CNN/Semantic_Segmentation/readme.md index c74e28ba..2993f3af 100644 --- a/CNN/Semantic_Segmentation/readme.md +++ b/CNN/Semantic_Segmentation/readme.md @@ -4,3 +4,5 @@ [图像语义分割的研究进展(课件PPT)](https://blog.csdn.net/sparkexpert/article/details/74279793) [语义分割研究进展](https://blog.csdn.net/cheese_pop/article/details/56014439) + +[图像语义分割之FCN和CRF 条件随机场](https://blog.csdn.net/u012759136/article/details/52434826) diff --git a/CNN/ShuffleNet/readme.md b/CNN/ShuffleNet/readme.md index 998b64a3..8fbc4cc6 100644 --- a/CNN/ShuffleNet/readme.md +++ b/CNN/ShuffleNet/readme.md @@ -11,8 +11,6 @@ [预训练的ShuffleNet-cafe模型参数文件](https://github.com/msnqqer/ShuffleNet) -[预训练模型文件 password is "bcj6"](https://pan.baidu.com/s/1eS8NOm2) - ## ResNet 残差网络  结合不同层特征 ________________________________> | ADD --> f(x) + x diff --git a/CNN/StructuredLearning/readme.md b/CNN/StructuredLearning/readme.md new file mode 100644 index 00000000..765de627 --- /dev/null +++ b/CNN/StructuredLearning/readme.md @@ -0,0 +1,11 @@ +# Structured Learning 结构化学习 + +相比于回归,输出一个标量或者预测,输出一个向量,结构化学习的输出更加复杂,可以是图像,可以是语句,可以是树结构,等等可由更小的组件构成的结构体,我的理解。 + +较火的技术GAN,最多的用处便是生成图像,这就是一个结构化学习的例子,其实像目标检测,语义分割,实例分割这些也是结构化学习,因为他们的输出都不是简单的标量或向量, +是结构更加复杂的输出了,还有,像李宏毅老师课程里讲的,机器翻译,语音识别,聊天机器人都是结构化学习。 + +[李宏毅老师课程](http://speech.ee.ntu.edu.tw/~tlkagk/courses_MLSD15_2.html) + +[李宏毅老师课程 SL笔记](https://www.cnblogs.com/bluemapleman/p/9277175.html) + diff --git a/CNN/VisualQuestionAnswering/readme.md b/CNN/VisualQuestionAnswering/readme.md new file mode 100644 index 00000000..77a30724 --- /dev/null +++ b/CNN/VisualQuestionAnswering/readme.md @@ -0,0 +1,8 @@ +# Visual Question Answering(VQA)视觉问答 + +[【自然语言处理】--视觉问答(Visual Question Answering,VQA)从初始到应用](https://blog.csdn.net/LHWorldBlog/article/details/81124981) + +视觉问答(Visual Question Answering,VQA),是一种涉及计算机视觉和自然语言处理的学习任务。这一任务的定义如下: A VQA system takes as input an image and a free-form, open-ended, natural-language question about the image and produces a natural-language answer as the output[1]。 翻译为中文:一个VQA系统以一张图片和一个关于这张图片形式自由、开放式的自然语言问题作为输入,以生成一条自然语言答案作为输出。简单来说,VQA就是给定的图片进行问答。 + +VQA系统需要将图片和问题作为输入,结合这两部分信息,产生一条人类语言作为输出。针对一张特定的图片,如果想要机器以自然语言来回答关于该图片的某一个特定问题,我们需要让机器对图片的内容、问题的含义和意图以及相关的常识有一定的理解。VQA涉及到多方面的AI技术(图1):细粒度识别(这位女士是白种人吗?)、 物体识别(图中有几个香蕉?)、行为识别(这位女士在哭吗?)和对问题所包含文本的理解(NLP)。综上所述,VQA是一项涉及了计算机视觉(CV)和自然语言处理(NLP)两大领域的学习任务。它的主要目标就是让计算机根据输入的图片和问题输出一个符合自然语言规则且内容合理的答案。 + diff --git a/CNN/readme.md b/CNN/readme.md index 228e6353..9ec1ae0a 100644 --- a/CNN/readme.md +++ b/CNN/readme.md @@ -1,5 +1,7 @@ # 包含目录 +[动手学深度学习(Dive into Deep Learning,D2L) 墙裂推荐](https://github.com/d2l-ai/d2l-zh) + 1. 行为识别 Action_Recognition IDT TSN @@ -51,9 +53,15 @@ ![](https://github.com/Ewenwan/MVision/blob/master/od.png) + +[目标检测相关论文笔记](https://github.com/Ewenwan/windy-afternoon/tree/master/ml/papers/detection) + # 卷积神经网络 [one-stage two-stage目标检测总结](https://zsc.github.io/megvii-pku-dl-course/slides/Lecture6(Object%20Detection).pdf) +[2d目标检测网络各种结构代码](https://github.com/Ewenwan/awesome-object-detection) + + [Deep Learning (Computer Architecture) 计算框架 caffe pytorch](https://zsc.github.io/megvii-pku-dl-course/slides18/deeplearning_framework_peking.pdf) [深度学习数学知识 向量 矩阵 概率密度函数 贝叶斯 协方差 信息熵 KL散度 梯度下降 过拟合 正则化](https://zsc.github.io/megvii-pku-dl-course/slides/Lecture2(MathInDL).pdf) @@ -235,6 +243,8 @@ If you like this, star it, thanks! [ocn代码示例](https://github.com/fengbingchun/OCR_Test) +[Use CTC + tensorflow to OCR ](https://github.com/ilovin/lstm_ctc_ocr) + * CTPN [Detecting Text in Natural Image with Connectionist Text Proposal Network](https://arxiv.org/abs/1609.03605) [中文版](http://noahsnail.com/2018/02/02/2018-02-02-Detecting%20Text%20in%20Natural%20Image%20with%20Connectionist%20Text%20Proposal%20Network%E8%AE%BA%E6%96%87%E7%BF%BB%E8%AF%91%E2%80%94%E2%80%94%E4%B8%AD%E6%96%87%E7%89%88/) @@ -246,5 +256,14 @@ If you like this, star it, thanks! To be added. +## 迁移学习 Transfer Learning +[学习资料论文代码](https://github.com/Ewenwan/transferlearning) + +[学习手册 视觉文本时序医疗健康 KL散度度量 特征学习 子空间 深度对抗网络 ](http://jd92.wang/assets/files/transfer_learning_tutorial_wjd.pdf) + + +## 人脸识别 +[使用Google的人脸检测API检测情绪-Python](http://blog.topspeedsnail.com/archives/10489) +[使用OpenFace进行人脸识别](http://blog.topspeedsnail.com/archives/10933) diff --git a/Character/readme.md b/Character/readme.md new file mode 100644 index 00000000..50df5918 --- /dev/null +++ b/Character/readme.md @@ -0,0 +1,359 @@ +# 文字识别 Optical Character Recognition,OCR + +[自然场景文本检测识别技术综述](https://cloud.tencent.com/developer/article/1154619) + +将图片上的文字内容,智能识别成为可编辑的文本。 + +> 场景文字识别(Scene Text Recognition,STR) + +OCR(Optical Character Recognition, 光学字符识别)传统上指对输入扫描文档图像进行分析处理,识别出图像中文字信息。场景文字识别(Scene Text Recognition,STR) 指识别自然场景图片中的文字信息。自然场景图像中的文字识别,其难度远大于扫描文档图像中的文字识别,因为它的文字展现形式极其丰富: + +1·允许多种语言文本混合,字符可以有不同的大小、字体、颜色、亮度、对比度等。 +2·文本行可能有横向、竖向、弯曲、旋转、扭曲等式样。 +3·图像中的文字区域还可能会产生变形(透视、仿射变换)、残缺、模糊等现象。 +4·自然场景图像的背景极其多样。如文字可以出现在平面、曲面或折皱面上;文字区域附近有复杂的干扰纹理、或者非文字区域有近似文字的纹理,比如沙地、草丛、栅栏、砖墙等。 + + +也有人用OCR技术泛指所有图像文字检测和识别技术, 包括传统OCR技术与场景文字识别技术。这是因为,场景文字识别技术可以被看成是传统OCR技术的自然演进与升级换代。 + + + +> **应用:** + +1.身份证、名片、银行卡、户口本等卡证类、出版物(扫描版图像、试题)、票据类(发票、火车票、彩票、出租车票)的印刷体识别; + +2.运单、考试试卷、办公手写文档、快递手写单号等手写体识别; + +3.车牌、集装箱号、快递运单、行驶证、驾驶证、等交通物流字符识别等; + +4.水表、电表、燃气表等各种传感器可视化数据识别(5G物联网之后可能就不需要了); + +5.图像文字检测和识别技术有着广泛的应用场景。已经被互联网公司落地的相关应用涉及了识别名片、识别菜单、识别快递单、识别身份证、识别营业证、识别银行卡、识别车牌、识别路牌、识别商品包装袋、识别会议白板、识别广告主干词、识别试卷、识别单据等等。 + +文本检测和识别技术处于一个学科交叉点,其技术演进不断受益于计算机视觉处理和自然语言处理两个领域的技术进步。它既需要使用视觉处理技术来提取图像中文字区域的图像特征向量,又需要借助自然语言处理技术来解码图像特征向量为文字结果。 + + +## 什么是OCR? + +OCR英文全称是Optical Character Recognition,中文叫做光学字符识别。它是利用光学技术和计算机技术把印在或写在纸上的文字读取出来,并转换成一种计算机能够接受、人又可以理解的格式。文字识别是计算机视觉研究领域的分支之一,而且这个课题已经是比较成熟了,并且在商业中已经有很多落地项目了。比如汉王OCR、百度OCR、阿里OCR、腾讯OCR等等,很多企业都有能力都是拿OCR技术开始挣钱了。其实我们自己也能感受到,OCR技术确实也在改变着我们的生活:比如一个手机APP就能帮忙扫描名片、身份证,并识别出里面的信息;汽车进入停车场、收费站都不需要人工登记了,都是用车牌识别技术;我们看书时看到不懂的题,拿个手机一扫,APP就能在网上帮你找到这题的答案。太多太多的应用了,OCR的应用在当今时代确实是百花齐放啊。 + +## OCR的发展 + +在一些简单环境下OCR的准确度已经比较高了(比如电子文档),但是在一些复杂环境下的字符识别,在当今还没有人敢说自己能做的很好。现在大家都很少会把目光还放在如何对电子文档的文字识别该怎么进一步提高准确率了,因为他们把目光放在更有挑战性的领域。OCR传统方法在应对复杂图文场景的文字识别显得力不从心,越来越多人把精力都放在研究如何把文字在复杂场景读出来,并且读得准确作为研究课题,用学界术语来说,就是场景文本识别(文字检测+文字识别)。自然场景下的文字识别比简单场景的文字识别实在困难太多了,现在虽然出了很多成果,但是离理想结果还是差很远。 + + +## OCR的分类 + +如果要给OCR进行分类,我觉得可以分为两类:**手写体识别和印刷体识别**。这两个可以认为是OCR领域两个大主题了,当然印刷体识别较手写体识别要简单得多,我们也能从直观上理解,印刷体大多都是规则的字体,因为这些字体都是计算机自己生成再通过打印技术印刷到纸上。在印刷体的识别上有其独特的干扰:在印刷过程中字体很可能变得断裂或者墨水粘连,使得OCR识别异常困难。当然这些都可以通过一些图像处理的技术帮他尽可能的还原,进而提高识别率。总的来说,单纯的印刷体识别在业界已经能做到很不错了,但说100%识别是肯定不可能的,但是说识别得不错那是没毛病。 + +印刷体已经识别得不错了,那么手写体呢?手写体识别一直是OCR界一直想攻克的难关,但是时至今天,感觉这个难关还没攻破,还有很多学者和公司在研究。为什么手写体识别这么难识别?因为人类手写的字往往带有个人特色,每个人写字的风格基本不一样,虽然人类可以读懂你写的文字,但是机器缺很难。那为什么机器能读懂印刷体?因为印刷体是机器造出来的啊,那机器当然能读懂自己造的字体啦哈哈~其实上面也提到了,印刷体一般都比较规则,字体都基本就那几十种,机器学习这几十种字体并不是一件难事,但是手写体,每个人都有一种字体的话,那机器该学习多少字体啊?这就是难度所在。 + +如果按识别的内容来分类,也就是按照识别的语言的分类的话,那么要识别的内容将是人类的所有语言**(汉语、英语、德语、法语等)**。如果仅按照我们国人的需求,那识别的内容就包括:**汉字、英文字母、阿拉伯数字、常用标点符号**。根据要识别的内容不同,识别的难度也各不相同。简单而言,识别数字是最简单了,毕竟要识别的字符只有0~9,而英文字母识别要识别的字符有26个(如果算上大小写的话那就52个),而中文识别,要识别的字符高达数千个(二级汉字一共6763个)!因为汉字的字形各不相同,结构非常复杂(比如带偏旁的汉字)如果要将这些字符都比较准确地识别出来,是一件相当具有挑战性的事情。但是,并不是所有应用都需要识别如此庞大的汉字集,比如车牌识别,我们的识别目标仅仅是数十个中国各省和直辖市的简称,难度就大大减少了。当然,在一些文档自动识别的应用是需要识别整个汉字集的,所以要保证识别的整体的识别还是很困难的。 + +传统OCR一般有 模板匹配的方法(简单的场景 单一数字识别)、特征设计提取分类(传统机器学习方法) + +## 现代 OCR 流程 +深度学习的出现,让OCR技术焕发第二春。现在OCR基本都用卷积神经网络来做了,而且识别率也是惊人的好,人们也不再需要花大量时间去设计字符特征了。在OCR系统中,人工神经网络主要充当特征提取器和分类器的功能,输入是字符图像,输出是识别结果,一气呵成。 + +* **1.图像预处理(做角度矫正和去噪) ** + +[传统opencv 轮廓检测+透视变换+二值化](https://www.cnblogs.com/skyfsm/p/7324346.html) + +最后总结一下两个算法的应用场景: + +> 基于轮廓提取的矫正算法更适用于车牌、身份证、人民币、书本、发票一类矩形形状而且边界明显的物体矫正。 + +> 基于直线探测的矫正算法更适用于文本类的矫正。 + +[基于轮廓和直线的图片校正](https://www.cnblogs.com/skyfsm/p/6902524.html) + +[cnn计算图像透视变换系数 Spatial Transformer Network(STN) ](https://arxiv.org/pdf/1506.02025.pdf) + +对于弯曲不规则文本,如果按照之前的识别方法,直接将整个文本区域图像强行送入CNN+RNN,由于有大量的无效区域会导致识别效果很差。所以这篇文章提出一种通过**STN网络Spatial Transformer Network(STN)**学习变换参数,将Rectified Image对应的特征送入后续RNN中识别。 + +对于STN网络,可以学习一组点 (x_i^s,y_i^s) 到对应点 (x_i^t,y_i^t) 的变换。而且STN可以插入轻松任意网络结构中学习到对应的变换。 + + (x_i^s, + y_i^s) = (c11, c12, c13 + c21, c22, c23) * (x_i^t, + y_i^t, + 1) + +〉* **2.字符检测(行分割/列分 解决的问题是哪里有文字,文字的范围)** + +传统算法:行切割(水平投影依据像素值(0为黑色)判断行起止)+列切割(垂直投影) + + 比如“刺”字被分为两部分了,那么我们就直接将这两个“字”送去识别,结果当然是得到一个置信度很低的一个反馈,那么我们就将这两个部分往他们身边最近的、而且没被成功识别的部分进行合并,再将这个合并后的字送进OCR识别,这样子我们就可以通过识别反馈来完成汉字的正确分割和识别了。 + +目标检测相关算法:yolo/ssd/frcnn + + 准确度还比较高 + +〉* **3.字符识别(单个字符识别/序列字符识别)** + +对定位好的文字区域进行识别,主要解决的问题是每个文字是什么,将图像中的文字区域进转化为字符信息. + +cnn + rnn(lstm) + attention + +cnn + rnn(lstm) + CTC + +现今基于深度学习的端到端OCR技术有两大主流技术:CRNN OCR和attention OCR。其实这两大方法主要区别在于最后的输出层(翻译层),即怎么将网络学习到的序列特征信息转化为最终的识别结果。这两大主流技术在其特征学习阶段都采用了CNN+RNN的网络结构,CRNN OCR在对齐时采取的方式是CTC算法(应用更为广泛),而attention OCR采取的方式则是attention机制。 + + +〉* **4.后处理识别矫正(语法检测器,检测字符的组合逻辑是否合理)** + + + + +# 基础网络 + +图文识别任务中充当特征提取模块的基础网络,可以来源于通用场景的图像分类模型。例如,VGGNet,ResNet、InceptionNet、DenseNet、Inside-Outside Net、Se-Net等。 + +图文识别任务中的基础网络,也可以来源于特定场景的专用网络模型。 + +例如,**擅长提取图像细节特征的FCN网络,** + +**擅长做图形矫正的STN网络。** + +## FCN网络 + +全卷积网络(FCN,fully convolutional network), 是去除了全连接(fc)层的基础网络,最初是用于实现语义分割任务。FC的优势在于利用反卷积(deconvolution)、上池化(unpooling)等上采样(upsampling)操作,将特征矩阵恢复到接近原图尺寸,然后对每一个位置上的像素做类别预测,从而能识别出更清晰的物体边界。基于FCN的检测网络,不再经过候选区域回归出物体边框, 而是根据高分辨率的特征图直接预测物体边框。因为不需要像Faster-RCNN那样在训练前定义好候选框长宽比例,FCN在预测不规则物体边界时更加鲁棒。由于FCN网络最后一层特征图的像素分辨率较高,而图文识别任务中需要依赖清晰的文字笔画来区分不同字符(特别是汉字),所以FCN网络很适合用来提取文本特征。当FCN被用于图文识别任务时,最后一层特征图中每个像素将被分成**文字行(前景)和非文字行(背景)两个类别。** + + +## STN网络 + +空间变换网络(STN,Spatial Transformer Networks)的作用是对输入特征图进行空间位置矫正得到输出特征图,这个矫正过程是可以进行梯度传导的,从而能够支持端到端的模型训练。 + +如下图所示,STN网络由定位网络(Localization Network) ,网格生成器(Grid generator),采样器(Sampler)共3个部分组成。定位网络根据原始特征图U计算出一套控制参数,网格生成器这套控制参数产生采样网格(sampling grid),采样器根据采样网格核函数将原始图U中像素对应采样到目标图V中。 + +空间变换的控制参数是根据原始特征图U动态生成的,生成空间变换控制参数的元参数则是在模型训练阶段学习到的、并且存放于定位网络的权重(weights)矩阵中。 + +## CTC网络 +链结式时间分类算法(CTC,Connectionist Temporal Classification)是一个损失函数,主要在序列数据上进行监督式学习,且不需要调整输入数据和标签。 + +## attention注意力网络 特征权重网络 + + +# 检测网络框架 + +Faster RCNN作为一个检测网络框架,其目标是寻找紧凑包围被检测对象的边框(BBOX,Bounding Box)。如下图所示,它在Fast RCNN检测框架基础上引入区域建议网络(RPN,Region Proposal Network),来快速产生与目标物体长宽比例接近的多个候选区域参考框(anchor);它通过ROI(Region of Interest) Pooling层为多种尺寸参考框产生出归一化固定尺寸的区域特征;它利用共享的CNN卷积网络同时向上述RPN网络和ROI Pooling层输入特征映射(Feature Maps),从而减少卷积层参数量和计算量。训练过程中使用到了多目标损失函数,包括RPN网络、ROI Pooling层的边框分类loss和坐标回归loss。通过这些loss的梯度反向传播,能够调节候选框的坐标、并增大它与标注对象边框的重叠度/交并比(IOU,Intersection over Union)。RPN网格生成的候选框初始值有固定位置以及长宽比例。如果候选框初始长宽比例设置得与图像中物体形状差别很大,就很难通过回归找到一个紧凑包围它的边框。 + + +SSD(Single Shot MultiBox Detector),是2016年提出的一种全卷积目标检测算法,截止到目前仍是主要的目标检测框架之一,相比Faster RCNN有着明显的速度优势。如下图所示,SSD是一种one stage算法,直接预测被检测对象的边框和得分。检测过程中,SSD算法利用多尺度思想进行检测,在不同尺度的特征图(feature maps)上产生与目标物体长宽比例接近的多个默认框(Default boxes),进行回归与分类。最后利用非极大值抑制(Non-maximum suppression)得到最终的检测结果。训练过程中,SSD采用Hard negative mining策略进行训练,使正负样本比例保持为1:3,同时使用多种数据增广(Data augmentation)方式进行训练,提高模型性能。 + + +# 文本检测模型 + +文本检测模型的目标是从图片中尽可能准确地找出文字所在区域。 + +但是,视觉领域常规物体检测方法(SSD, YOLO, Faster-RCNN等)直接套用于文字检测任务效果并不理想, 主要原因如下: + +1·相比于常规物体,文字行长度、长宽比例变化范围很大。 +2·文本行是有方向性的。常规物体边框BBox的四元组描述方式信息量不充足。 +3·自然场景中某些物体局部图像与字母形状相似,如果不参考图像全局信息将有误报。 +4·有些艺术字体使用了弯曲的文本行,而手写字体变化模式也很多。 +5·由于丰富的背景图像干扰,手工设计特征在自然场景文本识别任务中不够鲁棒。 + +针对上述问题根因,近年来出现了各种基于深度学习的技术解决方案。它们从特征提取、区域建议网络(RPN)、多目标协同训练、Loss改进、非极大值抑制(NMS)、半监督学习等角度对常规物体检测方法进行改造,极大提升了自然场景图像中文本检测的准确率。例如: + +1·CTPN方案中,用BLSTM模块提取字符所在图像上下文特征,以提高文本块识别精度。 +2·RRPN等方案中,文本框标注采用BBOX +方向角度值的形式,模型中产生出可旋转的文字区域候选框,并在边框回归计算过程中找到待测文本行的倾斜角度。 +3·DMPNet等方案中,使用四边形(非矩形)标注文本框,来更紧凑的包围文本区域。 +4·SegLink 将单词切割为更易检测的小文字块,再预测邻近连接将小文字块连成词。 +5·TextBoxes等方案中,调整了文字区域参考框的长宽比例,并将特征层卷积核调整为长方形,从而更适合检测出细长型的文本行。 +6·FTSN方案中,作者使用Mask-NMS代替传统BBOX的NMS算法来过滤候选框。 +7·WordSup方案中,采用半监督学习策略,用单词级标注数据来训练字符级文本检测模型。 + +### CTPN模型 + +CTPN是目前流传最广、影响最大的开源文本检测模型,可以检测水平或微斜的文本行。文本行可以被看成一个字符sequence,而不是一般物体检测中单个独立的目标。同一文本行上各个字符图像间可以互为上下文,在训练阶段让检测模型学习图像中蕴含的这种上下文统计规律,可以使得预测阶段有效提升文本块预测准确率。CTPN模型的图像预测流程中,前端使用当时流行的VGG16做基础网络来提取各字符的局部图像特征,中间使用BLSTM层提取字符序列上下文特征,然后通过FC全连接层,末端经过预测分支输出各个文字块的坐标值和分类结果概率值。在数据后处理阶段,将合并相邻的小文字块为文本行。 + +### RRPN模型 + +基于旋转区域候选网络(RRPN, Rotation Region Proposal Networks)的方案,将旋转因素并入经典区域候选网络(如Faster RCNN)。这种方案中,一个文本区域的ground truth被表示为具有5元组(x,y,h,w,θ)的旋转边框, 坐标(x,y)表示边框的几何中心, 高度h设定为边框的短边,宽度w为长边,方向是长边的方向。训练时,首先生成含有文本方向角的倾斜候选框,然后在边框回归过程中学习文本方向角。 + +RRPN中方案中提出了旋转感兴趣区域(RRoI,Rotation Region-of-Interest)池化层,将任意方向的区域建议先划分成子区域,然后对这些子区域分别做max pooling、并将结果投影到具有固定空间尺寸小特征图上。 + +### FTSN模型 +FTSN(Fused Text Segmentation Networks)模型使用分割网络支持倾斜文本检测。它使用Resnet-101做基础网络,使用了多尺度融合的特征图。标注数据包括文本实例的像素掩码和边框,使用像素预测与边框检测多目标联合训练。 + +基于文本实例间像素级重合度的Mask-NMS, 替代了传统基于水平边框间重合度的NMS算法。下图左边子图是传统NMS算法执行结果,中间白色边框被错误地抑制掉了。下图右边子图是Mask-NMS算法执行结果, 三个边框都被成功保留下来。 + +### DMPNet模型 + +DMPNet(Deep Matching Prior Network)中,使用四边形(非矩形)来更紧凑地标注文本区域边界,其训练出的模型对倾斜文本块检测效果更好。 + +如下图所示,它使用滑动窗口在特征图上获取文本区域候选框,候选框既有正方形的、也有倾斜四边形的。接着,使用基于像素点采样的Monte-Carlo方法,来快速计算四边形候选框与标注框间的面积重合度。然后,计算四个顶点坐标到四边形中心点的距离,将它们与标注值相比计算出目标loss。文章中推荐用Ln loss来取代L1、L2 loss,从而对大小文本框都有较快的训练回归(regress)速度。 + +### EAST模型 + +EAST(Efficient and Accuracy Scene Text detection pipeline)模型中,首先使用全卷积网络(FCN)生成多尺度融合的特征图,然后在此基础上直接进行像素级的文本块预测。该模型中,支持旋转矩形框、任意四边形两种文本区域标注形式。对应于四边形标注,模型执行时会对特征图中每个像素预测其到四个顶点的坐标差值。对应于旋转矩形框标注,模型执行时会对特征图中每个像素预测其到矩形框四边的距离、以及矩形框的方向角。 + +根据开源工程中预训练模型的测试,该模型检测英文单词效果较好、检测中文长文本行效果欠佳。或许,根据中文数据特点进行针对性训练后,检测效果还有提升空间。 + +上述过程中,省略了其他模型中常见的区域建议、单词分割、子块合并等步骤,因此该模型的执行速度很快。 + +### SegLink模型 + +SegLink模型的标注数据中,先将每个单词切割为更易检测的有方向的小文字块(segment),然后用邻近连接(link )将各个小文字块连接成单词。这种方案方便于识别长度变化范围很大的、带方向的单词和文本行,它不会象Faster-RCNN等方案因为候选框长宽比例原因检测不出长文本行。相比于CTPN等文本检测模型,SegLink的图片处理速度快很多。 + +如下图所示,该模型能够同时从6种尺度的特征图中检测小文字块。同一层特征图、或者相邻层特征图上的小文字块都有可能被连接入同一个单词中。换句话说,位置邻近、并且尺寸接近的文字块都有可能被预测到同一单词中。 + +### PixelLink模型 + +自然场景图像中一组文字块经常紧挨在一起,通过语义分割方法很难将它们识别开来,所以PixelLink模型尝试用实例分割方法解决这个问题。 + +该模型的特征提取部分,为VGG16基础上构建的FCN网络。模型执行流程如下图所示。首先,借助于CNN 模块执行两个像素级预测:一个文本二分类预测,一个链接二分类预测。接着,用正链接去连接邻居正文本像素,得到文字块实例分割结果。然后,由分割结果直接就获得文字块边框, 而且允许生成倾斜边框。 + +上述过程中,省掉了其他模型中常见的边框回归步骤,因此训练收敛速度更快些。训练阶段,使用了平衡策略,使得每个文字块在总LOSS中的权值相同。训练过程中,通过预处理增加了各种方向角度的文字块实例。 + +### Textboxes/Textboxes++模型 + +Textboxes是基于SSD框架的图文检测模型,训练方式是端到端的,运行速度也较快。如下图所示,为了适应文字行细长型的特点,候选框的长宽比增加了1,2,3,5,7,10这样初始值。为了适应文本行细长型特点,特征层也用长条形卷积核代替了其他模型中常见的正方形卷积核。为了防止漏检文本行,还在垂直方向增加了候选框数量。为了检测大小不同的字符块,在多个尺度的特征图上并行预测文本框, 然后对预测结果做NMS过滤。 + +Textboxes++是Textboxes的升级版本,目的是增加对倾斜文本的支持。为此,将标注数据改为了旋转矩形框和不规则四边形的格式;对候选框的长宽比例、特征图层卷积核的形状都作了相应调整。 + +### WordSup模型 + +如下图所示,在数学公式图文识别、不规则形变文本行识别等应用中,字符级检测模型是一个关键基础模块。由于字符级自然场景图文标注成本很高、相关公开数据集稀少,导致现在多数图文检测模型只能在文本行、单词级标注数据上做训练。WordSup提出了一种弱监督的训练框架, 可以文本行、单词级标注数据集上训练出字符级检测模型。 + +WordSup弱监督训练框架中,两个训练步骤被交替执行:给定当前字符检测模型,并结合单词级标注数据,计算出字符中心点掩码图; 给定字符中心点掩码图,有监督地训练字符级检测模型. + +训练好字符检测器后,可以在数据流水线中加入合适的文本结构分析模块,以输出符合应用场景格式要求的文本内容。该文作者例举了多种文本结构分析模块的实现方法。 + +# 文本识别模型 + +文本识别模型的目标是从已分割出的文字区域中识别出文本内容。 + + +## CRNN模型 + +现今基于深度学习的端到端OCR技术有两大主流技术:CRNN OCR和attention OCR。其实这两大方法主要区别在于最后的输出层(翻译层),即怎么将网络学习到的序列特征信息转化为最终的识别结果。这两大主流技术在其特征学习阶段都采用了CNN+RNN的网络结构,CRNN OCR在对齐时采取的方式是CTC算法(应用更为广泛),而attention OCR采取的方式则是attention机制。 + +[【OCR技术系列之七】端到端不定长文字识别CRNN算法详解](https://www.cnblogs.com/skyfsm/p/10335717.html) + +[代码 pytorch + wrap_ctc ](https://github.com/Ewenwan/crnn) + +[百度warp-ctc CPU和GPU上高效并行的CTC代码库 (library)](https://github.com/Ewenwan/warp-ctc) + +[caffe crnn](https://github.com/Ewenwan/crnn.caffe) + +[use STN+CNN+BLSTM+CTC to do OCR](https://github.com/wushilian/STN_CNN_LSTM_CTC_TensorFlow) + +CRNN(Convolutional Recurrent Neural Network)是目前较为流行的图文识别模型,可识别较长的文本序列。它包含CNN特征提取层和BLSTM序列特征提取层,能够进行端到端的联合训练。 它利用BLSTM和CTC部件学习字符图像中的上下文关系, 从而有效提升文本识别准确率,使得模型更加鲁棒。预测过程中,前端使用标准的CNN网络提取文本图像的特征,利用BLSTM将特征向量进行融合以提取字符序列的上下文特征,然后得到每列特征的概率分布,最后通过转录层(CTC rule)进行预测得到文本序列。 + +网络架构。架构包括三部分: + +1) 卷积层,使用CNN,作用是从输入图像中提取特征序列; + +2) 循环层,使用RNN,作用是预测从卷积层获取的特征序列(每一帧)的标签(真实值)分布; + +3) 转录层,使用CTC,作用是把从循环层获取(每一帧)的标签分布通过去重整合等操作转换成最终的识别结果(标签序列)。 + +![](https://img2018.cnblogs.com/blog/1093303/201901/1093303-20190129201843455-243108334.png) + +CNN提取图像像素特征,RNN提取图像时序特征,而CTC归纳字符间的连接特性。 + +CTC有什么好处?因手写字符的随机性,人工可以标注字符出现的像素范围,但是太过麻烦,ctc可以告诉我们哪些像素范围对应的字符: + +在CRNN的底部,卷积层自动从每个输入图像中提取特征序列。在卷积网络之上,构建了一个循环网络,用于对卷积层输出的特征序列的每一帧进行预测。采用CRNN顶部的转录层将循环层的每帧预测转化为标签序列。虽然CRNN由不同类型的网络架构(如CNN和RNN)组成,但可以通过一个损失函数进行联合训练。 + +> 转录 + +转录是将RNN所做的每帧预测转换成标签序列的过程。数学上,转录是根据每帧预测找到具有最高概率的标签序列。在实践中,存在两种转录模式,即无词典转录和基于词典的转录。词典是一组标签序列,预测受拼写检查字典约束。在无词典模式中,预测时没有任何词典。在基于词典的模式中,通过选择具有最高概率的标签序列进行预测。 + +我们采用Graves等人[15]提出的联接时间分类(CTC)层中定义的条件概率。按照每帧预测y=y1,...,yT对标签序列l定义概率,并忽略l中每个标签所在的位置。因此,当我们使用这种概率的负对数似然作为训练网络的目标函数时,我们只需要图像及其相应的标签序列,避免了标注单个字符位置的劳动。 + +CRNN OCR其实是借用了语音识别中解决不定长语音序列的思路。与语音识别问题类似,OCR可建模为时序依赖的词汇或者短语识别问题。基于联结时序分类(Connectionist Temporal Classification, CTC)训练RNN的算法,在语音识别领域显著超过传统语音识别算法。一些学者尝试把CTC损失函数借鉴到OCR识别中,CRNN 就是其中代表性算法。CRNN算法输入100*32归一化高度的词条图像,基于7层CNN(普遍使用VGG16)提取特征图,把特征图按列切分(Map-to-Sequence),每一列的512维特征,输入到两层各256单元的双向LSTM进行分类。在训练过程中,通过CTC损失函数的指导,实现字符位置与类标的近似软对齐。 + +CRNN借鉴了语音识别中的LSTM+CTC的建模方法,不同点是输入进LSTM的特征,从语音领域的声学特征(MFCC等),替换为CNN网络提取的图像特征向量。CRNN算法最大的贡献,是把CNN做图像特征工程的潜力与LSTM做序列化识别的潜力,进行结合。它既提取了鲁棒特征,又通过序列识别避免了传统算法中难度极高的单字符切分与单字符识别,同时序列化识别也嵌入时序依赖(隐含利用语料)。在训练阶段,CRNN将训练图像统一缩放100×32(w × h);在测试阶段,针对字符拉伸导致识别率降低的问题,CRNN保持输入图像尺寸比例,但是图像高度还是必须统一为32个像素,卷积特征图的尺寸动态决定LSTM时序长度。 + +1.input: 输入文字块,归一化到32*w 即height缩放到32,宽度按高度的比率缩放,也可以缩放到自己想要的宽度,训练时为批次训练,缩放到[32,Wmax]),示例为(32,128) + +2.经过两个conv层和两个poling层,conv3层时数据大小为256*8*32,两个pooling层步长为2. + +3.pooling2层步长为(2,1),(个人看法:作者使用的英文训练,英文字符的特征是高大于宽的特征,倘若使用中文训练,建议使用(2,2),我的代码中默认为(2,2),示例以(2,1)为例,所以此时输出为256*4*33 + +4.bn层不改变输出的大小(就是做个归一化,加速训练收敛),p3层时,w+1,所以pooling3层时,输出为512*2*34 + +5.conv7层时,kernel 为22,stride(1,1) padding(0,0) + + Wnew = (2 + 2 padW - kernel ) / strideW + 1 = 1 + Hnew = 33 + 所以conv7层输出为512133 + +6. 后面跟两个双向Lstm,隐藏节点都是256 + + Blstm1输出33*1256 + Blstm2输出 33*1*5530 5530 = 字符个数 + 非字符 = 5529 + 1 + +最终的输出结果直观上可以想象成将128分为33份,每一份对应5530个类别的概率 + +现在输入有个图像,为了将特征输入到Recurrent Layers,做如下处理: + +1.首先会将图像缩放到 32×W×1 大小 +2.然后经过CNN后变为 1×(W/4)× 512 +3.接着针对LSTM,设置 T=(W/4) , D=512 ,即可将特征输入LSTM。 +4.LSTM有256个隐藏节点,经过LSTM后变为长度为T × nclass的向量,再经过softmax处理,列向量每个元素代表对应的字符预测概率,最后再将这个T的预测结果去冗余合并成一个完整识别结果即可。 + +> cTc + +我们知道,CRNN中RNN层输出的一个不定长的序列,比如原始图像宽度为W,可能其经过CNN和RNN后输出的序列个数为S,此时我们要将该序列翻译成最终的识别结果。RNN进行时序分类时,不可避免地会出现很多冗余信息,比如一个字母被连续识别两次,这就需要一套去冗余机制,但是简单地看到两个连续字母就去冗余的方法也有问题,比如cook,geek一类的词,所以CTC有一个blank机制来解决这个问题。 + +![](https://img2018.cnblogs.com/blog/1093303/201901/1093303-20190129201921725-1294260731.png) + +如上图所示,我们要识别这个手写体图像,标签为“ab”,经过CNN+RNN学习后输出序列向量长度为5,即t0~t4,此时我们要将该序列翻译为最后的识别结果。我们在翻译时遇到的第一个难题就是,5个序列怎么转化为对应的两个字母?重复的序列怎么解决?刚好位于字与字之间的空白的序列怎么映射?这些都是CTC需要解决的问题。 + +我们从肉眼可以看到,t0,t1,t2时刻都应映射为“a”,t3,t4时刻都应映射为“b”。如果我们将连续重复的字符合并成一个输出的话,即“aaabb”将被合并成“ab”输出。但是这样子的合并机制是有问题的,比如我们的标签图像时“aab”时,我们的序列输出将可能会是“aaaaaaabb”,这样子我们就没办法确定该文本应被识别为“aab”还是“ab”。CTC为了解决这种二义性,提出了插入blank机制,比如我们以“-”符号代表blank,则若标签为“aaa-aaaabb”则将被映射为“aab”,而“aaaaaaabb”将被映射为“ab”。引入blank机制,我们就可以很好地处理了重复字符的问题了。 + +但我们还注意到,“aaa-aaaabb”可以映射为“aab”,同样地,“aa-aaaaabb”也可以映射为“aab”,也就是说,存在多个不同的字符组合可以映射为“aab”,更总结地说,一个标签存在一条或多条的路径。比如下面“state”这个例子,也存在多条不同路径映射为"state": + +![](https://img2018.cnblogs.com/blog/1093303/201901/1093303-20190129201933672-77661160.png) + +上面提到,RNN层输出的是序列中概率矩阵,那么 + +p(π=−−stta−t−−−e|x,S)=∏T(yt_πt)=(y1−)×(y2−)×(y3s)×(y4t)×(y5t)×(y6a)×(y7−)×(y8t)×(y9−)×(y10−)×(y11−)×(y12e) + +其中,y1−y−1表示第一个序列输出“-”的概率,那么对于输出某条路径ππ的概率为各个序列概率的乘积。所以要得到一个标签可以有多个路径来获得,从直观上理解就是,我们输出一张文本图像到网络中,我们需要使得输出为标签L的概率最大化,由于路径之间是互斥的,对于标注序列,其条件概率为所有映射到它的路径概率之和: + +![](https://img2018.cnblogs.com/blog/1093303/201901/1093303-20190129201945171-1526153135.png) + +其中π∈B−1(l)π∈B−1(l)的意思是,所有可以合并成l的所有路径集合。 + +这种通过映射B和所有候选路径概率之和的方式使得CTC不需要对原始的输入序列进行准确的切分,这使得RNN层输出的序列长度>label长度的任务翻译变得可能。CTC可以与任意的RNN模型,但是考虑到标注概率与整个输入串有关,而不是仅与前面小窗口范围的片段相关,因此双向的RNN/LSTM模型更为适合。 + +ctc会计算loss ,从而找到最可能的像素区域对应的字符。事实上,这里loss的计算本质是对概率的归纳: + +![](https://img2018.cnblogs.com/blog/1093303/201901/1093303-20190129201956696-854357259.png) + +如上图,对于最简单的时序为2的(t0t1)的字符识别,可能的字符为“a”,“b”和“-”,颜色越深代表概率越高。我们如果采取最大概率路径解码的方法,一看就是“--”的概率最大,真实字符为空即“”的概率为0.6*0.6=0.36。 + +但是我们忽略了一点,真实字符为“a”的概率不只是”aa” 即0.4*0.4 , 事实上,“aa”, “a-“和“-a”都是代表“a”,所以,输出“a”的概率为: + +0.4*0.4 + 0.4 * 0.6 + 0.6*0.4 = 0.16+0.24+0.24 = 0.64 + +所以“a”的概率比空“”的概率高!可以看出,这个例子里最大概率路径和最大概率序列完全不同,所以CTC解码通常不适合采用最大概率路径的方法,而应该采用前缀搜索算法解码或者约束解码算法。 + +通过对概率的计算,就可以对之前的神经网络进行反向传播更新。类似普通的分类,CTC的损失函数O定义为负的最大似然,为了计算方便,对似然取对数。 + +![]() + +![]() + +## RARE模型 + +RARE(Robust text recognizer with Automatic Rectification)模型在识别变形的图像文本时效果很好。如下图所示,模型预测过程中,输入图像首先要被送到一个空间变换网络中做处理,矫正过的图像然后被送入序列识别网络中得到文本预测结果。 + +空间变换网络内部包含定位网络、网格生成器、采样器三个部件。经过训练后,它可以根据输入图像的特征图动态地产生空间变换网格,然后采样器根据变换网格核函数从原始图像中采样获得一个矩形的文本图像。RARE中支持一种称为TPS(thin-plate splines)的空间变换,从而能够比较准确地识别透视变换过的文本、以及弯曲的文本. + +# 端到端模型 + +端到端模型的目标是一站式直接从图片中定位和识别出所有文本内容来。 + +## FOTS Rotation-Sensitive Regression + +FOTS(Fast Oriented Text Spotting)是图像文本检测与识别同步训练、端到端可学习的网络模型。检测和识别任务共享卷积特征层,既节省了计算时间,也比两阶段训练方式学习到更多图像特征。引入了旋转感兴趣区域(RoIRotate), 可以从卷积特征图中产生出定向的文本区域,从而支持倾斜文本的识别. + +STN-OCR模型 + +STN-OCR是集成了了图文检测和识别功能的端到端可学习模型。在它的检测部分嵌入了一个空间变换网络(STN)来对原始输入图像进行仿射(affine)变换。利用这个空间变换网络,可以对检测到的多个文本块分别执行旋转、缩放和倾斜等图形矫正动作,从而在后续文本识别阶段得到更好的识别精度。在训练上STN-OCR属于半监督学习方法,只需要提供文本内容标注,而不要求文本定位信息。作者也提到,如果从头开始训练则网络收敛速度较慢,因此建议渐进地增加训练难度。STN-OCR已经开放了工程源代码和预训练模型。 diff --git a/GNN/readme.md b/GNN/readme.md index 83028127..17d4a033 100644 --- a/GNN/readme.md +++ b/GNN/readme.md @@ -1,4 +1,6 @@ -# 图卷积网络(Graph Convolutional Network) +# 图卷积网络(Graph Convolutional Network) 因果推理 +[相关论文](https://github.com/Ewenwan/GNNPapers) + [代码](https://github.com/Ewenwan/Graph-neural-networks) [简介](https://tkipf.github.io/graph-convolutional-networks/) @@ -13,3 +15,428 @@ 图中的节点表示网络中的个体,连边表示个体之间的连接关系。 许多机器学习任务例如社团发现、链路预测等都需要用到图结构数据, 因此图卷积神经网络的出现为这些问题的解决提供了新的思路。 +[清华大学孙茂松组一文综述GNN](https://mp.weixin.qq.com/s?__biz=MzI3MTA0MTk1MA==&mid=2652034713&idx=1&sn=66be74a9435810f1e782bc0de44b3791&chksm=f121a268c6562b7e9d3905468b6995427b689fe580c3283ada699f1b928236aeb771f15eb91c&mpshare=1&scene=23&srcid=12278Oi7f7bFQuHybgt0xvBU#rd) + + + 深度学习无法进行因果推理,而图模型(GNN)或是解决方案之一。 + 图神经网络是连接主义与符号主义的有机结合, + 不仅使深度学习模型能够应用在图这种非欧几里德结构上, + 还为深度学习模型赋予了一定的因果推理能力。 + +## GNN的三大通用框架 + 1. 消息传递神经网络(message passing neural network, MPNN),统一了各种 图神经网络 和 图卷积网络方法。 + 2. 非局部神经网络(non-local neural network, NLNN),它结合了几种“self-attention”风格的方法。 + 3. 图网络(graph network, GN),它统一了统一了MPNN和NLNN方法以及许多其他变体, + 如交互网络(Interaction Networks), + 神经物理引擎(Neural Physics Engine), + CommNet,structure2vec, + GGNN, + 关系网络(Relation Network), + Deep Sets 和 + Point Net。 +## 问题 + 1. GNN总是很浅,大多数不超过三层。 + 堆叠多个GCN层将导致过度平滑,也就是说,所有顶点将收敛到相同的值。 + + 2. GNN在非结构场景中的应用。 + + 3. 对GNN进行扩展是很困难的。 + 首先,图数据并不规则,每个节点都有自己的邻域结构,因此不能批量化处理。 + 其次,当存在的节点和边数量达到数百万时,计算图的拉普拉斯算子也是不可行的。 + 此外,我们需要指出,可扩展性的高低,决定了算法是否能够应用于实际场景。 + 目前已经有一些研究提出了解决这个问题的办法,我们正在密切关注这些新进展。 + + + + +## 综述研究类论文 +1. **Graph Neural Networks: A Review of Methods and Applications.** +*Jie Zhou, Ganqu Cui, Zhengyan Zhang, Cheng Yang, Zhiyuan Liu, Maosong Sun.* 2018. [paper](https://arxiv.org/pdf/1812.08434.pdf) + +2. **Deep Learning on Graphs: A Survey.** +*Ziwei Zhang, Peng Cui, Wenwu Zhu.* 2018. [paper](https://arxiv.org/pdf/1812.04202.pdf) + +3. **Relational Inductive Biases, Deep Learning, and Graph Networks.** +*Battaglia, Peter W and Hamrick, Jessica B and Bapst, Victor and Sanchez-Gonzalez, Alvaro and Zambaldi, Vinicius and Malinowski, Mateusz and Tacchetti, Andrea and Raposo, David and Santoro, Adam and Faulkner, Ryan and others.* 2018. [paper](https://arxiv.org/pdf/1806.01261.pdf) + +4. **Geometric Deep Learning: Going beyond Euclidean data.** +*Bronstein, Michael M and Bruna, Joan and LeCun, Yann and Szlam, Arthur and Vandergheynst, Pierre.* IEEE SPM 2017. [paper](https://arxiv.org/pdf/1611.08097.pdf) + +5. **Computational Capabilities of Graph Neural Networks.** +*Scarselli, Franco and Gori, Marco and Tsoi, Ah Chung and Hagenbuchner, Markus and Monfardini, Gabriele.* IEEE TNN 2009. [paper](https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=4703190) + +6. **Neural Message Passing for Quantum Chemistry.** +*Gilmer, Justin and Schoenholz, Samuel S and Riley, Patrick F and Vinyals, Oriol and Dahl, George E.* 2017. [paper](https://arxiv.org/pdf/1704.01212.pdf) + +7. **Non-local Neural Networks.** +*Wang, Xiaolong and Girshick, Ross and Gupta, Abhinav and He, Kaiming.* CVPR 2018. [paper](http://openaccess.thecvf.com/content_cvpr_2018/papers/Wang_Non-Local_Neural_Networks_CVPR_2018_paper.pdf) + +8. **The Graph Neural Network Model.** +*Scarselli, Franco and Gori, Marco and Tsoi, Ah Chung and Hagenbuchner, Markus and Monfardini, Gabriele.* IEEE TNN 2009. [paper](https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=4700287) + + +## 模型 +1. **A new model for learning in graph domains.** +*Marco Gori, Gabriele Monfardini, Franco Scarselli.* IJCNN 2005. [paper](https://www.researchgate.net/profile/Franco_Scarselli/publication/4202380_A_new_model_for_earning_in_raph_domains/links/0c9605188cd580504f000000.pdf) + +1. **Graph Neural Networks for Ranking Web Pages.** +*Franco Scarselli, Sweah Liang Yong, Marco Gori, Markus Hagenbuchner, Ah Chung Tsoi, Marco Maggini.* WI 2005. [paper](https://www.researchgate.net/profile/Franco_Scarselli/publication/221158677_Graph_Neural_Networks_for_Ranking_Web_Pages/links/0c9605188cd5090ede000000/Graph-Neural-Networks-for-Ranking-Web-Pages.pdf) + +1. **Gated Graph Sequence Neural Networks.** +*Yujia Li, Daniel Tarlow, Marc Brockschmidt, Richard Zemel.* ICLR 2016. [paper](https://arxiv.org/pdf/1511.05493.pdf) + +1. **Geometric deep learning on graphs and manifolds using mixture model cnns.** +*Federico Monti, Davide Boscaini, Jonathan Masci, Emanuele Rodolà, Jan Svoboda, Michael M. Bronstein.* CVPR 2017. [paper](https://arxiv.org/pdf/1611.08402.pdf) + +1. **Spectral Networks and Locally Connected Networks on Graphs.** +*Joan Bruna, Wojciech Zaremba, Arthur Szlam, Yann LeCun.* ICLR 2014. [paper](https://arxiv.org/pdf/1312.6203.pdf) + +1. **Deep Convolutional Networks on Graph-Structured Data.** +*Mikael Henaff, Joan Bruna, Yann LeCun.* 2015. [paper](https://arxiv.org/pdf/1506.05163.pdf) + +1. **Convolutional Neural Networks on Graphs with Fast Localized Spectral Filtering.** +*Michaël Defferrard, Xavier Bresson, Pierre Vandergheynst.* NIPS 2016. [paper](http://papers.nips.cc/paper/6081-convolutional-neural-networks-on-graphs-with-fast-localized-spectral-filtering.pdf) + +1. **Learning Convolutional Neural Networks for Graphs.** +*Mathias Niepert, Mohamed Ahmed, Konstantin Kutzkov.* ICML 2016. [paper](http://proceedings.mlr.press/v48/niepert16.pdf) + +1. **Semi-Supervised Classification with Graph Convolutional Networks.** +*Thomas N. Kipf, Max Welling.* ICLR 2017. [paper](https://arxiv.org/pdf/1609.02907.pdf) + +1. **Graph Attention Networks.** +*Petar Velickovic, Guillem Cucurull, Arantxa Casanova, Adriana Romero, Pietro Lio, Yoshua Bengio.* ICLR 2018. [paper](https://mila.quebec/wp-content/uploads/2018/07/d1ac95b60310f43bb5a0b8024522fbe08fb2a482.pdf) + +1. **Deep Sets.** +*Manzil Zaheer, Satwik Kottur, Siamak Ravanbakhsh, Barnabas Poczos, Ruslan Salakhutdinov, Alexander Smola.* NIPS 2017. [paper](https://arxiv.org/pdf/1703.06114.pdf) + +1. **Graph Partition Neural Networks for Semi-Supervised Classification.** +*Renjie Liao, Marc Brockschmidt, Daniel Tarlow, Alexander L. Gaunt, Raquel Urtasun, Richard Zemel.* 2018. [paper](https://arxiv.org/pdf/1803.06272.pdf) + +1. **Covariant Compositional Networks For Learning Graphs.** +*Risi Kondor, Hy Truong Son, Horace Pan, Brandon Anderson, Shubhendu Trivedi.* 2018. [paper](https://arxiv.org/pdf/1801.02144.pdf) + +1. **Modeling Relational Data with Graph Convolutional Networks.** +*Michael Schlichtkrull, Thomas N. Kipf, Peter Bloem, Rianne van den Berg, Ivan Titov, Max Welling.* ESWC 2018. [paper](https://arxiv.org/pdf/1703.06103.pdf) + +1. **Stochastic Training of Graph Convolutional Networks with Variance Reduction.** +*Jianfei Chen, Jun Zhu, Le Song.* ICML 2018. [paper](http://www.scipaper.net/uploadfile/2018/0716/20180716100330880.pdf) + +1. **Learning Steady-States of Iterative Algorithms over Graphs.** +*Hanjun Dai, Zornitsa Kozareva, Bo Dai, Alex Smola, Le Song.* ICML 2018. [paper](http://proceedings.mlr.press/v80/dai18a/dai18a.pdf) + +1. **Deriving Neural Architectures from Sequence and Graph Kernels.** +*Tao Lei, Wengong Jin, Regina Barzilay, Tommi Jaakkola.* ICML 2017. [paper](https://arxiv.org/pdf/1705.09037.pdf) + +1. **Adaptive Graph Convolutional Neural Networks.** +*Ruoyu Li, Sheng Wang, Feiyun Zhu, Junzhou Huang.* AAAI 2018. [paper](https://arxiv.org/pdf/1801.03226.pdf) + +1. **Graph-to-Sequence Learning using Gated Graph Neural Networks.** +*Daniel Beck, Gholamreza Haffari, Trevor Cohn.* ACL 2018. [paper](https://arxiv.org/pdf/1806.09835.pdf) + +1. **Deeper Insights into Graph Convolutional Networks for Semi-Supervised Learning.** +*Qimai Li, Zhichao Han, Xiao-Ming Wu.* AAAI 2018. [paper](https://arxiv.org/pdf/1801.07606.pdf) + +1. **Graphical-Based Learning Environments for Pattern Recognition.** +*Franco Scarselli, Ah Chung Tsoi, Marco Gori, Markus Hagenbuchner.* SSPR/SPR 2004. [paper](https://link.springer.com/content/pdf/10.1007%2F978-3-540-27868-9_4.pdf) + +1. **A Comparison between Recursive Neural Networks and Graph Neural Networks.** +*Vincenzo Di Massa, Gabriele Monfardini, Lorenzo Sarti, Franco Scarselli, Marco Maggini, Marco Gori.* IJCNN 2006. [paper](https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=1716174) + +1. **Graph Neural Networks for Object Localization.** +*Gabriele Monfardini, Vincenzo Di Massa, Franco Scarselli, Marco Gori.* ECAI 2006. [paper](http://ebooks.iospress.nl/volumearticle/2775) + +1. **Knowledge-Guided Recurrent Neural Network Learning for Task-Oriented Action Prediction.** +*Liang Lin, Lili Huang, Tianshui Chen, Yukang Gan, Hui Cheng.* ICME 2017. [paper](https://arxiv.org/pdf/1707.04677.pdf) + +1. **Semantic Object Parsing with Graph LSTM.** +*Xiaodan LiangXiaohui ShenJiashi FengLiang Lin, Shuicheng Yan.* ECCV 2016. [paper](https://link.springer.com/content/pdf/10.1007%2F978-3-319-46448-0_8.pdf) + +1. **CelebrityNet: A Social Network Constructed from Large-Scale Online Celebrity Images.** +*Li-Jia Li, David A. Shamma, Xiangnan Kong, Sina Jafarpour, Roelof Van Zwol, Xuanhui Wang.* TOMM 2015. [paper](https://dl.acm.org/ft_gateway.cfm?id=2801125&ftid=1615097&dwn=1&CFID=38275959&CFTOKEN=6938a464cf972252-DF065FDC-9FED-EB68-3528017EA04F0D29) + +1. **Inductive Representation Learning on Large Graphs.** +*William L. Hamilton, Rex Ying, Jure Leskovec.* NIPS 2017. [paper](https://arxiv.org/pdf/1706.02216.pdf) + +1. **Graph Classification using Structural Attention.** +*John Boaz Lee, Ryan Rossi, Xiangnan Kong.* KDD 18. [paper](https://dl.acm.org/ft_gateway.cfm?id=3219980&ftid=1988883&dwn=1&CFID=38275959&CFTOKEN=6938a464cf972252-DF065FDC-9FED-EB68-3528017EA04F0D29) + +1. **Adversarial Attacks on Neural Networks for Graph Data.** +*Daniel Zügner, Amir Akbarnejad, Stephan Günnemann.* KDD 18. [paper](http://delivery.acm.org/10.1145/3230000/3220078/p2847-zugner.pdf?ip=101.5.139.169&id=3220078&acc=ACTIVE%20SERVICE&key=BF85BBA5741FDC6E%2E587F3204F5B62A59%2E4D4702B0C3E38B35%2E4D4702B0C3E38B35&__acm__=1545706391_e7484be677293ffb5f18b39ce84a0df9) + +1. **Large-Scale Learnable Graph Convolutional Networks.** +*Hongyang Gao, Zhengyang Wang, Shuiwang Ji.* KDD 18. [paper](http://delivery.acm.org/10.1145/3220000/3219947/p1416-gao.pdf?ip=101.5.139.169&id=3219947&acc=ACTIVE%20SERVICE&key=BF85BBA5741FDC6E%2E587F3204F5B62A59%2E4D4702B0C3E38B35%2E4D4702B0C3E38B35&__acm__=1545706457_bb20316c7ce038aefb97afcf4ef9668b) + +1. **Contextual Graph Markov Model: A Deep and Generative Approach to Graph Processing.** +*Davide Bacciu, Federico Errica, Alessio Micheli.* ICML 2018. [paper](https://arxiv.org/pdf/1805.10636.pdf) + +1. **Diffusion-Convolutional Neural Networks.** +*James Atwood, Don Towsley.* NIPS 2016. [paper](https://arxiv.org/pdf/1511.02136.pdf) + +1. **Neural networks for relational learning: an experimental comparison.** +*Werner Uwents, Gabriele Monfardini, Hendrik Blockeel, Marco Gori, Franco Scarselli.* Machine Learning 2011. [paper](https://link.springer.com/content/pdf/10.1007%2Fs10994-010-5196-5.pdf) + +1. **FastGCN: Fast Learning with Graph Convolutional Networks via Importance Sampling.** +*Jie Chen, Tengfei Ma, Cao Xiao.* ICLR 2018. [paper](https://arxiv.org/pdf/1801.10247.pdf) + +1. **Adaptive Sampling Towards Fast Graph Representation Learning.** +*Wenbing Huang, Tong Zhang, Yu Rong, Junzhou Huang.* NIPS 2018. [paper](https://arxiv.org/pdf/1809.05343.pdf) + +## 应用 + +1. **Discovering objects and their relations from entangled scene representations.** +*David Raposo, Adam Santoro, David Barrett, Razvan Pascanu, Timothy Lillicrap, Peter Battaglia.* ICLR Workshop 2017. [paper](https://arxiv.org/pdf/1702.05068.pdf) + +1. **A simple neural network module for relational reasoning.** +*Adam Santoro, David Raposo, David G.T. Barrett, Mateusz Malinowski, Razvan Pascanu, Peter Battaglia, Timothy Lillicrap.* NIPS 2017. [paper](https://arxiv.org/pdf/1706.01427.pdf) + +1. **Attend, Infer, Repeat: Fast Scene Understanding with Generative Models.** +*S. M. Ali Eslami, Nicolas Heess, Theophane Weber, Yuval Tassa, David Szepesvari, Koray Kavukcuoglu, Geoffrey E. Hinton.* NIPS 2016. [paper](https://arxiv.org/pdf/1603.08575.pdf) + +1. **Beyond Categories: The Visual Memex Model for Reasoning About Object Relationships.** +*Tomasz Malisiewicz, Alyosha Efros.* NIPS 2009. [paper](http://papers.nips.cc/paper/3647-beyond-categories-the-visual-memex-model-for-reasoning-about-object-relationships.pdf) + +1. **Understanding Kin Relationships in a Photo.** +*Siyu Xia, Ming Shao, Jiebo Luo, Yun Fu.* TMM 2012. [paper](https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=6151163) + +1. **Graph-Structured Representations for Visual Question Answering.** +*Damien Teney, Lingqiao Liu, Anton van den Hengel.* CVPR 2017. [paper](https://arxiv.org/pdf/1609.05600.pdf) + +1. **Spatial Temporal Graph Convolutional Networks for Skeleton-Based Action Recognition.** +*Sijie Yan, Yuanjun Xiong, Dahua Lin.* AAAI 2018. [paper](https://arxiv.org/pdf/1801.07455.pdf) + +1. **Few-Shot Learning with Graph Neural Networks.** +*Victor Garcia, Joan Bruna.* ICLR 2018. [paper](https://arxiv.org/pdf/1711.04043.pdf) + +1. **The More You Know: Using Knowledge Graphs for Image Classification.** +*Kenneth Marino, Ruslan Salakhutdinov, Abhinav Gupta.* CVPR 2017. [paper](https://arxiv.org/pdf/1612.04844.pdf) + +1. **Zero-shot Recognition via Semantic Embeddings and Knowledge Graphs.** +*Xiaolong Wang, Yufei Ye, Abhinav Gupta.* CVPR 2018. [paper](https://arxiv.org/pdf/1803.08035.pdf) + +1. **Rethinking Knowledge Graph Propagation for Zero-Shot Learning.** +*Michael Kampffmeyer, Yinbo Chen, Xiaodan Liang, Hao Wang, Yujia Zhang, Eric P. Xing.* 2018. [paper](https://arxiv.org/pdf/1805.11724.pdf) + +1. **Interaction Networks for Learning about Objects, Relations and Physics.** +*Peter Battaglia, Razvan Pascanu, Matthew Lai, Danilo Rezende, Koray Kavukcuoglu.* NIPS 2016. [paper](https://arxiv.org/pdf/1612.00222.pdf) + +1. **A Compositional Object-Based Approach to Learning Physical Dynamics.** +*Michael B. Chang, Tomer Ullman, Antonio Torralba, Joshua B. Tenenbaum.* ICLR 2017. [paper](https://arxiv.org/pdf/1612.00341.pdf) + +1. **Visual Interaction Networks: Learning a Physics Simulator from Vide.o** +*Nicholas Watters, Andrea Tacchetti, Théophane Weber, Razvan Pascanu, Peter Battaglia, Daniel Zoran.* NIPS 2017. [paper](http://papers.nips.cc/paper/7040-visual-interaction-networks-learning-a-physics-simulator-from-video.pdf) + +1. **Relational neural expectation maximization: Unsupervised discovery of objects and their interactions.** +*Sjoerd van Steenkiste, Michael Chang, Klaus Greff, Jürgen Schmidhuber.* ICLR 2018. [paper](https://arxiv.org/pdf/1802.10353.pdf) + +1. **Graph networks as learnable physics engines for inference and control.** +*Alvaro Sanchez-Gonzalez, Nicolas Heess, Jost Tobias Springenberg, Josh Merel, Martin Riedmiller, Raia Hadsell, Peter Battaglia.* ICML 2018. [paper](https://arxiv.org/pdf/1806.01242.pdf) + +1. **Learning Multiagent Communication with Backpropagation.** +*Sainbayar Sukhbaatar, Arthur Szlam, Rob Fergus.* NIPS 2016. [paper](https://arxiv.org/pdf/1605.07736.pdf) + +1. **VAIN: Attentional Multi-agent Predictive Modeling.** +*Yedid Hoshen.* NIPS 2017 [paper](https://arxiv.org/pdf/1706.06122.pdf) + +1. **Neural Relational Inference for Interacting Systems.** +*Thomas Kipf, Ethan Fetaya, Kuan-Chieh Wang, Max Welling, Richard Zemel.* ICML 2018. [paper](https://arxiv.org/pdf/1802.04687.pdf) + +1. **Translating Embeddings for Modeling Multi-relational Data.** +*Antoine Bordes, Nicolas Usunier, Alberto Garcia-Duran, Jason Weston, Oksana Yakhnenko.* NIPS 2013. [paper](http://papers.nips.cc/paper/5071-translating-embeddings-for-modeling-multi-relational-data.pdf) + +1. **Representation learning for visual-relational knowledge graphs.** +*Daniel Oñoro-Rubio, Mathias Niepert, Alberto García-Durán, Roberto González, Roberto J. López-Sastre.* 2017. [paper](https://arxiv.org/pdf/1709.02314.pdf) + +1. **Knowledge Transfer for Out-of-Knowledge-Base Entities : A Graph Neural Network Approach.** +*Takuo Hamaguchi, Hidekazu Oiwa, Masashi Shimbo, Yuji Matsumoto.* IJCAI 2017. [paper](https://arxiv.org/pdf/1706.05674.pdf) + +1. **Representation Learning on Graphs with Jumping Knowledge Networks.** +*Keyulu Xu, Chengtao Li, Yonglong Tian, Tomohiro Sonobe, Ken-ichi Kawarabayashi, Stefanie Jegelka.* ICML 2018. [paper](https://arxiv.org/pdf/1806.03536.pdf) + +1. **Multi-Label Zero-Shot Learning with Structured Knowledge Graphs.** +*Chung-Wei Lee, Wei Fang, Chih-Kuan Yeh, Yu-Chiang Frank Wang.* CVPR 2018. [paper](https://arxiv.org/pdf/1711.06526.pdf) + +1. **Dynamic Graph Generation Network: Generating Relational Knowledge from Diagrams.** +*Daesik Kim, Youngjoon Yoo, Jeesoo Kim, Sangkuk Lee, Nojun Kwak.* CVPR 2018. [paper](http://openaccess.thecvf.com/content_cvpr_2018/papers/Kim_Dynamic_Graph_Generation_CVPR_2018_paper.pdf) + +1. **Deep Reasoning with Knowledge Graph for Social Relationship Understanding.** +*Zhouxia Wang, Tianshui Chen, Jimmy Ren, Weihao Yu, Hui Cheng, Liang Lin.* IJCAI 2018. [paper](https://arxiv.org/pdf/1807.00504.pdf) + +1. **Constructing Narrative Event Evolutionary Graph for Script Event Prediction.** +*Zhongyang Li, Xiao Ding, Ting Liu.* IJCAI 2018. [paper](https://arxiv.org/pdf/1805.05081.pdf) + +1. **Modeling Semantics with Gated Graph Neural Networks for Knowledge Base Question Answering.** +*Daniil Sorokin, Iryna Gurevych.* COLING 2018. [paper](https://arxiv.org/pdf/1808.04126.pdf) + +1. **Convolutional networks on graphs for learning molecular fingerprints.** +*David Duvenaud, Dougal Maclaurin, Jorge Aguilera-Iparraguirre, Rafael Gómez-Bombarelli, Timothy Hirzel, Alán Aspuru-Guzik, Ryan P. Adams.* NIPS 2015. [paper](https://arxiv.org/pdf/1509.09292.pdf) + +1. **Molecular Graph Convolutions: Moving Beyond Fingerprints.** +*Steven Kearnes, Kevin McCloskey, Marc Berndl, Vijay Pande, Patrick Riley.* Journal of computer-aided molecular design 2016. [paper](https://arxiv.org/pdf/1603.00856.pdf) + +1. **Protein Interface Prediction using Graph Convolutional Networks.** +*Alex Fout, Jonathon Byrd, Basir Shariat, Asa Ben-Hur.* NIPS 2017. [paper](http://papers.nips.cc/paper/7231-protein-interface-prediction-using-graph-convolutional-networks.pdf) + +1. **Traffic Graph Convolutional Recurrent Neural Network: A Deep Learning Framework for Network-Scale Traffic Learning and Forecasting.** +*Zhiyong Cui, Kristian Henrickson, Ruimin Ke, Yinhai Wang.* 2018. [paper](https://arxiv.org/pdf/1802.07007.pdf) + +1. **Spatio-Temporal Graph Convolutional Networks: A Deep Learning Framework for Traffic Forecasting.** +*Bing Yu, Haoteng Yin, Zhanxing Zhu.* IJCAI 2018. [paper](https://arxiv.org/pdf/1709.04875.pdf) + +1. **Semi-supervised User Geolocation via Graph Convolutional Networks.** +*Afshin Rahimi, Trevor Cohn, Timothy Baldwin.* ACL 2018. [paper](https://arxiv.org/pdf/1804.08049.pdf) + +1. **Dynamic Graph CNN for Learning on Point Clouds.** +*Yue Wang, Yongbin Sun, Ziwei Liu, Sanjay E. Sarma, Michael M. Bronstein, Justin M. Solomon.* CVPR 2018. [paper](https://arxiv.org/pdf/1801.07829.pdf) + +1. **PointNet: Deep Learning on Point Sets for 3D Classification and Segmentation.** +*Charles R. Qi, Hao Su, Kaichun Mo, Leonidas J. Guibas.* CVPR 2018. [paper](https://arxiv.org/pdf/1612.00593.pdf) + +1. **3D Graph Neural Networks for RGBD Semantic Segmentation.** +*Xiaojuan Qi, Renjie Liao, Jiaya Jia, Sanja Fidler, Raquel Urtasun.* CVPR 2017. [paper](http://openaccess.thecvf.com/content_ICCV_2017/papers/Qi_3D_Graph_Neural_ICCV_2017_paper.pdf) + +1. **Iterative Visual Reasoning Beyond Convolutions.** +*Xinlei Chen, Li-Jia Li, Li Fei-Fei, Abhinav Gupta.* CVPR 2018. [paper](https://arxiv.org/pdf/1803.11189) + +1. **Dynamic Edge-Conditioned Filters in Convolutional Neural Networks on Graphs.** +*Martin Simonovsky, Nikos Komodakis.* CVPR 2017. [paper](https://arxiv.org/pdf/1704.02901) + +1. **Situation Recognition with Graph Neural Networks.** +*Ruiyu Li, Makarand Tapaswi, Renjie Liao, Jiaya Jia, Raquel Urtasun, Sanja Fidler.* ICCV 2017. [paper](https://arxiv.org/pdf/1708.04320) + +1. **Conversation Modeling on Reddit using a Graph-Structured LSTM.** +*Vicky Zayats, Mari Ostendorf.* TACL 2018. [paper](https://arxiv.org/pdf/1704.02080) + +1. **Graph Convolutional Networks for Text Classification.** +*Liang Yao, Chengsheng Mao, Yuan Luo.* AAAI 2019. [paper](https://arxiv.org/pdf/1809.05679.pdf) + +1. **Attention Is All You Need.** +*Ashish Vaswani, Noam Shazeer, Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N. Gomez, Lukasz Kaiser, Illia Polosukhin.* NIPS 2017. [paper](https://arxiv.org/pdf/1706.03762) + +1. **Self-Attention with Relative Position Representations.** +*Peter Shaw, Jakob Uszkoreit, Ashish Vaswani.* NAACL 2018. [paper](https://arxiv.org/pdf/1803.02155) + +1. **Hyperbolic Attention Networks.** +*Caglar Gulcehre, Misha Denil, Mateusz Malinowski, Ali Razavi, Razvan Pascanu, Karl Moritz Hermann, Peter Battaglia, Victor Bapst, David Raposo, Adam Santoro, Nando de Freitas* 2018. [paper](https://arxiv.org/pdf/1805.09786) + +1. **Effective Approaches to Attention-based Neural Machine Translation.** +*Minh-Thang Luong, Hieu Pham, Christopher D. Manning.* EMNLP 2015. [paper](https://arxiv.org/pdf/1508.04025) + +1. **Graph Convolutional Encoders for Syntax-aware Neural Machine Translation.** +*Joost Bastings, Ivan Titov, Wilker Aziz, Diego Marcheggiani, Khalil Sima'an.* EMNLP 2017. [paper](https://arxiv.org/pdf/1704.04675) + +1. **NerveNet: Learning Structured Policy with Graph Neural Networks.** +*Tingwu Wang, Renjie Liao, Jimmy Ba, Sanja Fidler.* ICLR 2018. [paper](https://openreview.net/pdf?id=S1sqHMZCb) + +1. **Metacontrol for Adaptive Imagination-Based Optimization.** +*Jessica B. Hamrick, Andrew J. Ballard, Razvan Pascanu, Oriol Vinyals, Nicolas Heess, Peter W. Battaglia.* ICLR 2017. [paper](https://arxiv.org/pdf/1705.02670) + +1. **Learning model-based planning from scratch.** +*Razvan Pascanu, Yujia Li, Oriol Vinyals, Nicolas Heess, Lars Buesing, Sebastien Racanière, David Reichert, Théophane Weber, Daan Wierstra, Peter Battaglia.* 2017. [paper](https://arxiv.org/pdf/1707.06170) + +1. **Structured Dialogue Policy with Graph Neural Networks.** +*Lu Chen, Bowen Tan, Sishan Long and Kai Yu.* ICCL 2018. [paper](http://www.aclweb.org/anthology/C18-1107) + +1. **Relational inductive bias for physical construction in humans and machines.** +*Jessica B. Hamrick, Kelsey R. Allen, Victor Bapst, Tina Zhu, Kevin R. McKee, Joshua B. Tenenbaum, Peter W. Battaglia.* CogSci 2018. [paper](https://arxiv.org/abs/1806.01203) + +1. **Relational Deep Reinforcement Learning.** +*Vinicius Zambaldi, David Raposo, Adam Santoro, Victor Bapst, Yujia Li, Igor Babuschkin, Karl Tuyls, David Reichert, Timothy Lillicrap, Edward Lockhart, Murray Shanahan, Victoria Langston, Razvan Pascanu, Matthew Botvinick, Oriol Vinyals, Peter Battaglia.* 2018. [paper](https://arxiv.org/abs/1806.01830) + +1. **Action Schema Networks: Generalised Policies with Deep Learning.** +*Sam Toyer, Felipe Trevizan, Sylvie Thiébaux, Lexing Xie.* AAAI 2018. [paper](https://arxiv.org/abs/1709.04271) + +1. **Neural Combinatorial Optimization with Reinforcement Learning.** +*Irwan Bello, Hieu Pham, Quoc V. Le, Mohammad Norouzi, Samy Bengio.* 2016. [paper](https://arxiv.org/abs/1611.09940) + +1. **A Note on Learning Algorithms for Quadratic Assignment with Graph Neural Networks.** +*Alex Nowak, Soledad Villar, Afonso S. Bandeira, Joan Bruna.* PADL 2017. [paper](https://www.padl.ws/papers/Paper%2017.pdf) + +1. **Learning Combinatorial Optimization Algorithms over Graphs.** +*Hanjun Dai, Elias B. Khalil, Yuyu Zhang, Bistra Dilkina, Le Song.* NIPS 2017. [paper](https://arxiv.org/abs/1704.01665) + +1. **Attention Solves Your TSP, Approximately.** +*Wouter Kool, Herke van Hoof, Max Welling.* 2018. [paper](https://arxiv.org/abs/1803.08475) + +1. **Learning a SAT Solver from Single-Bit Supervision.** +*Daniel Selsam, Matthew Lamm, Benedikt Bünz, Percy Liang, Leonardo de Moura, David L. Dill.* 2018. [paper](https://arxiv.org/abs/1802.03685) + +1. **Learning to Represent Programs with Graphs.** +*Miltiadis Allamanis, Marc Brockschmidt, Mahmoud Khademi.* ICLR 2018. [paper](https://arxiv.org/abs/1711.00740) + +1. **Learning Graphical State Transitions.** +*Daniel D. Johnson.* ICLR 2017. [paper](https://openreview.net/forum?id=HJ0NvFzxl) + +1. **Inference in Probabilistic Graphical Models by Graph Neural Networks.** +*KiJung Yoon, Renjie Liao, Yuwen Xiong, Lisa Zhang, Ethan Fetaya, Raquel Urtasun, Richard Zemel, Xaq Pitkow.* ICLR Workshop 2018. [paper](https://arxiv.org/abs/1803.07710) + +1. **Learning deep generative models of graphs.** +*Yujia Li, Oriol Vinyals, Chris Dyer, Razvan Pascanu, Peter Battaglia.* ICLR Workshop 2018. [paper](https://arxiv.org/abs/1803.03324) + +1. **MolGAN: An implicit generative model for small molecular graphs.** +*Nicola De Cao, Thomas Kipf.* 2018. [paper](https://arxiv.org/abs/1805.11973) + +1. **GraphRNN: Generating Realistic Graphs with Deep Auto-regressive Models.** +*Jiaxuan You, Rex Ying, Xiang Ren, William L. Hamilton, Jure Leskovec.* ICML 2018. [paper](https://arxiv.org/abs/1802.08773) + +1. **NetGAN: Generating Graphs via Random Walks.** +*Aleksandar Bojchevski, Oleksandr Shchur, Daniel Zügner, Stephan Günnemann.* ICML 2018. [paper](https://arxiv.org/abs/1803.00816) + +1. **Adversarial Attack on Graph Structured Data.** +*Hanjun Dai, Hui Li, Tian Tian, Xin Huang, Lin Wang, Jun Zhu, Le Song.* ICML 2018. [paper](https://arxiv.org/abs/1806.02371) + +1. **Graph Convolutional Neural Networks for Web-Scale Recommender Systems.** +*Rex Ying, Ruining He, Kaifeng Chen, Pong Eksombatchai, William L. Hamilton, Jure Leskovec.* KDD 2018. [paper](https://arxiv.org/abs/1806.01973) + +1. **Improved Semantic Representations From Tree-Structured Long Short-Term Memory Networks.** +*Kai Sheng Tai, Richard Socher, Christopher D. Manning.* ACL 2015. [paper](https://www.aclweb.org/anthology/P15-1150) + +1. **Neural Module Networks.** +*Jacob Andreas, Marcus Rohrbach, Trevor Darrell, Dan Klein.* CVPR 2016. [paper](https://arxiv.org/pdf/1511.02799.pdf) + +1. **Encoding Sentences with Graph Convolutional Networks for Semantic Role Labeling.** +*Diego Marcheggiani, Ivan Titov.* EMNLP 2017. [paper](https://arxiv.org/abs/1703.04826) + +1. **Graph Convolutional Networks with Argument-Aware Pooling for Event Detection.** +*Thien Huu Nguyen, Ralph Grishman.* AAAI 2018. [paper](http://ix.cs.uoregon.edu/~thien/pubs/graphConv.pdf) + +1. **Geometric Matrix Completion with Recurrent Multi-Graph Neural Networks.** +*Federico Monti, Michael M. Bronstein, Xavier Bresson.* NIPS 2017. [paper](https://arxiv.org/abs/1704.06803) + +1. **Graph Convolutional Matrix Completion.** +*Rianne van den Berg, Thomas N. Kipf, Max Welling.* 2017. [paper](https://arxiv.org/abs/1706.02263) + +1. **Hybrid Approach of Relation Network and Localized Graph Convolutional Filtering for Breast Cancer Subtype Classification.** +*Sungmin Rhee, Seokjun Seo, Sun Kim.* IJCAI 2018. [paper](https://arxiv.org/abs/1711.05859) + +1. **Modeling polypharmacy side effects with graph convolutional networks.** +*Marinka Zitnik, Monica Agrawal, Jure Leskovec.* ISMB 2018. [paper](https://arxiv.org/abs/1802.00543) + +1. **DeepInf: Modeling influence locality in large social networks.** +*Jiezhong Qiu, Jian Tang, Hao Ma, Yuxiao Dong, Kuansan Wang, Jie Tang.* KDD 2018. [paper](https://arxiv.org/pdf/1807.05560.pdf) + +1. **Exploiting Semantics in Neural Machine Translation with Graph Convolutional Networks.** +*Diego Marcheggiani, Joost Bastings, Ivan Titov.* NAACL 2018. [paper](http://www.aclweb.org/anthology/N18-2078) + +1. **Exploring Graph-structured Passage Representation for Multi-hop Reading Comprehension with Graph Neural Networks.** +*Linfeng Song, Zhiguo Wang, Mo Yu, Yue Zhang, Radu Florian, Daniel Gildea.* 2018. [paper](https://arxiv.org/abs/1809.02040) + +1. **Graph Convolution over Pruned Dependency Trees Improves Relation Extraction.** +*Yuhao Zhang, Peng Qi, Christopher D. Manning.* EMNLP 2018. [paper](https://arxiv.org/abs/1809.10185) + +1. **N-ary relation extraction using graph state LSTM.** +*Linfeng Song, Yue Zhang, Zhiguo Wang, Daniel Gildea.* EMNLP 18. [paper](https://arxiv.org/abs/1808.09101) + +1. **A Graph-to-Sequence Model for AMR-to-Text Generation.** +*Linfeng Song, Yue Zhang, Zhiguo Wang, Daniel Gildea.* ACL 2018. [paper](https://arxiv.org/abs/1805.02473) + +1. **Cross-Sentence N-ary Relation Extraction with Graph LSTMs.** +*Nanyun Peng, Hoifung Poon, Chris Quirk, Kristina Toutanova, Wen-tau Yih.* TACL. [paper](https://arxiv.org/abs/1708.03743) + +1. **Sentence-State LSTM for Text Representation.** +*Yue Zhang, Qi Liu, Linfeng Song.* ACL 2018. [paper](https://arxiv.org/abs/1805.02474) + +1. **End-to-End Relation Extraction using LSTMs on Sequences and Tree Structures.** +*Makoto Miwa, Mohit Bansal.* ACL 2016. [paper](https://arxiv.org/abs/1601.00770) + +1. **Learning Human-Object Interactions by Graph Parsing Neural Networks.** +*Siyuan Qi, Wenguan Wang, Baoxiong Jia, Jianbing Shen, Song-Chun Zhu.* ECCV 2018. [paper](https://arxiv.org/pdf/1808.07962.pdf) diff --git a/GUI/Pangolin_ForkLift-Path-Tracking.cpp b/GUI/Pangolin_ForkLift-Path-Tracking.cpp new file mode 100644 index 00000000..501ee949 --- /dev/null +++ b/GUI/Pangolin_ForkLift-Path-Tracking.cpp @@ -0,0 +1,481 @@ +#include +#include +#include +#include +#define FORKLIFT_LENGTH 1.3; +#define D (1.5) +#define WHEEL_WIDTH 0.3 +#define WHEEL_LEN 0.2 +void DrawRearSteerWheel(float steerAngle) +{ + + pangolin::OpenGlMatrix Twc,Twc_T ,Twc_R; + Twc.SetIdentity(); + + Twc_R =Twc.RotateZ(steerAngle); + + Twc_R(0,3) += Twc(0,3); + Twc_R(1,3) += Twc(1,3); + Twc_R(2,3) += Twc(2,3); + + glPushMatrix(); + glMultMatrixd(Twc_R.m); + + + glBegin(GL_LINES); + glLineWidth(1); + glColor3f(1, 0, 0); + + glVertex3f(-WHEEL_LEN, WHEEL_WIDTH, 0); + glVertex3f(WHEEL_LEN ,WHEEL_WIDTH, 0); + + glVertex3f(-WHEEL_LEN, WHEEL_WIDTH, 0); + glVertex3f(-WHEEL_LEN, -WHEEL_WIDTH, 0); + + glVertex3f(WHEEL_LEN, WHEEL_WIDTH, 0); + glVertex3f(WHEEL_LEN, -WHEEL_WIDTH, 0); + + glVertex3f(WHEEL_LEN,-WHEEL_WIDTH, 0); + glVertex3f(-WHEEL_LEN, -WHEEL_WIDTH, 0); + + glEnd(); + + glPopMatrix(); + +} + + +void DrawPassiveWheel() +{ + float baseY = FORKLIFT_LENGTH ; + float baseLX = -D/2; + float baseLR= D/2; + + + glPointSize(5); + glBegin(GL_POINTS); + + glColor3f(1, 0, 0); + // DRAW LEFT + + glVertex3f( -0.5,1.3, 0); + + glVertex3f(0.5, 1.3, 0); + + glEnd(); + + glBegin(GL_LINES); + + glVertex3f(-0.7, 1.5, 0); + glVertex3f(0.7, 1.5, 0); + + glVertex3f(-0.7, -0.4, 0); + glVertex3f(0.7, -0.4, 0); + + glVertex3f(-0.7, 1.5, 0); + glVertex3f(-0.7, -0.4, 0); + + glVertex3f(0.7, 1.5, 0); + glVertex3f(0.7, -0.4, 0); + glEnd(); + +} + +void DrawForkLift(float x, float y, float yaw,float steer) +{ + pangolin::OpenGlMatrix Twc,Twc_T ,Twc_R; + Twc.SetIdentity(); + Twc_T = Twc.Translate(x, y, 0.0); + Twc_R =Twc.RotateZ(yaw); + + Twc_R(0,3) += Twc_T(0,3); + Twc_R(1,3) += Twc_T(1,3); + Twc_R(2,3) += Twc_T(2,3); + + glPushMatrix(); + glMultMatrixd(Twc_R.m); + DrawPassiveWheel(); + DrawRearSteerWheel(steer); + glPopMatrix(); +} +void drawGrid(int size) +{ + glBegin(GL_LINES); + glLineWidth(1); + + glColor3f(0.1, 0.1, 0.1); //gray + + for(int i = -size; i <= size ; i++){ + + glVertex3f(i,size, 0); + glVertex3f(i, -size, 0); + glVertex3f( size, i, 0); + glVertex3f(-size, i, 0); + } + glEnd(); +} +using namespace std; +float k = 0.7; // look forward gain +float Lfc = 2.0; // look ahead distance +float Kp = 1.0; // speed propotional gain +float dt = 0.1; +float L = 1.3; +class Point2f +{ +public: + Point2f() + {x=0; y= 0;} + Point2f(float _x, float _y ) + { + x = _x; + y = _y; + } + float x; + + float y; +}; + +class State +{ +public: + State() + { + x= 0; + y = 0; + yaw = 0; + v = 0; + } + void update(float a, float delta) + { + x = x + v*cos(yaw)*dt; + y = y + v*sin(yaw)*dt; + yaw = yaw + v/L*tan(delta)*dt; + v = v + a*dt; + } + float x; + float y; + float yaw; + float v; +}; + +float PIDcontrol(float target, float current) +{ + float a = Kp*(target - current); + return a; +} + +int calc_target_index(State state, vectorpath) +{ + float minDis = FLT_MAX; + int ind = 0; + for(int i=0; iLd) && (ind+1)path, int pind, float &delta) +{ + int ind = calc_target_index(state, path); + float tx, ty; + int N = path.size(); + if(pind >= ind) + { + ind = pind; + } + if(indpath) +{ + glPointSize(4); + glBegin(GL_POINTS); + glColor3f(0, 0, 0); + for(int i=0; ipath; + for(float i=-3.14; i<=3.14; i+=0.1) + { + Point2f pt; + pt.x = 10*cos(i); + pt.y = 10*sin(i); + path.push_back(pt); + } + +// for(float i=-10; i<20; i+=0.01) +// { +// Point2f pt; +// pt.x = i; +// pt.y = 10/(1+exp(-i)); +// //pt.y = sin(i+3.14/6)*i/10.0; +// path.push_back(pt); +// } + float target_speed = 0.5; + + State state; + state.x= -20.0; + state.y =-3; + state.yaw = 0; + int target_ind = calc_target_index(state,path); + float di = 3.14/2; + while(1) + { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + d_cam.Activate(s_cam); + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + drawTarget( path[target_ind]); + DrawForkLift(state.x, state.y, 3.14/2+state.yaw, di); + drawGrid(100); + drawPath(path); + if(target_ind #include @@ -119,4 +127,25 @@ TARGET_LINK_LIBRARIES(test_${sample_basename} ${OPENGL_LIBRARIES}) - +# QT + + 安装命令: + sudo apt-get install qt4-dev-tools qt4-doc qt4-qtconfig qt4-demos qt4-designer + + 关于集成开发环境我觉得QDevelop很不错,它跟Qt Designer结合的很好,而且有提示类成员函数的功能。 + 这样,使用Qdevelop编写代码和编译、调试,使用Qt Designer设计界面,开发效率较高。 + 运行以下命令安装QDevelop: + sudo apt-get install qdevelop + + 为了连接MySQL数据库,需要安装连接MySQL的驱动程序: + sudo apt-get install libqt4-sql-mysql + + 如果还需要其它的没有默认安装的Qt库,可以在命令行输入 + sudo apt-get install libqt4- + 然后按tab键自动补全,就会列出所有以libqt4- + + + 如果还需要画一些数据曲线和统计图表等,而第三方的QWT库提供了这些功能。同样,只需要一个命令即可完成安装: + sudo apt-get install libqwt5-qt4 libqwt5-qt4-dev + + diff --git a/LSLAM/readme.md b/LSLAM/readme.md new file mode 100644 index 00000000..dbf17494 --- /dev/null +++ b/LSLAM/readme.md @@ -0,0 +1,3 @@ +# LSLAM 激光雷达SLAM + +[参考 激光slam 完整答案解析 和 个人笔记](https://github.com/Ewenwan/laser_slam) diff --git a/MXnet/maxnet_dl.pdf b/MXnet/maxnet_dl.pdf new file mode 100644 index 00000000..bc16b82a Binary files /dev/null and b/MXnet/maxnet_dl.pdf differ diff --git a/MXnet/readme.md b/MXnet/readme.md index 841a3497..7fac032a 100644 --- a/MXnet/readme.md +++ b/MXnet/readme.md @@ -1,7 +1,9 @@ # MXnet [参考](http://lucianlv.blog.51cto.com/9871307/1812733) -[通过 MXNet / Gluon 来动手学习深度学习 在线](http://zh.gluon.ai/) +[通过 MXNet / Gluon 来动手学习深度学习 在线](https://zh.diveintodeeplearning.org/) + +[github](https://github.com/diveintodeeplearning/d2l-zh) [pdf](http://zh.gluon.ai/gluon_tutorials_zh.pdf) diff --git a/PCL_APP/Basic/Filtering/PassThroughfilter.cpp b/PCL_APP/Basic/Filtering/PassThroughfilter.cpp index fc7ba55c..42ea0386 100644 --- a/PCL_APP/Basic/Filtering/PassThroughfilter.cpp +++ b/PCL_APP/Basic/Filtering/PassThroughfilter.cpp @@ -55,6 +55,7 @@ int pass.setInputCloud (cloud_ptr);//设置输入点云 pass.setFilterFieldName ("z");// 定义轴 pass.setFilterLimits (0.0, 1.0);// 范围 + // pass.setKeepOrganized(true); // 保持 有序点云结构=============== pass.setFilterLimitsNegative (true);//标志为false时保留范围内的点 pass.filter (*cloud_filtered_ptr); diff --git "a/Python_Machine_Learning/c_cpp\344\273\243\347\240\201\345\256\236\347\216\260.md" "b/Python_Machine_Learning/c_cpp\344\273\243\347\240\201\345\256\236\347\216\260.md" new file mode 100644 index 00000000..9e5ef9af --- /dev/null +++ "b/Python_Machine_Learning/c_cpp\344\273\243\347\240\201\345\256\236\347\216\260.md" @@ -0,0 +1 @@ +# c_cpp代码实现 机器学习库 代码分析记录 diff --git a/Python_Machine_Learning/readme.md b/Python_Machine_Learning/readme.md index 93e9eb59..4e6c31f3 100644 --- a/Python_Machine_Learning/readme.md +++ b/Python_Machine_Learning/readme.md @@ -1,9 +1,22 @@ # 机器学习 +[我的代码!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!](https://github.com/Ewenwan/PyML) + +[台湾大学李宏毅老师机器学习](https://github.com/Ewenwan/NTU-Machine-learning) + +[机器学习算法 程序笔记 待整合](https://github.com/Ewenwan/Machine_Learning) + +[机器学习&深度学习网站资源汇总(Machine Learning Resources) ](https://github.com/Ewenwan/mlhub123) + +[机器学习资源 Machine learning Resources](https://github.com/Ewenwan/MachineLearning-1) + +[(西瓜书)公式推导解析](https://github.com/Ewenwan/pumpkin-book) + +[c++ 机器学习库源码,可借鉴,学习!!!!!!!](https://github.com/mlpack/mlpack) + ![](http://antkillerfarm.github.io/images/article/ML.jpg) [机器学习与概率 概率图模型CPD 结构学习 CRF MCMC ](https://www.cnblogs.com/ironstark/category/765694.html) -[我的代码](https://github.com/Ewenwan/PyML) [机器学习实战 一整套教学 ](https://github.com/Ewenwan/MachineLearning) @@ -19,6 +32,11 @@ [Artificial Intelligence 词汇集](https://jiqizhixin.github.io/AI-Terminology-page/) +[课程《Python3 入门机器学习》示例代码](https://github.com/liuyubobobo/Play-Leetcode) + +[台大机器学习课程作业详解 ](https://github.com/Ewenwan/ML-Foundation-and-ML-Techniques) + +[集体智慧编程 collective intelligence](https://github.com/Ewenwan/Programming-Collective-Intelligence-Source-Code) ## 1 最大释然估计 Maximum Likelihood Estimation (MLE) 最大后验概率Maximum A Posterior (MAP) ## 2 朴素贝叶斯 Naive Bayes diff --git "a/Python_Machine_Learning/\346\234\272\345\231\250\345\255\246\344\271\240\344\270\216\344\274\230\345\214\226.md" "b/Python_Machine_Learning/\346\234\272\345\231\250\345\255\246\344\271\240\344\270\216\344\274\230\345\214\226.md" new file mode 100644 index 00000000..403bcb5a --- /dev/null +++ "b/Python_Machine_Learning/\346\234\272\345\231\250\345\255\246\344\271\240\344\270\216\344\274\230\345\214\226.md" @@ -0,0 +1,335 @@ +# 机器学习与优化 + +https://intelligent-optimization.org/LIONbook/ + +本书是机器学习实战领域的一本佳作,从机器学习的基本概念讲起,旨在将初学者引入机器学习的大门,并走上实践的道路。本书通过讲解机器学习中的监督学习和无监督学习,并结合特征选择和排序、聚类方法、文本和网页挖掘等热点问题,论证了“优化是力量之源”这一观点,为机器学习在企业中的应用提供了切实可行的操作建议。 + +本书适合从事机器学习领域工作的相关人员,以及任何对机器学习感兴趣的读者。 + +## 第1 章引言 + +人不应该过着野兽般的生活,而是要追寻美德与知识。—————— 但丁 + +### 1.1 学习与智能优化:燎原之火 + +**优化是指为了找到更好的解决方案而进行的自动化搜寻过程。**可以说,流程、方案、产品和服务之所以能持续改进,正是缘于优化为之提供的强大动力。优化不仅关乎方案的确定(从一些给定的可行方案中,选出最好的一个),**它还能主动创造出新的解决方案。** + +**优化催生了自动化的创造和革新。**这看起来非常矛盾,因为自动化通常不会和创造与革新联系起来。因此,那些相信机器只能用来处理单调的重复性工作的人们在阅读本书时,会觉得书中的观点简直是胡言乱语,甚至会感受到如同被挑衅一般的愤怒。 + +几乎所有的商业问题都可以归结为寻找一个最优决策值x, 这要通过使某个收益函数goodness(x) 最大化来实现。为了能形象地理解,我们假设有一个集合变量x = (x1; ... ; xn),它描述的可以是一个或多个待调节的旋钮,也可以是将要做出的选择,还可以是待确定的参数。 + +在市场营销中,x 可以是一个向量,其数值表示为各类宣传活动(电视、报纸、各种网站、社交媒体)分配的预算,goodness(x) 则可以是由这些宣传活动而产生的新客户数量(产生的新粉丝数量). + +在网站优化中,x 可以涉及图片、链接、话题和不同大小文本的使用,goodness(x) 则可以是该网站的普通访客成为客户的转化率。 + +在工程学中,x 可以是一个汽车发动机的设计参数集,goodness(x)则可以是该发动机每加仑汽油所能行驶的英里数。 + +将问题归结为**“优化一个收益函数”也激励着决策者,使用量化的目标,就可以用可衡量的方式来领会宗旨,也就可以专注于方针的制定而非执行的细枝末节。**当人们深陷于执行的泥潭中,以至于遗忘了目标时,企业就染上了“疫病”,此时如果外界环境发生了变化,这种“疫病”将会使企业无法做出及时的应对。 + +**自动化**是解决这个问题的关键:将一个问题形式化地表述后,我们**把得到的收益模型输入计算机,计算机将自动创造出并找到一个或多个最佳的选项。**另外,当条件和重点发生改变时,只需要修改一下收益函数的量化目标,再重启优化过程就可以了。当然,CPU 时间会是个问题,也并非每次都能保证找到全局最优解决方案。但可以肯定的是,使用计算机来搜寻,无论是速度还是范围,都远远领先于人力搜寻,并且这一领先优势会越来越明显。 + +然而,在大多数现实场景中,优化的惊人力量仍遭到很大程度的压制。优化在现实中没有被广泛采纳的主要原因是,**标准的数学优化理论假设存在一个需要最大化的收益函数**,也就是说,有一个明确定义的模型goodness(x) 为每个输入配置x 匹配一个结果。而目前,在现实的商业情境里,这个函数通常是不存在的。即使存在,靠人力找到这个函数也是极其困难、极其昂贵的。试想,问一个CEO“请您告诉我,优化您业务的数学公式是什么”,显然不是咨询工作中开始对话的最佳方式。当然,一个经理对于目标应该会有一些想法和权衡,但是这些目标并没有以数学模型的方式给定,它们是动态的、模糊的,会随着时间改变,并且受限于估计误差和人们的学习进程。**直觉被用来替代那些明确给定的、量化的和数据驱动的决策过程。** + +如果优化是燃料,那么点燃这些燃料的火柴就是机器学习。机器学习通过摒弃那种明确定义的目标goodness(x) 来拯救优化:我们可以**通过丰富的数据来建立模型。** + + +机器学习与智能优化(learning and intelligent optimization,LION)结合了学习和优化,它从数据中学习,又将优化用于解决复杂的、动态的问题。LION 方法提高了自动化水平,并将数据与决策、行动直接联系起来。描述性分析和预测性分析之后,LION 的第三阶段(也是最终阶段)是规范性分析(prescriptive analysis)。在自助服务的方式中,决策者手中直接握有更多的权力,而不必求助于中间层的数据科学家。就像汽车的发动机一样,LION 包含一系列复杂的机制,但是用户(司机)并不需要知道发动机的内部工作原理,就可以享用它带来的巨大好处。在未来的几十年内,LION 方法带来的创新,将会像野火那样,以燎原之势延伸到大多数行业。那么企业就像野火频发的生态系统中的植物一样,只有适应并拥抱LION 技术才能生存下来,并繁荣昌盛;否则,无论之前如何兴盛,在竞争逐渐加剧的挑战面前,都可能土崩瓦解。 + +LION 范式关注的并不是数学上的收益模型,而是海量数据,以及如何针对多种具体选择(包括实际的成功案例)进行专家决策,或者如何交互地定义成功的标准。当然,这些都是建立在让人们感觉轻松愉快的基础之上的。例如,在市场营销中,相关数据可以描述之前的资金分配和宣传活动的成效;在工程学中,数据可以描述发动机设计的实验(真实的或模拟的)和相应的油耗测量方式。 + +### 1.2 寻找黄金和寻找伴侣 + +用于优化的机器学习需要数据。数据来源可以是**以往的优化过程**,也可以是**决策者的反馈**。 + +丹尼尔是一名南非的采矿工程师,他曾遇到一个问题:如何在一张地图上找到挖掘金矿的最佳坐标。 +大约在1951 年,他开创性地将统计学的思想应用于新金矿的估值,而这一方法仅需用到有限的几个矿坑。需要优化的函数是Gold(x),即坐标x 处的金矿的金量。当然,在一个新的地方x 评估Gold(x) 是非常昂贵的。你可以想象,挖一个新矿没那么快,也没那么简单。但是在一些试探性的挖掘之后,工程师们会积累一些把坐标x1; x2; x3 ... 和金量Gold(x1); Gold(x2); Gold(x3) 关联起来的实例知识。克里金的直觉告诉他,用这些实例(**来自以往优化过程的数据**)可以建立起函数Gold(x) 的模型。这个称为GoldModel(x) 的模型归纳以往的实验结果,为地图上的每个位置x 给出金量的估计值。通过优化,这个模型找到使预计黄金产量GoldModel(x) 最大化的地点xbest,于是这个xbest 成为下一个挖掘的地点。 + +这种技术现在被称为克里金法(Kriging),它背后的理念是未知点对应的值应该是其邻近已知点所对应的值的加权平均,权重与这些已知点到该未知点的距离相关。高斯过程、贝叶斯推断和样条函数(spline)都涉及了相关的建模方法。 + +在一开始,待优化函数中的某些信息是不全面的,只有决策者才能够调整优化的过程。许多现实问题,即使不是大多数,都需要借助有学习参与的迭代过程来解决。在了解了越来越多的案例后,用户会认识并调节自己的喜好,系统会从用户的反馈中建立起他的喜好模型。这一过程将持续下去,直到用户满意或者直到耗尽为这一决策分配的时间。 + +### 1.3 需要的只是数据 +商业领域里充斥着各种数字形式的数据。大数据指的是大量的半结构数据。顺便提一句,在20 世纪七八十年代,数据对于当时的存储设备来说是庞大的,而如今的“大数据”更多是商业上的宣传概念:即便是最大的公司产生的所有数据,只需一台PC 就足以处理了。 + +随着社交网络的爆发、电子商务的迅速扩张和物联网的兴起,网络正在掀起一场由结构化和非结构化数据引起的海啸。这场海啸驱使人们在信息技术领域花费多达数十亿美元。也有新的证据表明,标准的商业智能平台使用率正在下降,这是因为企业界已经不得不开始考虑一些非结构化的数据,而这些数据拥有无法估量的现实价值。例如,社交网络产生大量的数据,其中的大多数无法分类,也无法用传统数据的刚性层次结构来表示。试想,你该如何评估Facebook 上一个“赞”的价值?况且非结构化数据需要用自适应方法来分析。再想想,随着时间的流逝,一个“赞”的价值会发生怎样的变化? 由于这类问题的存在,我们需要在数据建模、自适应学习和优化等领域运用更加先进的技术。 + +为了让软件能够自我改进,并能快速适应新数据和调整后的业务目标,需要使用LION方法。这种方法的优势在于能够从过往的经验中学习、在工作中学习、应对不完全的信息,并快速适应新的情况,而这些能力通常只与人类的大脑联系起来。 + +LION 技术这种内在的灵活性是至关重要的,因为在求解过程开始之前,我们很可能无法确定哪些是对决策有影响的因素和重点。例如,我们要给一个市场营销的前景评分来估计其价值,应该考虑哪些因素?这些因素又对结果分别有多大程度的影响? 如果使用LION 方法的话,这些问题的答案就是:“这些都不是问题。”系统会开始自我训练,源源不断的数据加上终端用户的反馈将快速提升系统的性能。专家||这里指营销经理||可以通过表达他们自己的观点来改善系统的输出。 + + +### 1.4 超越传统的商业智能 + +每一家企业都需要数据来满足3 项基本需求: + +* (1) 了解目前的业务流程,并评估以往的表现; +* (2) 预测商业决策的影响; +* (3) 对业务的关键因素制定并执行明智且合理的决定,从而提升赢利能力。 + +传统的描述型商业智能(business intelligence,BI)擅于记录和可视化过往的表现。构建这样的记录意味着需要聘请顶级顾问,或雇用那些有统计、分析和数据库等领域知识的专业人员。专家必须要设计数据提取和操作的流程,然后交给程序员来实际执行。这是一个缓慢而繁琐的过程,毕竟大多数商业的境况都是瞬息万变的。 + +因此,那些严重依赖于BI 的企业正在利用性能快照,尝试理解当前情况和未来趋势,并对此做出反应。这就如同开车的时候只盯着后视镜,很有可能会撞上什么东西。现在对于企业来说,就像是已经撞到了一堵僵化的墙,并且缺乏快速适应变化的能力。 + +**预测分析**确实在预见方案效果方面做得更出色,然而,**将数据驱动模型和优化进行整合, +自动创建完善的解决方案,才是LION 真正的强大之处**。 + +**规范性分析**做到了引领我们直接从数据到最佳改进方案,**以及从数据到可执行的洞察力,再到行动本身!** + + +### 1.5 LION 方法的实施 + +对于处在不同业务状态的企业而言,全面采用LION 方法作为商业实践的步骤会有所不同。更重要的是,相关数据的情况也会影响这一进程。显然,在数据收集完成的时候引进LION范式会相对容易,开销也更少。对某些企业来说,由于遗留系统的迁移和转换需要涉及大范围的整理,开销会非常大。这也正是那些老练的服务提供商能大显身手的地方。 + +除了整理和定义相关数据的结构之外,最重要的一点就是建立起数据分析团队和商业终端用户之间的合作。LION 方法通过自身的特性提供了一种合作方式,助其共同发现蕴藏在结构化或半结构化数据中的潜能。数据分析团队能够和商业终端用户高效地并肩合作,关键在于能够使业务目标的不断变化迅速反映到模型上。LION 方法的引入可以帮助数据分析团队在价值创造链中产生根本性的变化,它能揭示隐藏的商机,也能加快他们的商业伙伴对客户要求和市场变化的反应速度。 + +就业市场也将被打乱。从人类的实例中进行学习的软件将推导出我们在使用却又不明确了解的规则。这将消除进一步自动化的障碍,在许多需要适应性、常识和创造性的任务中,机器将会代替工人,也许会让中产阶级处在风险之中。 + +LION 方法可以说是**一种极具颠覆性的发现隐藏价值的智能方法,它能快速适应改变并改进业务**。通过恰当的规划和实施,LION 技术可以帮助企业在竞争中独领风骚,避免被燎原之火灼伤,同时也可以帮助个人在高技能人才的就业市场中保持竞争力。 + + +## 第2 章懒惰学习:最近邻方法--自然不允许跳跃 + +如果你还记得小时候是如何识字的,那么你就可以理解什么是从实例中学习,尤其是监督学习。父母和老师给你展示一些带有英文字母(a、b、c,等等)的实例,然后告诉你:这是a,这是b。 + +在监督学习中,由监督者(老师)给出一些已标记的实例,系统根据这些已标记的实例来完成训练。每一个实例是一个数列,它包括一个作为输入参数的向量x,称为**特征(feature)**,和与之相对应的输出标记y。 + +那些懒惰的初学者在采蘑菇的时候遵循简单的模式。通常他们在采摘蘑菇之前没有学习任何相关的知识,毕竟,他们到特伦蒂诺是来度假的,而不是来工作的。当发现一个蘑菇时,他们会在书中寻找相似的图片,然后仔细检查对照细节列表中的相似特征。这就是机器学习中懒惰的“最近邻”(nearest neighbor)算法在实际问题中的一次应用。 + +为什么这样一种简单的方法是有效的呢?我们可以用Natura non facit saltus(“自然不允许跳跃”的拉丁文)原则来解释它。自然的事物与特征常常是逐渐改变,而不是突然改变的。如果你将书中的一个可食用的蘑菇作为原型,然后发现你自己采摘的蘑菇与这个原型蘑菇的各项特征非常相似,那么你也许会认为你的蘑菇是可以食用的。 + +在机器学习领域,最近邻方法的基本形式与基于实例的学习、基于案例的学习和基于记忆的学习有关。它的工作原理如下:我们把已标记的实例(包括输入及相应的输出的标记)储存起来,不进行任何操作,直到一个新输入模式需要一个输出。这种系统被称为懒惰的学习者:它们只是将这些实例储存起来,其他的什么也不做,直到用户询问它们。当一个新输入模式到达时,我们在存储器中查找到与这个新模式相近的那些实例,输出则由这些相近模式的输出所决定。 + +一个更具健壮性和灵活性的方法是考虑大小为k 的近邻集合,而不仅仅是最相近的那一个,不难猜到这种方法被称为**K 近邻(KNN)方法**。它的灵活性来源于可以使用不同的分类方法。例如,新实例的输出可以用多数同意规则,即输出这k 个近邻中占大多数的那一个输出。如果想要更加安全的方法,可以仅在这k 个近邻的输出完全相同时才确定新实例的类别(一致同意规则),否则就输出“未知”。这个建议可以用在区分有毒的蘑菇时:如果输出“未知”,就联系当地警方寻求帮助。 + +如果面临的是一个回归问题(预测一个实数,例如蘑菇中有毒物质的含量),我们可以将这k 个最相近的实例的输出平均值作为新实例的输出。当然,这k 个实例到新实例的距离可能有所差别,而且在某些情况下,距离较近的实例对新实例的输出影响更大是很合理的。在这种被称为**加权K 近邻(WKNN)**的方法中,权重取决于距离。 + +y=sum(yi/(d(xi,x)+d0))/sum(1/(d(xi,x)+d0)) + +其中d(xi; x) 指两个向量在属性空间中的距离(例如欧氏距离),d0 是一个小的偏移常数,用以避免出现0 作为除数的情况。d0 越大,距离较远的点的贡献就越大。如果d0 趋近于无穷大,那么这k 个实例的权重就几乎一样了。 + +WKNN 算法很容易实现,并且相应的估计误差也很小。它的主要缺点是需要大量的内存空间,以及在测试阶段巨大的计算量。因此我们常常将已标记的实例进行聚类,用来减少所需的内存空间。聚类方法按照相似性将它们划分成一个个小组,并且只存储每个小组的原型(中心)。 + +本书接下来将继续考虑新实例和内存中实例之间的距离,并且将这一想法一般化。核方法与局部加权回归就可看作最近邻方法的一般化,这两种方法并不是粗鲁地直接将远处的点排除,而是根据它们到查询点的距离,灵活地赋予它们相应的重要性(权重)。 + +KNN(K 近邻)是一种原始的懒惰的机器学习方式:它只是把所有的训练实例存在存储器中(输入和对应的输出标记)。 + +当有一个新输入并需要计算其对应的输出时,在存储器中查找k 个最接近的实例。读取它们的输出,并根据它们的大多数或平均值推导出新实例的输出。当存储了非常多的实例时,训练阶段的懒惰会让预测阶段的响应时间变得很长。 + +相似的输入经常对应着相似的输出,这是机器学习领域的一个基本假设,因此KNN方法在很多实际案例中都有效。它与人类的某些“基于案例”的推理具有相似性。虽然这个方法简单粗暴,但它在很多现实案例中的效果都令人惊奇。 + +从现在起,不要做一个懒惰的学习者,别以为这样可以高枕无忧。继续读下面的章节,坚持学下去。早起的鸟儿有虫吃,睡懒觉只能肚子空空了。 + +## 第3 章学习需要方法 +数据挖掘,名词,对数据进行的严刑逼供.如果拷打得足够久,它会向你坦白任何事情。 + +无论是对于人类,还是对于机器来说,学习都是一种强大却又微妙的能力。真正的学习涉及如何从一个现象中提取深层次的、基础的关系,如何简要地概括各种不同的事件所遵循的规律,以及**如何通过发现基本的定律来统一解释不同的情况。** + +最重要的是,我们真正的目标是能够泛化的模型,以及模型对新实例的解释能力,新实例是指与训练实例来自同一个应用领域,但在学习阶段没有遇见过的实例,而从实例中学习仅仅是走向这一终点的途径之一。与此相反,死记硬背常常被认为是非常低效的学习方式,它虽然对初学者有一定的作用,但是无法使你成为真正的专家。如果目标是泛化,那么模型在学习集上的表现并不能保证泛化是正确的,还可能导致我们对结果过于乐观,因此要极其谨慎地估计这个模型的性能。**归根结底,只擅于死记硬背的学生日后在生活中未必能取得个人的成功。** + +事实上,开始机器学习流程之前,用户会根据直觉和智能在原始数据中提取一个具有代表性的子集,这一步是非常有用的。特征(或属性)是观察到的现象的各个可度量的性质,这些性质包含了与输出有关的有用的信息。这一准备阶段称为**特征选择(选出一个集)**,以及**特征提取(生成一个组合)**。 + +**分类问题**(识别以特征x 描述的某一特定目标的类别)中,输出是类别的相应编码。输出y 属于一个有限集,例如yi = +-1,或者yi 属于{ 1,...,N}。例如,可以将蘑菇分为两类:可食用的和有毒的。 + +**回归问题**的输出从一开始就是一个实数值,它的目标是通过建模研究因变量(输出值y)与一个或多个自变量(输入值x)之间的关系。例如,根据蘑菇的特征来预测其有毒物质的含量。 + +### 从已标记的案例中学习:最小化和泛化 + +监督学习方法使用实例构造一个函数y = f(x),将输入x 和输出y 关联起来。这一关联选自一个灵活的模型f(x;w),其中的灵活性来自可调整的参数(即权重系数)w。 + +在许多情况下,特征提取需要一些来自人类的洞见,然而最优参数的确定则是完全自动的,这也是这一方法被称为机器学习的原因。**让模型对训练集中的实例进行正确的分析,从而确定那些自由参数。** + +如果需要优化的函数是可微的,一个简单的方法是使用梯度下降(gradient descent)。人们可以重复地计算这个函数关于权重的梯度,并朝着负梯度的方向移动一小步。事实上,这是神经网络里很流行的一种技术,称为基于误差反向传播(backpropagation)的学习. + +偏差-方差困境可表述如下: + +* 参数过少的模型会因较大的偏差而失准:它们缺乏灵活性。 +* 参数过多的模型则会因较大的方差而失准:它们对于样本中的细节过于敏感(细节中的改变将会使模型产生大的变化)。 +* 找到最佳模型需要控制“模型复杂度”,即模型的结构和参数数量都要恰到好处,从而在偏差和方差之间达成折中方案。 + +区分监督分类的两类方法也是有意义的。第一类热衷于得到某个关于输入是如何产生输出的“构造性的模型”;第二类更在意结果,即获得正确的分类。前者关心对内在机制的解释,后者则单纯地在意其性能。 + +第一类情况下,生成方法(generative method)尝试在实例中建模,为不同的类型y 生成实测数据x 的过程进行建模。给定某个类,比如有毒的蘑菇,它具有某种外形的概率是多少? + +判别算法(discriminative algorithm)就不会尝试建模数据的生成过程,它们直接估计p(yjx),这个问题在某些情况下比之前生成方法的两步过程(首先建模p(xjy),然后才导出p(yjx))要更简单。判别型方法的例子包括多层感知器神经网络,以及支持向量机(SVM)等,接下来的章节里将会讨论。 + +判别算法所示的捷径具有深远意义,我们不必知道某些类别如何产生输入实例,也不必为此建立一个详尽的模型,就可以构造精确的分类器。想要不用冒着生命危险去采摘蘑菇,并不需要成为真菌学家,你只需要大量有代表性的蘑菇实例集,并且它们已经正确地分好了类。 + +认识到不需要成为某个领域的专家就可以做出贡献,这是个人的一小步,却是LION 发展道路上的一大步。不用说,成功的企业用朴实低调而又功能强大的数据驱动和优化驱动的工具,弥补了专业知识方面的缺憾。 + + + +### 3.2 学习、验证、测试 + +基于已标记实例的学习要求我们采用细致的实验程序来测量学习过程的效果。尤其注意,不能将已经用于训练的实例再用于测试学习系统的性能,如果这么做,将是一个可耻且无法原谅的错误。机器学习的目标是获得一个拥有泛化能力的系统,用以分析新的或以往未见过的数据;否则,这个系统就不是在学习,而只是记住了一些已经知道的模式,这也是学校不停更换考试题的原因. + +然而现实可能与理想相差甚远。一些情况下,训练集是相当小的,并且需要尽可能保证它们能同时满足训练和性能测试的要求。这种情况下,实例集必须清楚地分为训练集和验证集,前者用来训练,后者用来测试性能. + +一个典型的性能测试是系统输出与监督者给出的正确输出之间的均方根(root mean square,RMS)误差。值集的RMS 值是原始值的平方的算术平均的平方根。 + +一般而言,学习过程通过优化模型参数以使得模型尽可能好地拟合训练数据的输出。那样的话,如果我们从验证数据的同一个总体中取一个独立的抽样作为训练数据,一般会导致验证数据集的误差大于训练数据集的误差。如果训练过度的话,这种差异很可能会变得非常严重,并导致**过拟合(过度训练)**。当训练实例很少,或者模型中的参数很多时,更容易发生这种情况。 + +分层交叉验证(strati¯ed cross-validation)作为一种改进,可以避免训练集和测试集中不同类的平衡问题。它能够避免有时发生这种情况,即某一个类在训练集中很多,而在验证集中很少(相对于所有实例的平均出现率)。应用分层能够分别从每个类别中抽取出K 个测试样本,以保证不同类别的实例分布均衡。 + +### 3.3 不同类型的误差 +在测试一个模型的性能时,各种各样的误差带来的影响并不一样。如果你将有毒的蘑菇当作可食用的,你可能会有生命危险;如果你将可食用的蘑菇当作有毒的,你只是浪费了一点时间。根据问题的不同,确定最佳分类的标准也随之改变。考虑一个二元分类(输出“是”或者“否”)。一些可能的标准是:准确率(accuracy)、精确率(precision)和召回率(recall)。虽然它们的定义都很简单,但是需要小心区分以避免混淆(见图3-4)。 + +## 第4 章线性模型 +大多数惯用右手的人拥有线性思维, 爱用传统的方式思考。(读者可以自由选择是否相信我们的开场白。) + + +优化的强大力量建立在拥有神奇力量的线性代数上。你是否记得在学校里老师说“好好学习线性代数,你会受益终身”?好吧,多年以后你会发现他是对的。线性代数是“数学生存工具包”,当你面临一个棘手的问题时,应该首先试试线性方程组。在很多情况下,即使你不能用线性代数直接解决这些问题,至少也能得到一个不错的逼近。这不足为奇,解释数据的模型也是这样的。 + +### 4.1 线性回归 + +输入与输出特征的线性相关是一个广泛采用的模型。这一模型十分简单,并且训练起来很容易。另外,模型中每一项的权重系数都为这一项对应的特征的重要性提供了直观的解释:某一项权重系数的绝对值越大,对应的属性的影响就越大。所以,为了不让问题变得复杂,不要轻易尝试非线性模型,除非你的理由十分充足。 + + +### 4.4 大脑是如何工作的 +可以肯定的是,计算两个很大数的和的系统,与玩“赶尽杀绝”这类动作游戏的系统是很不一样的。进行逻辑演算或推理的系统认出母亲的脸的系统也是很不一样的。前一种系统是迭代的,它的工作方式是按照顺序的步骤来进行的,需要有意识地努力集中注意力。后一种系统以并行的方式工作,速度很快,无须太多努力,以非符号的方式(不会用到符号和逻辑)工作。 + +机器学习中的不同机制可以模仿这两类系统。线性判别器运用迭代梯度下降的学习方法来逐步改进,它更多模仿的是非符号系统;基于一连串“如果{那么{否则”规则(后面的章节将会提到它们)的分类树更多模仿的是逻辑系统。 + + +### 4.5 线性模型为何普遍,为何成功 + +线性模型如此普遍的深层原因是存在于许多或大部分物理现象中的平滑性(“自然不允许跳跃”)。图4-5 中的例子表明,青少年的平均身高随着年龄逐渐增长,而不是跳跃式地增长,直到青春期之后慢慢停滞。 + +### 4.6 最小化平方误差和 + +线性模型通过最小化式(4.2) 中的平方误差和确定下来。 + +### 4.7 数值不稳定性和岭回归 +实数(比如pi 和“大多数”的数)无法在数字计算机中表示出来,它们是“伪的”。数字计算机中的每个数都被赋以一个固定的有限的二进制数,没有方法来表示一个无限数位的数,像3:14159265 : : :。因此,在计算机中表示的实数都是“伪的”,它们能并且经常造成误差。误差会在数学运算的过程中不断传播,在某些情况下,一连串运算的结果可能与数学上的结果相差甚远。找一个矩阵,求它的逆矩阵,并且将二者相乘。你期望会得到单位矩阵,但最后你却得到一个不同的答案。也许你应该查查银行使用的小数精度。 + +如果没有办法来改变训练样本点的选择,而样本点又没有如愿地分布时,用以保证数值稳定性的数学工具是岭回归(ridge reghression)。它在需要最小化的(最小二乘)误差函数中加入了一个正则化(regularization)项 w转置*w + + + +传统的线性回归模型(一组输入{输出对的线性逼近)通过最小化线性模型预测值与训练样本输出值之间的平方误差和来找到可能的最好的实验数据线性拟合。最小化可以是“一招制胜”,通过推广线性代数中的矩阵求逆,也可以通过迭代的方式逐步修改模型参数并降低误差。广义逆法可能是拟合实验数据的最常用的技术。 + +在分类中,线性模型旨在用线条、平面与超平面来分离实例。要确定分离平面,人们可以要求把输入值映射到两个不同的输出值(如+1 和¡1)并使用回归。考虑到泛化性,找到健壮的分离超平面的更先进的技术是下面章节中将会描述的支持向量机。 + +计算机中不存在实数,它们只能用有限大小的二进制数字逼近,而这可能会导致误差 +和不稳定(样本点的小扰动导致结果变化较大)。 + +一些机器学习方法与生物大脑从经验和功能中的学习方式存在松散的联系。学习骑自行车与符号逻辑方程无关,而是关于如何进行逐步调整以及⋯⋯迅速从初始的事故中恢复过来。 + + +## 第5 章广义线性最小二乘法--如无必要,勿增实体。 +一个严谨的建模工作的输出并不是一个单一的“带走它或者留下它”的模型。通常,人们通过评价一个模型的性能(拟合的优劣)来处理多种建模体系结构,通过确定模型参数估计值的置信区间(例如误差线)来选择尽可能好的架构,等等。读完本章之后,你应当可以从一个普通用户变成专业的最小二乘法大师。 + +学习数据显著的模式和关系,意味着需要消除非显著的细节,例如测量噪声(由物理测量中有限精度导致的随机误差)。想想如何建模一个人的身高随着年龄改变的趋势。如果你重复用高精密仪器测量你的身高,那么每个测量会得到不同的值。这些带噪声的测量反映了一个简单的事实,那就是只能用有限的数位来描述你的身高(没有哪个精神正常的人会回答自己的身高是1823477 微米)。 + +### 5.1 拟合的优劣和卡方分布 + +在统计学中,如果一个模型倾向于描述随机误差或噪声而不是数据间的基本关系,那么就会产生**过拟合(over-ftting)现象**。当一个模型过于复杂时,例如相对于可用的数据量有太多的自由度(在我们多项式的例子中,就是有太多的参数),过拟合现象就会产生。 + +一般来说,过拟合模型的预测性能会很差。如果用人类的行为来打比方,可以想想教学:如果一个学生只关注并记住老师在课堂上讲的一些细节(例如数学课上某个特定练习的细节),而不是提炼并理解基本的规则和意义,他只能靠着记忆空洞地重复老师的字眼,却无法将他的知识举一反三应用到新案例上。 + +### 5.2 最小二乘法与最大似然估计 + +了解广义最小二乘拟合的基本方法后,现在从统计学的角度来思考一些附加的动机。鉴于我们有选择不同模型的自由,比如拟合多项式的次数,那么用于辨别最佳模型构架的方法将是十分珍贵的,毕竟不能仅仅依靠肤浅的“目测卡方”方法。 + +下面是最小二乘拟合的过程。 +* (1) 假设大自然和实验程序(包括测量)会产生独立的实验样本(xi; yi)。假设yi 的测量值受到了误差的影响,这个误差服从正态(即高斯)分布。 +* (2) 如果模型参数c 是已知的,那么就可以估计我们测量数据的概率。在统计学的术语中,这叫作数据的似然率(likelihood)。 +* (3) 最小二乘拟合所找到的就是使得我们数据的似然率最大化的参数。最小二乘是一种最大似然估计(maximum likelihood estimator)。从直觉上来说,这使得选择的模型和观察到的数据之间的“契合度”最大化。 + +### 5.3 置信度的自助法 + + +多项式拟合以一种特定的方式使用线性系数模型(linear-in-the-coe±cients model)来处理非线性问题。该模型包括(待定)系数的线性加权和乘以原始的输入变量的积。如果积被替换为输入变量的任意函数,相同的技术也可以使用,只要这个函数是固定的(函数中没有自由参数,仅作为乘法系数)。通过最小化平方误差来确定最优系数,这就意味着求解一组线性方程组。如果系数的数目大于输入{输出实例数,会出现过拟合(over-¯tting),用这样的模型来推断新输入值的输出结果是危险的。 + +多项式拟合的优度(goodness of a polynominal fit)可以通过预测观察到与实测数据的差异的概率来评价(给定了模型参数后数据的似然率)。如果这个概率很低,那么不应该太过于信任该模型。但关于误差如何生成的错误假设容易导致我们得出过于乐观或过于悲观的结论。统计从假设开始建立坚实的科学建筑。如果建立在无效假设的沙土上,即使最坚实的统计建筑也会倒塌粉碎。幸运的是,基于可行性强的大规模计算的方法(例如交叉验证)是容易理解的,并且具有健壮性。 + +像自助法(bootstrapping)这样“荒谬”的方法(对同一数据进行带放回的再抽样,并以蒙特卡罗的方式重复估计过程),可以用于获取估计的参数值周围的置信区间。你不过是最大化了自己被当成线性最小二乘法大师的概率。 + + +## 第6 章规则、决策树和森林 + + +## 第7 章特征排序及选择 + + +## 第8 章特定非线性模 + + + +## 第9 章神经网络:多层感知器 + + +## 第10 章深度和卷积网络 + + + +## 第11 章统计学习理论和支持向量机 + + +## 第12 章最小二乘法和鲁棒内核机器 + + + +## 第13 章机器学习中的民主 + + + + +## 第14 章递归神经网络和储备池计算 + + +## 第15 章自顶向下的聚类:K 均值 + + +## 第16 章自底向上(凝聚)聚类 + + + +## 第17 章自组织映射 + + + +## 第18 章通过线性变换降维(投影) + + +## 第19 章通过非线性映射可视化图与网络 + + + +## 第20 章半监督学习 + + +## 第21 章自动改进的局部方法 + + +## 第22 章局部搜索和反馈搜索优化 + +## 第23 章合作反馈搜索优化 + + + +## 第24 章多目标反馈搜索优化 + + +## 第25 章文本和网页挖掘 + + +## 第26 章协同过滤和推荐 + + +## + + +## + +## + + + +## + + +## + +## + + diff --git "a/Python_Machine_Learning/\346\234\272\345\231\250\345\255\246\344\271\240\344\270\216\344\274\230\345\214\226.pdf" "b/Python_Machine_Learning/\346\234\272\345\231\250\345\255\246\344\271\240\344\270\216\344\274\230\345\214\226.pdf" new file mode 100644 index 00000000..5da8672d Binary files /dev/null and "b/Python_Machine_Learning/\346\234\272\345\231\250\345\255\246\344\271\240\344\270\216\344\274\230\345\214\226.pdf" differ diff --git "a/Python_Machine_Learning/\346\234\272\345\231\250\345\255\246\344\271\240\345\267\245\344\275\234\350\246\201\346\261\202.md" "b/Python_Machine_Learning/\346\234\272\345\231\250\345\255\246\344\271\240\345\267\245\344\275\234\350\246\201\346\261\202.md" new file mode 100644 index 00000000..ad1f69fd --- /dev/null +++ "b/Python_Machine_Learning/\346\234\272\345\231\250\345\255\246\344\271\240\345\267\245\344\275\234\350\246\201\346\261\202.md" @@ -0,0 +1,66 @@ +# 机器学习招聘要求 +## 一、编程 + 熟练使用java, C++, python + 熟练运用SQL +## 二、大数据 + 熟悉Hadoop、Storm、Spark、Flink等分布式处理平台(Hadoop —> Storm —> Spark —> Flink) +## 三、机器学习 +对机器学习、深度学习、迁移学习、强化学习、异常检测其中之一理解透彻;对分类、回归、聚类、标注等统计机器学习问题具有很深的理解;熟悉常用的机器学习算法模型:lr、knn、naive bayes、rf、gbdt、svm、pca、svd、kmeans、kmodes、rl、din、cnn、rnn、NN(LSTM/AlexNet/GoogleNet/ResNet等)、TL等一部分或全部,有一定广度 + +在以下至少一个领域有深入研究:深度学习、自然语言处理、搜索算法、推荐算法、异常检测、图像识别、统计机器学习、互联网风控、广告、图挖掘、文本挖掘、知识图谱、模式识别、排序系统、数据挖掘、运筹优化、精准投放、个性化搜索经验、路径规划、人机交互、智能问答、文本检索、多语言处理 + +优秀的算法应用能力,包括特征提取、模型建立、效果评估、应用部署以及优化迭代等环节 + +良好的数学基础 + +良好的算法和数据结构基础 + +熟悉LTR模型、CTR预估算法等 + +## 四、熟悉一个或多个NLP/ML/DL开源工具库,能够快速实现并验证想法 + Caffe + TensorFlow + Keras + SkLearn +## 五、熟悉常用机器学习库 + Weka + Mahat + libSVM + sklearn + CRF++ +## 六、其它 + 参加ACM竞赛并取得名次者优先 + 有实际成果并发表在国际顶级会议、期刊(如CVPR,ICCV,ECCV,NIPS,ICLR,TPAMI等)者优先 + 有在ImageNet、MSCOCO、ICDAR等权威数据库上提交过结果并取得优异成绩者优先 + 长期跟踪机器学习领域的研究论文 + +# 知识体系 +结构化的知识才有力量。水泥钢筯以科学的比例和结构组织在一起才能成为高楼大厦。人体的各个器官以正确的结构组合在一起,才能成为智慧的人类。知识也只有以合理的比例和结构组合在一起,才能发挥威力,而比例怎么分配,结构怎么规划,需要慎重思考,仔细计划,最后才是有针对性地学习。就像盖高楼大厦要先设计,再购买原料,最后施工一样,学习也要先设计知识结构,再制定学习计划,最后再有针对性地学习,完成知识体系的搭建。 + +招聘要求中列出的知识点过多,并不是每一个都需要学,下面列出的知识点是学习AI过程中必须要学习的,但要求不同。这些知识点相互配合,搭建一个合理有效的关于AI的知识体系,不浪费过多精力,也没有缺失。 + +## 一、预备知识 + 熟练使用python + 熟练微积分、线性代数、概率论 + 熟练SQL操作 + 良好的算法基础 + 良好的数据结构基础 +## 二、大数据 + 熟练使用Spark + 了解Hadoop、Storm、Flink +## 三、机器学习 +熟练常用的机器学习算法模型:lr、knn、naive bayes、rf、gbdt、svm、pca、svd、kmeans、kmodes、rl、din、cnn、rnn、NN(LSTM/AlexNet/GoogleNet/ResNet等)、TL、LTR、CTR + +理解机器学习、深度学习、强化学习、迁移学习、异常检测 + +理解分类、回归、聚类、标注等机器学习问题 + +优秀的算法应用能力,包括特征提取、模型建立、效果评估、应用部署以及优化迭代等环节 + +深入研究深度学习和搜索算法,熟悉自然语言处理、推荐算法、图像识别 + +# 四、工具库 + 熟练使用TensorFlow,熟悉Keras,了解Caffe + 熟练使用libSVM、sklearn、CRF++ + +[机器学习算法总结](https://github.com/houchenl/AI/blob/9b3b9da55a89c3aa501396002b1b7c1ead1d117f/%E7%AE%97%E6%B3%95%E6%80%BB%E7%BB%93.md) diff --git a/README.md b/README.md index 53a0b03a..b10ff6d1 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,7 @@ # MVision Machine Vision 机器视觉 +[AI算法工程师手册 数学基础 统计学习 深度学习 自然语言处理 工具使用](http://www.huaxiaozhuan.com/) + +[AI 安全数据科学和算法 ](https://github.com/Ewenwan/AI-Security-Learning) [澳大利亚机器人视觉研究中心](https://www.roboticvision.org/) @@ -10,6 +13,12 @@ [Computer Vision and Pattern Recognition arxiv.org 最新提交的论文](https://arxiv.org/list/cs.CV/recent) +[papercept 会议论文投递](https://controls.papercept.net/conferences/scripts/start.pl) + +[easychair 会议论文投递](https://easychair.org/my/roles.cgi?welcome=1) + +[DBLP 计算机核心技术文献](https://dblp.uni-trier.de/) + [技术刘 增强现实、图像识别、深度学习、机器人](http://liuxiao.org/category/robots/) [漫谈 SLAM 技术(上)](https://cloud.tencent.com/developer/article/1005894) @@ -104,7 +113,6 @@ [Kalibr calibration toolbox 标定多目相机系统、相机 IMU 相 对 位 姿 和 卷 帘 快 门 相 机 ](https://github.com/Ewenwan/kalibr) - [霍夫森林(Hough Forest) 随机森林和霍夫投票在计算机视觉中的应用,可以用在物体检测,跟踪和动作识别](https://github.com/Ewenwan/HoughForest) [百度自动驾驶开源框架 apollo](https://github.com/Ewenwan/apollo) @@ -113,6 +121,14 @@ [Halcon 使用参考](https://blog.csdn.net/maweifei/article/details/52613392) +[有代码的论文](https://github.com/Ewenwan/pwc) + +[图像处理基本算法代码](http://www.cnblogs.com/Imageshop/p/3430742.html) + +# 感谢支持 + +![](https://github.com/Ewenwan/EwenWan/blob/master/zf.jpg) + # 无人驾驶的各个方面知识 [参考](https://blog.csdn.net/qq_40027052/article/details/78485120) @@ -323,68 +339,13 @@ ## 公司 [视觉领域的部分国内公司](http://www.ipcv.org/cvcom/) ### 初创公司: -[图普科技](http://www.tuputech.com/) - -[Face++](http://www.faceplusplus.com.cn/) - -[Linkface](http://www.linkface.cn/index.html) - -[Minieye](http://www.minieye.cc/cn/) - -[知图Cogtu](http://www.cogtu.com/?lang=zh) - -[商汤科技Sensetime](http://www.sensetime.com/cn) - -[亮风台Hiscene](http://www.hiscene.com/) - -[掌赢科技](http://www.zhangying.mobi/index.html) - -[格灵深瞳DeepPG](http://www.deepglint.com/) - -[凌感科技usens](http://www.lagou.com/gongsi/j114187.html) - -[图森TuSimple](http://www.tusimple.com/) - -[中科视拓Seetatech(山世光)](http://www.seetatech.com/) - -[第四范式](https://www.4paradigm.com/product/prophet) +[图普科技](http://www.tuputech.com/)---[Face++](http://www.faceplusplus.com.cn/)---[Linkface](http://www.linkface.cn/index.html)---[Minieye](http://www.minieye.cc/cn/)---[知图Cogtu](http://www.cogtu.com/?lang=zh)---[商汤科技Sensetime](http://www.sensetime.com/cn)---[亮风台Hiscene](http://www.hiscene.com/)---[掌赢科技](http://www.zhangying.mobi/index.html)---[格灵深瞳DeepPG](http://www.deepglint.com/)---[凌感科技usens](http://www.lagou.com/gongsi/j114187.html)---[图森TuSimple](http://www.tusimple.com/)---[中科视拓Seetatech(山世光)](http://www.seetatech.com/)---[第四范式](https://www.4paradigm.com/product/prophet) ### 上市公司: - -[百度DL实验室](http://idl.baidu.com/) - -[腾讯优图](http://youtu.qq.com/) - -[阿里高德](http://www.newsmth.net/nForum/#!article/Career_Upgrade/429476) - -[暴风魔镜](http://www.newsmth.net/nForum/#!article/Career_PHD/225254) - -[搜狗](http://www.newsmth.net/nForum/#!article/Career_PHD/224449) - -[乐视tv](http://www.newsmth.net/nForum/#!article/Career_PHD/222651) - -[奇虎360](http://www.newsmth.net/nForum/#!article/Career_PHD/222379) - -[京东实验室](http://www.newsmth.net/nForum/#!article/Career_PHD/223133/a>) - -[阿里巴巴](http://www.newsmth.net/nForum/#!article/Career_PHD/222007) - -[联想研究院](http://www.newsmth.net/nForum/#!article/Career_PHD/220225) - -[华为研究院](http://www.newsmth.net/nForum/#!article/Career_PHD/225976) +[百度DL实验室](http://idl.baidu.com/)---[腾讯优图](http://youtu.qq.com/)---[阿里高德](http://www.newsmth.net/nForum/#!article/Career_Upgrade/429476)---[暴风魔镜](http://www.newsmth.net/nForum/#!article/Career_PHD/225254)---[搜狗](http://www.newsmth.net/nForum/#!article/Career_PHD/224449)---[乐视tv](http://www.newsmth.net/nForum/#!article/Career_PHD/222651)---[奇虎360](http://www.newsmth.net/nForum/#!article/Career_PHD/222379)---[京东实验室](http://www.newsmth.net/nForum/#!article/Career_PHD/223133/a>)---[阿里巴巴](http://www.newsmth.net/nForum/#!article/Career_PHD/222007)---[联想研究院](http://www.newsmth.net/nForum/#!article/Career_PHD/220225)---[华为研究院](http://www.newsmth.net/nForum/#!article/Career_PHD/225976) ### 知名外企: -[佳能信息](http://www.newsmth.net/nForum/#!article/Career_PHD/222548) - -[索尼研究院](http://www.newsmth.net/nForum/#!article/Career_PHD/223437) - -[富士通研发中心](http://www.newsmth.net/nForum/#!article/Career_PHD/220654) - -[微软研究院](https://careers.microsoft.com/?rg=cn) - -[英特尔研究院](http://www.newsmth.net/nForum/#!article/Career_PHD/221175) - -[三星研究院](http://www.yingjiesheng.com/job-001-742-124.html) +[佳能信息](http://www.newsmth.net/nForum/#!article/Career_PHD/222548)---[索尼研究院](http://www.newsmth.net/nForum/#!article/Career_PHD/223437)---[富士通研发中心](http://www.newsmth.net/nForum/#!article/Career_PHD/220654)---[微软研究院](https://careers.microsoft.com/?rg=cn)---[英特尔研究院](http://www.newsmth.net/nForum/#!article/Career_PHD/221175)---[三星研究院](http://www.yingjiesheng.com/job-001-742-124.html) @@ -452,7 +413,6 @@ [Self-augmented Convolutional Neural Networks](https://github.com/msraig/self-augmented-net) - [运动估计 motion estimation](http://www.ipcv.org/on-motion-estimation/) [面部变形 face morphing ](http://www.ipcv.org/about-face-morphing/) diff --git a/Speech/readme.md b/Speech/readme.md index fd02e8e8..d171db5f 100644 --- a/Speech/readme.md +++ b/Speech/readme.md @@ -1,16 +1,70 @@ + # Speech Automatic Speech Recognition,(ASR) + +语音识别,通俗来讲,就是将一段语音信号转换成对应的文本信息。具体来说,语音识别是从一段连续声波中采样,将每个采样值量化;然后对量化的采样音频进行分帧,对于每一帧,抽取出一个描述频谱内容的特征向量;最后根据语音信号的特征识别语音所代表的单词。 + 包含: 语言识别ASR 语义理解ALU 文字转语言TTS - 文字识别ocr 等 + 文字识别ocr + 声纹识别 VPR + 回声消除 AEC/AES +[语音识别 RNN LSTM HMM GMM CTC The official repository of the Eesen project](https://github.com/Ewenwan/eesen) + +[声纹识别发展综述](https://zhuanlan.zhihu.com/p/67563275) + +## 回声消除 AEC/AES + +Android 和 WebRTC 里应该都有相应的模块。 + +回声消除指的是 AEC/AES,在手机上用于消除手机 MIC 录进手机扬声器的对方通话声音,避免对方在通话时听到自己的声音,不是指 dereverberation(去混响)。 + +自适应回声消除器 + +回声是由于扬声器放出来的声音经过衰减和延时然后又被麦克风收录产生的。自适应回声消除器简单说就是用一个参数可调的滤波器,通过一个自适应算法,模拟回声产生的信道环境,进而“猜测”回声信号,然后在麦克风收录的信号里“减去”这个信号。 + +回声消除的效果和采用的算法有关,一般有LMS,NLMS,RLS,APA算法等等,算法太复杂,就不多讲了。。。 + +从上面的描述你应该可以看出来,你的声音是在对方设备上产生的回声,所以你的声音的回声是在对方设备上消除的,同理,对方声音得回声在你的设备上消除 + +[即时语音(如:YY语音)中回声消除技术是如何实现的?](https://www.zhihu.com/question/21406954/answer/5072738420 + +从通讯回音产生的原因看,可以分为声学回音(Acoustic Echo 如上图)和线路回音(Line Echo),相应的回声消除技术就叫声学回声消除(Acoustic Echo Cancellation,AEC)和线路回声消除(Line Echo Cancellation, LEC)。声学回音是由于在免提或者会议应用中,扬声器的声音多次反馈到麦克风引起的(比较好理解);线路回音是由于物理电子线路的二四线匹配耦合引起的(一般硬件厂商来保证,不做具体阐述)。 + +在发送时,把不需要的回音从语音流中间去掉。 + +算法只获取麦克风采集的混合信号是无法做回声消除的,因为算法并不清楚混合的信号里面哪些部分是回声哪些是本端的人说的话。但是回声其实播放的声音经过空间的墙面,地面,桌面反射回麦克风的信号,而播放的信号SDK其实是可以获取的,这就有了参考信号帮助算法来确定哪些是回声哪些是本端声音。 + +尽管回声消除是非常复杂的技术,但我们可以简单的描述这种处理方法: + + 1、假设设备播放的声音是Y,经过空间反射产生的回声是Y',近端说话的声音是X,那么麦克风采集的信号就是 X+ Y'。 + 2、AEC 算法的输入需要 麦克风的信号(X+ Y')以及播放的声音Y,理想的输出是X。 + 3、算法的过程可以简单理解成用滤波器去模拟空间的反射变化,假设滤波器是f,那么就是希望f(Y) = Y'。这样我们就得到了Y'再在输入信号里面去掉。 + 4、上述是理想情况,实际情况是空间反射,以及采集播放的性能决定Y到Y'基本都是非线性的变化,然而因为计算量的限制,一般的实时系统都是使用的线性的滤波器,所以滤波器即使处在最理想的情况下也只能处理线性部分,对于非线性部分(很多情况下非线性回声是主要部分)还要有非线性的处理Nonlinear Process。 + 5、又因为回声的反射路径随着空间环境的变化随时都会变化,一般滤波器会设计成自适应的去跟踪环境回声路径的变化。 + + ## 语言识别ASR ![](http://antkillerfarm.github.io/images/img2/speech.png) ![](http://antkillerfarm.github.io/images/img2/speech_2.png) +语音识别的整个流程,主要包含特征提取和解码(声学模型、字典、语言模型)部分。 + +1. 特征提取:从语音波形中提取出随时间变化的语音特征序列(即将声音信号从时域转换到频域),为声学模型提供合适的特征向量。主要算法有线性预测倒谱系数(LPCC)和梅尔频率倒谱系数(MFCC)。 + +2. 声学模型:根据声学特性计算每一个特征向量在声学特征上的得分,输入是特征向量,输出为音素信息。最常用的声学建模方式是隐马尔科夫模型(HMM),基于深度学习的发展,深度神经网络(DNN)、卷积神经网络(CNN)、循环神经网络(RNN)等模型在观测概率的建模中取得了非常好的效果。 + +在语音识别整个流程中,声学模型作为识别系统的底层模型,声学模型的任务是计算 P(O|W),(即模型生成观察序列的概率),它占据着语音识别大部分的计算开销,决定着语音识别系统的性能。所以,声学模型是语音识别系统中最关键的一部分。 + +3. 字典:字或者词与音素的对应,中文就是拼音和汉字的对应,英文就是音标与单词的对应。(音素,单词的发音由音素构成。对英语来说,一种常用的音素集是卡内基梅隆大学的一套由 39 个音素构成的音素集,汉语一般直接用全部声母和韵母作为音素集)。 + +4. 语言模型:通过对大量文本信息进行训练,得到单个字或者词相互关联的概率。语音识别中,最常见的语言模型是 N-Gram。近年,深度神经网络的建模方式也被应用到语言模型中,比如基于 CNN 及 RNN 的语言模型。 + +5. 解码:通过声学模型、字典、语言模型对提取特征后的音频数据进行文字输出。 [语音识别(一)——概述 HMM -> GMM -> 深度学习RNN HTK CMU-Sphinx SPTK ](http://antkillerfarm.github.io/graphics/2018/04/16/speech.html) @@ -25,7 +79,104 @@ [中文分词!!!!!!!](https://github.com/Ewenwan/cppjieba) +[阿里巴巴的 DFSMN 声学模型 基于 开源的语音识别工具 Kaldi DFSMN 是 Kaldi 的一个补丁文件,所以,为了使用 DFSMN 模型,我们必须先部署 Kaldi 语音识别工具 ]() + +### DFSMN && Kaldi + +[参考](https://www.zhihu.com/search?type=content&q=%E8%AF%AD%E9%9F%B3%E8%AF%86%E5%88%AB%E6%A8%A1%E5%9E%8B%20DFSMN) + +目前主流的语音识别系统普遍采用基于深度神经网络和隐马尔可夫(Deep Neural Networks-Hidden Markov Model,DNN-HMM)的声学模型. + +声学模型的输入是传统的语音波形经过加窗、分帧,然后提取出来的频谱特征,如 PLP, MFCC 和 FBK等。而模型的输出一般采用不同粒度的声学建模单元,例如单音素 (mono-phone)、单音素状态、绑定的音素状态 (tri-phonestate) 等。从输入到输出之间可以采用不同的神经网络结构,将输入的声学特征映射得到不同输出建模单元的后验概率,然后再结合HMM进行解码得到最终的识别结果。 + +最早采用的网络结构是前馈全连接神经网路(Feedforward Fully-connected Neural Networks, FNN)。FNN实现固定输入到固定输出的一对一映射,其存在的缺陷是没法有效利用语音信号内在的长时相关性信息。一种改进的方案是采用基于长短时记忆单元(Long-Short Term Memory,LSTM)的循环神经网络(Recurrent Neural Networks,RNN)。LSTM-RNN通过隐层的循环反馈连接,可以将历史信息存储在隐层的节点中,从而可以有效地利用语音信号的长时相关性。 + +进一步地通过使用双向循环神经网络(BidirectionalRNN),可以有效地利用语音信号历史以及未来的信息,更有利于语音的声学建模。基于循环神经网络的语音声学模型相比于前馈全连接神经网络可以获得显著的性能提升。但是循环神经网络相比于前馈全连接神经网络模型更加复杂,往往包含更多的参数,这会导致模型的训练以及测试都需要更多的计算资源。 +另外基于双向循环神经网络的语音声学模型,会面临很大的时延问题,对于实时的语音识别任务不适用。现有的一些改进的模型,例如,基于时延可控的双向长短时记忆单元(Latency Controlled LSTM,LCBLSTM )[1-2],以及前馈序列记忆神经网络(Feedforward SequentialMemory Networks,FSMN)[3-5]。 + +FSMN是近期被提出的一种网络结构,通过在FNN的隐层添加一些可学习的记忆模块,从而可以有效地对语音的长时相关性进行建模。FSMN相比于LCBLSTM不仅可以更加方便地控制时延,而且也能获得更好的性能,需要的计算资源也更少。但是标准的FSMN很难训练非常深的结构,会由于梯度消失问题导致训练效果不好。而深层结构的模型目前在很多领域被证明具有更强的建模能力。因而针对此我们提出了一种改进的FSMN模型,称之为深层的FSMN(DeepFSMN, DFSMN)。进一步地我们结合LFR(lowframe rate)技术构建了一种高效的实时语音识别声学模型,相比于去年我们上线的LCBLSTM声学模型可以获得超过20%的相对性能提升,同时可以获得2-3倍的训练以及解码的加速,可以显著地减少我们的系统实际应用时所需要的计算资源。 + + +DFSMN 特点:跳层连接,更深的层数。和LFR结合。模型尺寸更小,低延迟。 +实验结果表明DFSMN是用于声学模型的BLSTM强有力替代方案。 + +[参考](https://blog.csdn.net/zhanaolu4821/article/details/88977782) + +Kaldi 是一个开源的语音识别工具库,隶属于 Apache 基金会,主要由 Daniel Povey 开发和维护。Kaldi 内置功能强大,支持 GMM-HMM、SGMM-HMM、DNN-HMM 等多种语音识别模型的训练和预测。随着深度学习的影响越来越大,Kaldi 目前对 DNN、CNN、LSTM 以及 Bidirectional-LSTM 等神经网络结构均提供模型训练支持。 + +[ Kaldi ](https://github.com/kaldi-asr/kaldi) + +[ DFSMN ](https://github.com/alibaba/Alibaba-MIT-Speech) + +配置: + +git clone https://github.com/kaldi-asr/kaldi.git kaldi-trunk --origin golden + + +cd kaldi-trunk/ && git clone https://github.com/alibaba/Alibaba-MIT-Speech + +将补丁加载到 Kaldi 分支 git apply --stat Alibaba-MIT-Speech/Alibaba_MIT_Speech_DFSMN.patch + +测试补丁:git apply --check Alibaba-MIT-Speech/Alibaba_MIT_Speech_DFSMN.patch + +添加 Git 账户邮箱和用户名,否则无法应用补丁。 + + git config --global user.email "userEmail" + git config --global user.name "username" + +应用补丁:git am --signoff < Alibaba-MIT-Speech/Alibaba_MIT_Speech_DFSMN.patch + +> 安装 Kaldi + +切换到 tools 目录中,自动检测并安装缺少的依赖包,直到出现 all OK 为止。 + +extras/check_dependencies.sh + +编译:make -j6 编译 –j 参数表示内核数,根据自己环境设定运用多少内核工作。 + +切换到 src 目录下,进行安装。 + + cd ../src + ./configure –shared + make depend -j6 + +自动安装其它扩展包,执行以下命令:make ext + +运行自带的 demo: + + cd ../egs/yesno/s5/ + ./run.sh +### 语音特征提取 MFCC +MFCC(MeI-Freguency CeptraI Coefficients)是语音特征参数提取方法之一,因其独特的基于倒谱的提取方式,更加符合人类的听觉原理,因而也是最为普遍、最有效的语音特征提取算法。通过 MFCC,我们可以有效地区分出不同的人声,识别不同的说话人。 + + 预加重 --> 分帧 --> 加窗 --> FFT 离散傅立叶变换(DFT) --> Mel滤波数组 --> 对数运算 --> DCT + + 1. 预加重其实就是将语音信号通过一个高通滤波器,来增强语音信号中的高频部分,并保持在低频到高频的整个频段中,能够使用同样的信噪比求频谱。 + + 2. 分帧是指在给定的音频样本文件中,按照某一个固定的时间长度分割,分割后的每一片样本,称之为一帧。 + + 分帧是先将 N 个采样点集合成一个观测单位,也就是分割后的帧。通常情况下 N 的取值为 512 或 256,涵盖的时间约为 20~30ms。N 值和窗口间隔可动态调整。为避免相邻两帧的变化过大,会让两相邻帧之间有一段重叠区域,此重叠区域包含了 M 个取样点,一般 M 的值约为 N 的 1/2 或 1/3。 +语音识别中所采用的信号采样频率一般为 8kHz 或 16kHz。以 8kHz 来说,若帧长度为 256 个采样点,则对应的时间长度是 256/8000*1000=32ms。本次测试中所使用的采样率为 16kHz,窗长 37.5ms(600 个采样点),窗间隔为 10ms(160 个采样点)。 + + 3. 加窗,在对音频进行分帧之后,需要对每一帧进行加窗,以增加帧左端和右端的连续性,减少频谱泄漏。比较常用的窗口函数为 Hamming 窗。 + + 4. 离散傅立叶变换(DFT) + + 由于信号在时域上的变换通常很难看出信号的特性,所以通常将它转换为频域上的能量分布来观察,不同的能量分布,代表不同语音的特性。所以在进行了加窗处理后,还需要再经过离散傅里叶变换以得到频谱上的能量分布。对分帧加窗后的各帧信号进行快速傅里叶变换 FFT 得到各帧的频谱。并对语音信号的频谱取模平方得到语音信号的功率谱。 + + 5. Mel 滤波器组 + + MFCC 考虑人类的听觉特征,先将线性频谱映射到基于听觉感知的 Mel 非线性频谱中,然后转换到倒谱上。在 Mel 频域内,人对音调的感知度为线性关系。举例来说,如果两段语音的 Mel 频率相差两倍,则人耳听起来两者的音调也相差两倍。Mel 滤波器的本质其实是一个尺度规则:通常是将能量通过一组 Mel 尺度的三角形滤波器组,如定义有 MM 个滤波器的滤波器组,采用的滤波器为三角滤波器,中心频率为 f(m),m=1,2…Mf(m),m=1,2…M,MM 通常取 22~26。f(m)f(m)之间的间隔随着 mm 值的减小而缩小,随着 mm 值的增大而增宽. + + 6. 对频谱进行离散余弦变换(DCT) + +使⽤离散余弦变换,进⾏⼀个傅⽴叶变换的逆变换,得到倒谱系数。 由此可以得到 26 个倒谱系数。只取其 [2:13] 个系数,第 1 个用能量的对数替代,这 13 个值即为所需的 13 个 MFCC 倒谱系数。 + + 动态差分参数的提取(包括一阶差分和二阶差分 + +标准的倒谱参数 MFCC 只反映了语音参数的静态特性,语音的动态特性可以用这些静态特征的差分谱来描述。实验证明:把动、静态特征结合起来才能有效提高系统的识别性能。 + ### CTC(Connectionist Temporal Classifier) 一般译为联结主义时间分类器 , 适合于输入特征和输出标签之间对齐关系不确定的时间序列问题, @@ -42,3 +193,29 @@ [科大讯飞 TTS](https://github.com/Ewenwan/Ros/blob/master/src/voice_system/src/xf_tts.cpp) ## 文字识别ocr 其实属于图像识别问题了 +* CRNN +[An End-to-End Trainable Neural Network for Image-based Sequence Recognition and Its Application to Scene Text Recognition](https://arxiv.org/abs/1507.05717) +[中文版](http://noahsnail.com/2017/08/21/2017-8-21-CRNN%E8%AE%BA%E6%96%87%E7%BF%BB%E8%AF%91%E2%80%94%E2%80%94%E4%B8%AD%E6%96%87%E7%89%88/) +[中英文对照](http://noahsnail.com/2017/08/21/2017-8-21-CRNN%E8%AE%BA%E6%96%87%E7%BF%BB%E8%AF%91%E2%80%94%E2%80%94%E4%B8%AD%E8%8B%B1%E6%96%87%E5%AF%B9%E7%85%A7/) + +[ocn代码示例](https://github.com/fengbingchun/OCR_Test) + +[Use CTC + tensorflow to OCR ](https://github.com/ilovin/lstm_ctc_ocr) + +* CTPN +[Detecting Text in Natural Image with Connectionist Text Proposal Network](https://arxiv.org/abs/1609.03605) +[中文版](http://noahsnail.com/2018/02/02/2018-02-02-Detecting%20Text%20in%20Natural%20Image%20with%20Connectionist%20Text%20Proposal%20Network%E8%AE%BA%E6%96%87%E7%BF%BB%E8%AF%91%E2%80%94%E2%80%94%E4%B8%AD%E6%96%87%E7%89%88/) +[中英文对照](http://noahsnail.com/2018/02/02/2018-02-02-Detecting%20Text%20in%20Natural%20Image%20with%20Connectionist%20Text%20Proposal%20Network%E8%AE%BA%E6%96%87%E7%BF%BB%E8%AF%91%E2%80%94%E2%80%94%E4%B8%AD%E8%8B%B1%E6%96%87%E5%AF%B9%E7%85%A7/) + +## 自然语言处理 +[自然语言处理算法与实战](https://github.com/Ewenwan/learning-nlp) + + chapter-3 中文分词技术 + chapter-4 词性标注与命名实体识别 + chapter-5 关键词提取 + chapter-6 句法分析 + chapter-7 文本向量化 + chapter-8 情感分析 + chapter-9 NLP中用到的机器学习算法 + chapter-10 基于深度学习的NLP算法 + diff --git a/UMCar/ADAS/readme.md b/UMCar/ADAS/readme.md new file mode 100644 index 00000000..03993763 --- /dev/null +++ b/UMCar/ADAS/readme.md @@ -0,0 +1,178 @@ +# 高级驾驶辅助系统 Advanced Driving Assistance system + +[ADAS芯片解决方案汇总 ](https://www.cnblogs.com/shaobojiao/p/8274481.html) + +ADAS(高级辅助驾驶系统),是指利用安装于车上各式各样的传感器,在第一时间收集车内的环境数据,进行静、动态物体的辨识、侦测与追踪等技术上的处理,从而能够让驾驶者在最快的时间察觉可能发生的危险。 + +在过去的两年多时间,笔者拜访了数百家企业,最近一直花时间在做针对性地梳理和总结。在现在的电子信息领域,跨界融合的节奏越来越快,产业链各环节的衔接也是前所未有的紧密,所以现在看一个领域或一个项目,需要从整个产业链条各环节去综合考虑,包括云管端,包括硬件、软件、算法、数据,且各产业链条上各家企业,随时做前向或后向的整合,竞合关系随时转换。随着新硬件时代的来临,对产业的研究提出了更高的要求,思考的纬度需要变得更宽,要理清里面错综复杂的关系以及未来的发展趋势,工作量数倍于从前。 + +而对产业链各个环节标杆企业的研究是必备的功课,只有了解这些大企业的策略和动向,才能发现其中可能存在的创业/投资机会。所以最近有意识的对大企业做一点研究,如之前的音频、视觉、IOT平台等,以及本篇的主要针对ADAS的芯片厂商,理解各家的主要产品线和状态。 + +通常包括导航与实时交通系统TMC,电子警察系统ISA 、自适应巡航ACC 、车道偏移报警系统LDWS、车道保持系统,碰撞避免或预碰撞系统、夜视系统、自适应灯光控制、行人保护系统、自动泊车系统、交通标志识别、盲点探测,驾驶员疲劳探测、下坡控制系统和电动汽车报警系统等。 + +目前来看汽车的创新绝大部分来自于汽车电子的创新,而从汽车电子系统来讲,正在由分散式架构(众多的ECU控制),逐渐向集中式乃至中央控制系统(超级处理器)演进,这一趋势落实到ADAS上也是同样规律。这一趋势的变化,包括减少ECU,降低功耗,提高处理器和内存利用效率,降低软件的开发难度和提高安全,使汽车半导体厂商在整个汽车产业中扮演越来越重要的角色。同时,对ADAS处理器芯片来说,目前呈现出如智能家居类似的产品形态,单品爆款,以及多功能的组合,即类似于Mobileye的视觉处理ADAS芯片单品,以及多传感器的融合,使ADAS处理芯片成为平台的趋势。目前来看这两种形态都有市场,单功能会使ADAS在中低端车甚至后装市场,更大范围的普及,当然性价比是前提。而多传感器的融合会提升自动驾驶的等级向Level4甚至Level5方向走,目前像Google、百度等无人车都在做多传感器的融合,只是目前为止还没有专门的Level4/5ADAS ASIC芯片而已。 + +从芯片设计来说,现在ADAS处理器芯片的主要挑战在如下几个方面: + +1)车规级的标准,最好过ISO26262,达到ASIL-B甚至ASIL-D级别 + +2)高计算量以及高带宽,特别是多传感器融合的芯片,需要更高的芯片频率,以及异构设计,以达到快速的数据处理速度,同时传输的吞吐率上也有较高要求。 + +3)随着人工智能在ADAS上的应用,针对芯片的设计会考虑增加硬件的深度学习设计,如何在软硬件上做取舍,以及人工智能计算模型与原有软硬件架构以及整个系统设计上做匹配,目前来看还在早期探索阶段。 + +下面主要介绍各家主要ADAS处理器芯片厂商的产品,希望从他们的产品中一窥现在ADAS处理器芯片领域的现状,以及未来的发展趋势。 + + +> **场景:** + +高速道路:前视摄像头 检测前方车辆 利用目标检测(车道线、车辆)、目标跟踪(车辆)、目标分割(车道),判断车辆速度、车辆位置,完成车道保持、车道偏离预警、换道、自动刹车等。 + +城市道路: 激光雷达,摄像头,识别行人、车辆、斑马线、红路灯、障碍物等,完成辅助驾驶员行驶 + +停车,自动泊车,自动倒车入库、侧方停车等。 + +传感器: 激光雷达、毫米波雷达、超声测距、摄像头、GPS、IMU等 + +执行器: 电控执行器,刹车brake、离合gearbox、转向sterring、油门engine、车灯(转向灯、远光灯、近光灯) + +车内: 人机交互,控制面板、仪表盘、HUD抬头显示、可震动的方向盘、可收紧的安全带、可声光提醒的仪表符号。 + +车内面向驾驶员的摄像头: 驾驶员安全行为检测,安全带检测、打电话、玩手机、抽烟、眼睛疲劳、人脸识别(身份验证)等 + + +L0 L1 L2 属于ADAS + +L3 L4 L5 自动驾驶 AD Autonous Drining + + +L0 : + +LDW : Lane departure warning 车道偏离预警 + +FCW : Forward collision warning 前车碰撞预警 + +TSR : Traffic sign resognition 交通标志识别 限速识别 + +AVS : Aided Video System 辅助视频系统 + +LCA : Lane Change Assist 辅助变道 + +AHBA: 自动远近光灯切换 + +IHC 智能大灯控制 + +NV Night Viision 夜视 + +BSD Bind spot detect 盲点检测 + + + +L1: + +LKA : lane keep assist 车道保持 + +AEB : aUTO emergency Braking 自动紧急刹车 + +ACC : Adaptive Cruise Control 自适应巡航 + +L2: + +LKA : lane keep assist 车道保持 + +APA : Parking 自动泊车辅助 + + + + + +# ADAS FCW 前车碰撞预警 + +# ADAS AEB 自动紧急刹车 + +# ADAS LDW 车道偏离预警 + +# 定速巡航控制软件开发 ACC : Adaptive Cruise Control 自适应巡航 + +# ADAS LCA Lane Change Assist 辅助变道 + +# 自动驾驶基础--路径搜索算法Dijkstra + +# 自动驾驶基础--路径规划算法A* + +# 自动驾驶基础--动态路径规划算法 + +# 自动驾驶路径规划--车辆防碰撞问题 + +# AD路径跟踪算法 + +# ADAS功能软件开发_BSD + + + +## 芯片 + +高通/NXP + +由于高通已经收购NXP,所以在这里一起介绍。高通自己主要通过自己的移动处理器芯片(改成车规级),开始逐步切入ADAS,当然刚开始做环视等,最近有和纵目合作,在CES上推出首个基于骁龙820A平台并运用深度学习的最新ADAS产品原型,该产品运行了820A神经网络处理引擎(SNPE),能实现对车辆、行人、自行车等多类物体识别,以及对像素级别可行驶区域的实时语义分割,当然离商用应该还有一定距离。总的来说,高通骁龙产品策略应该还是以车载娱乐信息系统为主,逐步向更专业的ADAS拓展。 + +同时,NXP以及之前NXP收购的飞思卡尔,在汽车电子和ADAS芯片领域都有完整的产品线布局。 + +NXP已经发布Blubox平台,为OEM厂商提供设计、制造、销售Level 4级(SAE)无人驾驶汽车的解决方案计算平台。下图是NXP的ADAS系统框图,该系统对多路视频、77G雷达的数据进行融合处理,然后传送给云端和车身系统。我们看到NXP是能够提供全套Reference方案的公司,在这一块的产品线很全,虽然现在没有做更多的芯片集成,而是提供相对分散的芯片及解决方案。我们这里重点介绍一下中央处理器S32V234和MPC5775K,MPC5775K是对雷达数据进行处理,而S32V234是对多传感器处理过的数据进行融合分析,通过CAN总线,把结果传给车身系统。 + +S32V234是NXP的S32V系列产品中2015年推出的ADAS处理器,支持CPU(4颗ARM V8架构A53和M4)、GPU(GC3000)和图像识别处理(CogniVue APEX2 processors)的异构计算,5W的低功耗设计。通过CogniVue APEX2 processors能同时支持四路汽车摄像头(前、后、左、右),抽取图像并分类,同时GPU能实时3D建模,计算量达到50 GFLOPs。所以按照此硬件架构可完成360度环视,完成自动泊车等功能。同时,该芯片预留了支持毫米波雷达、激光雷达、超声波的接口,便于实现多传感器的融合,该芯片支持ISO 26262 ASIL B标准。 + +Qorivva MPC567xK系列基于Power Architecture 的32位MCU,MPC577XK是专门的雷达信息处理芯片,该系列增加了芯片的存储器,提升了运行速度和性能,能够支持自适应巡航控制、智能大灯控制、车道偏离警告和盲点探测等应用。从整个雷达系统来看,结合77G雷达收发器芯片组、Qorivva MPC567xK MCU、FPGA, ADC, DAC, SRAM, 支持长、中、短距离应用。这里需要重点关注的是信号处理工具集(Signal Processing Toolbox)设计,包括了FFT、DMA、COPY、Scheduler。目前77GHz的FCMW型雷达在数字信号处理中需要使用FFT,即快速傅里叶变换,一般车载雷达的采样点在512-2048左右,从芯片架构图我们看到专门的FFT电路。 + +除了S32V系列,被收购的飞思卡尔有一款著名的i.MX系列芯片也可以作为中央处理器。i.MX特别是i.MX6在汽车上,特别是车载信息系统上有大量的应用。众多的汽车厂商使用i.MX。 + + +英特尔/Mobileye/Altera + +通过一系列的收购,英特尔在ADAS处理器上的布局已经完善,包括Mobileye的ADAS视觉处理,利用Altera的FPGA处理,以及英特尔自身的至强等型号的处理器,可以形成自动驾驶整个硬件超级中央控制的解决方案。 + +其中特别要指出的是Mobileye的EyeQ系列,已经被多家汽车制造商使用,包括奥迪、宝马、菲亚特、福特、通用、本田、日产、标致、雪铁龙、雷诺、沃尔沃和特斯拉等在内。最近的EyeQ4展示的性能已经达到2.5万亿次每秒的性能,其运行功率可低至3W。从硬件架构来看,该芯片包括了一组工作在1 GHZ的工业级四核MIPS处理器,以支持创新性的多线程技术能更好的进行数据的控制和管理。多个专用的向量微码处理器(VMP),用来应对ADAS相关的图像处理任务(如:缩放和预处理、翘曲、跟踪、车道标记检测、道路几何检测、滤波和直方图等)。一颗军工级MIPS Warrior CPU位于次级传输管理中心,用于处理片内片外的通用数据。 + +由于目前融合多是雷达与摄像头融合,所需要的带宽,一般的ASIC都能够满足。但是要融合激光雷达,则最好用FPGA,FPGA做传感器Hub是最合适不过的。同时传感器融合目前应用较少,合适的ASIC并不好找,FPGA成为主流选择。同时,对一些精度要求较高的雷达,如使用单精度浮点处理实现一个4096点FFT,采样点越多,误差就越小,但运算量会大幅度增加。它在每个时钟周期输入输出四个复数采样。每个FFT内核运行速度超过80 GFLOPs,这一般需要FPGA才能比较好的实现。一般车载雷达的采样点在512-2048左右,但军用的可以达到8192,必须配备FPGA。如下图在AudizFAS的实物中,采用了Altera的CycloneV SoCFPGA,作为sensor fusion,同时负责毫米波雷达与激光雷达数据处理。 + + +瑞萨(Renesas) + +瑞萨针对ADAS处理器这一块业务,提供了较完整的产品线系列,也提供ADAS Kit开发系统。就芯片系列来说,最出名的莫过于其R-Car产品线,该系列高配产品的硬件架构包括了ARM Cortex A57/53、ARM Cortex R系列、Video Codec,2D/3DGPU、ISP等,能同时支持多路的视觉传感器输入,支持OPENGL、OpenCV等软件,符合ASILB车规级别。其实该产品最早是用于车载信息娱乐系统,而后该系统产品逐步适配汽车环视视觉系统、仪表板及ADAS系统等,该发展路径值得国内想进去汽车领域的半导体厂商借鉴。 + +除了R-Car系列产品外,就像NXP一样,瑞萨也有针对雷达传感器的专业处理器芯片如RH850/V1R-M系列,该产品采用40nm内嵌eFlash技术,优化的DSP能快速的进行FFT的处理。 + +最近有报道说瑞萨发布了Renesas Autonomy,一个全新设计的ADAS和自动驾驶平台。具体细节还不清楚,但是据瑞萨电子美国区汽车业务副总裁Amrit Vivekanand指出,瑞萨此次推出的自动驾驶平台与竞争对手不同,“这是一个开放的平台,希望用户更方便地将他们的算法、函数库和实时操作系统(RTOS)移植到平台中来。” Renesas Autonomy平台发布的第一个产品,是一块图像识别片上系统(SoC),叫作R-Car V3M。瑞萨将该高性能视觉处理芯片描述为“优化处理单元,首选应用于智能相机传感器,也可以用于环绕视觉系统甚至激光雷达的数据处理。”来自半导体行业分析公司Linley Group的高级分析师Mike Demler认为,此次发布的开放平台和产品,可以看作一种瑞萨电子对标Mobileye的布局,“他们希望吸引到没有与Mobileye合作的汽车制造商,尤其是日本厂商,也希望吸引到一些制造ADAS产品的Tier 1厂商。 ”相比于Mobileye处理平台的“黑箱”系统,瑞萨在不断强调解决方案的“开放”二字,这也是每个誓要抗衡Mobileye的处理器厂商都倾向于谈论的问题。瑞萨方面表示,其最新发布的R-Car V3M处理模块的全部算法将对其用户开放。 + + +英飞凌(Infineon) + +作为汽车电子、功率半导体以及智能卡芯片的全球市场领袖,英飞凌一直以来为汽车等工业应用提供半导体和系统解决方案。英飞凌在24/77/79G雷达、激光雷达等传感器器件及处理芯片方面都具有领先的技术。除此之外,在车身控制、安全气囊、EPS、TPMS等等各方面都有自己的解决方案。 + + +德州仪器(TI) + +TI在ADAS处理器上实际上是走得两条产品线,Jacinto和TDA系列。Jacinto系列主要是基于之前的OMAP处理器开发而来,TI在放弃移动处理器平台后,将数字处理器的重点放在了汽车等应用上,主要是车载信息娱乐系统。但是从Jacinto6中,我们看到车载信息娱乐与ADAS功能的结合,这款芯片包括了双ARM Cortex-A15内核、两个ARM M4内核、两个C66x浮点DSP、多个3D/2D图形处理器GPU(Imagination),并且还内置了两个EVE加速器。这款Jacintinto6 SoC处理器的功能异常强大,无论是在处理娱乐影音方面,还是车载摄像头的辅助驾驶,可利用汽车内部和外部的摄像头来呈现如物体和行人检测、增强的现实导航和驾驶员身份识别等多种功能。 + +TDA系列一直是侧重于ADAS功能,TDA3x系列可支持车道线辅助、自适应巡航控制、交通标志识别、行人与物体检测、前方防碰撞预警和倒车防碰撞预警等多种ADAS算法。这些算法对于前置摄像头、全车环视、融合、雷达与智能后置摄像头等众多ADAS应用的有效使用至关重要。 + + +英伟达(NVIDIA) + +随着人工智能和无人驾驶技术的兴起,由于NVIDIA的GPU极强的并行计算能力,特别适合做深度学习。一般认为相对于Mobileye只专注于视觉处理,NVIDIA的方案重点在于融合不同传感器,据传特斯拉已经放弃Mobileye,而采用NVIDIA。 + +NVIDIA推出的Drive PX2被黄仁勋称为“为汽车设计的超级电脑”,它将成为汽车的标准配备,可以用来感知汽车所处位置、辨识汽车周遭的物体,并且即时计算最安全的路径。“Tegra X1处理器和10GB内存,能够同时处理12个200万像素摄像头每秒60帧的拍摄图像,并通过环境视觉计算技术和强大的深层神经网络,主动识别道路上的各种车辆,甚至还能检测前方车辆是否在开门。Driver PX2还搭载了其他合作伙伴的芯片,包括Avago的PEX8724(24-lane,6-port,第三代 PCIe Gen交换机)用于两块Parker之间的互联。还有一片英特尔收购的Altera提供的FPGA,用于执行实时操作系统。FPGA的型号为Cyclone V 5SCXC6,是Altera的顶级产品,逻辑运算为110K,注册器达166036。最后还有一款英飞凌的AURIX TC 297 MCU做安全控制,据说可以让PX2达到ASIL C级水平。 还有博通的BCM89811低功耗物理层收发器(PHY),使用BroadR-Reach车载以太网技术,在单对非屏蔽双绞线上的传输速率可达100Mbps。所以NVidia实际上推出了板级的ADAS系统。 + +ADI + +相对于以上介绍的几家芯片公司,ADI在ADAS芯片上的策略主打性价比。ADAS技术目前基本应用在高端车型中,主要是因为总体成本高,ADI针对高、中、低档汽车,ADI针对性的推出某一项或几项ADAS技术进行实现,并把成本降到2美元、十几美元,对整车厂商及消费者无疑是一大好消息。 + +在视觉ADAS上ADI的Blackfin系列处理器被广泛的采用,其中低端系统基于BF592,实现LDW功能;中端系统基于BF53x/BF54x/BF561,实现LDW/HBLB/TSR等功能;高端系统基于BF60x,采用了“流水线视觉处理器(PVP)“,实现了LDW/HBLB/TSR/FCW/PD等功能。集成的视觉预处理器能够显著减轻处理器的负担,从而降低对处理器的性能要求。 + +值得一提的是,ADI最近推出Drive360TM 28nm CMOS RADAR技术(77/79GHz),将绝佳的RF性能运用于目标识别和分类,革新了ADAS应用的传感器性能。ADI的高性能RADAR解决方案能够提前探测快速移动的小型物体,而极低相位噪声能够在存在大物体的情况下对小物体进行最清楚的检测。ADI与瑞萨合作,共同针对该芯片推出系统性方案,结合ADI的RADAR,以及瑞萨Autonomy平台的RH850/V1R-M微控制器(MCU)。 + + +富士通(Fujitsu) + +富士通的ADAS技术主要涉及透过摄像头和传感器的结合,实现图像识别辅助和接近目标检测,应用的领域主要有360度3D立体全景辅助、可视停车辅助、驾驶盲区监控、安全开车门以及车行驶方向周围的障碍物和行人的识别。包括基于MB86R11“Emerald-L”2D/3D图像SoC的全景视频系统支持前后左右四个摄像头进行汽车周边环境的实时全景视频监测。从公开资料显示,富士通似乎更热衷于虚拟仪表盘及车载信息娱乐系统的构建,但这一块是最容易被国内芯片公司模仿并超越的。 + + diff --git "a/UMCar/Apollo\346\272\220\347\240\201\345\210\206\346\236\220.md" "b/UMCar/Apollo\346\272\220\347\240\201\345\210\206\346\236\220.md" new file mode 100644 index 00000000..dd4bd3ae --- /dev/null +++ "b/UMCar/Apollo\346\272\220\347\240\201\345\210\206\346\236\220.md" @@ -0,0 +1,40 @@ +# Apollo源码分析 +[源码](https://github.com/ApolloAuto/apollo) + +# 框架 + +``` + 地图 MAP (HP MAP 高精度地图) + | | | +目的地 goal -> 导航 routing ---path---> 规划planning ---path---> 感知perception(交通灯/障碍物/) + | | + | <-----------预测(障碍物/交通灯/) + | + 定位localization | + 控制 control + | 控制命令/传感器反馈 + canbus 汽车总线 + + +``` + +# 控制 control 模块 + +介绍 + + 本模块基于规划和当前的汽车状态,使用不同的控制算法来生成舒适的驾驶体验。控制模块可以在正常模式和导航模式下工作。 + +输入 + + 规划轨迹 + 车辆状态 + 定位 + Dreamview自动模式更改请求 + +输出 + + 给底盘的控制指令(转向,节流,刹车)。 + + + + diff --git a/UMCar/img/readme.md b/UMCar/img/readme.md new file mode 100644 index 00000000..33a32a6a --- /dev/null +++ b/UMCar/img/readme.md @@ -0,0 +1 @@ +# 图片 diff --git a/UMCar/img/sdc.PNG b/UMCar/img/sdc.PNG new file mode 100644 index 00000000..b964541e Binary files /dev/null and b/UMCar/img/sdc.PNG differ diff --git a/UMCar/radia/readme.md b/UMCar/radia/readme.md new file mode 100644 index 00000000..ccc751fa --- /dev/null +++ b/UMCar/radia/readme.md @@ -0,0 +1,39 @@ +# 雷达radia + + +## 激光雷达 + +激光雷达,是以发射激光束探测目标的位置、速度等特征量的雷达系统。其工作原理是向目标发射探测信号(激光束),然后将接收到的从目标反射回来的信号(目标回波)与发射信号进行比较,作适当处理后,就可获得目标的有关信息,如目标距离、方位、高度、速度、姿态、甚至形状等参数,从而对飞机、导弹等目标进行探测、跟踪和识别。它由激光发射机、光学接收机、转台和信息处理系统等组成,激光器将电脉冲变成光脉冲发射出去,光接收机再把从目标反射回来的光脉冲还原成电脉冲,送到显示器。 + +无人驾驶技术想要真正上路行驶,最关键的技术难点就在于汽车如何能对现实中复杂的交通状况了如指掌,这样一来就必须使用雷达装置。现阶段主流无人驾驶研发技术中,都选择了激光雷达,而一向“不走寻常路”的马斯克选择使用毫米波雷达。那么,两种类别的雷达技术究竟有什么区别? + + +激光雷达主要是通过发射激光束,来探测目标的位置、速度等特征量。车载激光雷达普遍采用多个激光发射器和接收器,建立三维点云图,从而达到实时环境感知的目的。从当前车载激光雷达来看,机械式的多线束激光雷达是主流方案。激光雷达的优势在于其探测范围更广,探测精度更高。但是,激光雷达的缺点也很明显:在雨雪雾等极端天气下性能较差,采集的数据量过大,价格十分昂贵。目前百度和谷歌无人驾驶汽车车身上的64位激光雷达,售价高达70万元人民币。激光发射器线束的越多,每秒采集的云点就越多,探测性能也就更强。然而线束越多也就代表着激光雷达的造价就更加昂贵,64线束的激光雷达价格是16线束的10倍。   + +作为ADAS不可或缺的核心传感器类型,毫米波雷达从上世纪起就已在高档汽车中使用,技术相对成熟。毫米波的波长介于厘米波和光波之间,因此毫米波兼有微波制导和光电制导的优点,且其引导头具有体积小、质量轻和空间分辨率高的特点。 + +此外,毫米波导引头穿透雾、烟、灰尘的能力强,相比于激光雷达是一大优势。而毫米波雷达的缺点也十分直观,探测距离受到频段损耗的直接制约(想要探测的远,就必须使用高频段雷达),也无法感知行人,并且对周边所有障碍物无法进行精准的建模。受益于技术相对成熟,毫米波雷达在单价方面,只能算是激光雷达的九牛一毛,单体价格大约在100美元左右。并且车载毫米波雷达的市场需求也相对更多,带来的规模效益有望进一步拉低成本。 + + +## 毫米波雷达 +首先我们要明白啥是毫米波,毫米波实质上就是电磁波。毫米波的频段比较特殊,其频率高于无线电,低于可见光和红外线,频率大致范围是10GHz—200GHz。这是一个非常适合车载领域的频段。 + +原理:振荡器会产生一个频率随时间逐渐增加的信号,这个信号遇到障碍物之后,会反弹回来,其时延是2倍距离/光速。返回来的波形和发出的波形之间有个频率差,这个频率差和时延是呈线性关系的:物体越远,返回的波收到的时间就越晚,那么它跟入射波的频率差值就越大。将这两个频率做一个减法,就可以得到二者频率的差频(差拍频率),通过判断差拍频率的高低就可以判断障碍物的距离。 + + +在自动驾驶传感器领域,看上去有些沉寂的毫米波雷达开始变得热门。虽然毫米波雷达可能不如摄像头渗透率高,也不如自带光环的激光雷达那样未来感十足,但在自动驾驶领域,毫米波雷达也越来越不可或缺。相比昂贵的激光雷达,毫米波雷达无疑更接地气,更能应对复杂多变的天气条件,在技术上也较为成熟。 + +0124GHz和77GHz毫米波雷达 + +毫米波实质上就是电磁波,频率为30-300GHz(波长1-10mm)。毫米波雷达就是指工作频段在毫米波频段的雷达,测距原理跟一般雷达一样,也就是把无线电波(雷达波)发出去,然后接收回波,根据收发之间的时间差测得目标的位置数据。毫米波雷达就是这个无线电波的频率是毫米波频段。 + +毫米波雷达具有探测性能稳定、作用距离较长、环境适用性好等特点。与超声波雷达相比,毫米波雷达具有体积小、质量轻和空间分辨率高的特点。与红外、激光、摄像头等光学传感器相比,毫米波雷达穿透雾、烟、灰尘的能力强,具有全天候全天时的特点。 + +目前主流使用的车载毫米波雷达按照其频率不同,主要可分为两种:24GHz和77GHz。 + +24GHz频段,能够实现的ADAS功能有盲点检测、变道辅助等,在自动驾驶系统中常用于感知车辆近处的障碍物,为换道决策提供感知信息。因为侦测距离不够远,因此大部分用来做盲区、障碍物的侦测。 + +77GHz频段,性能良好,最大检测距离可以达到160米以上,因此常被安装在前保险杠上,正对汽车的行驶方向。长距离雷达能够用于实现紧急制动、高速公路跟车等ADAS功能,同时也能满足自动驾驶领域,对障碍物距离、速度和角度的测量需求。 + +2005-2013年,欧盟将24GHz、79GHz作为车载毫米波雷达的频谱,而美国使用24GHz、77GHz频带,日本选用了60-61GHz的频段。随着世界范围内76-77GHz毫米波雷达的广泛应用,日本也逐渐转入了79GHz毫米波雷达的开发中。各大国的车载雷达频段主要集中在在23-24GHz、60-61GHz和76-77GHz(79GHz)3个频段,而世界各国对毫米波车载雷达频段使用的混乱情况使得汽车行业车载雷达的发展受到了限制。 + diff --git a/UMCar/readme.md b/UMCar/readme.md index 8ae1aee6..2b4614f5 100644 --- a/UMCar/readme.md +++ b/UMCar/readme.md @@ -1,4051 +1,556 @@ # 无人驾驶 - 以百度apollo 无人驾驶平台介绍相关的技术 - - 1. apollo 源码分析 - 2. 感知 - 3. 规划 - -[comma.ai(无人驾驶公司)的这两千行Python/tf代码 Learning a Driving Simulator](https://github.com/Ewenwan/research) - -[openpilot 一个开源的自动驾驶(驾驶代理),它实行 Hondas 和 Acuras 的自适应巡航控制(ACC)和车道保持辅助系统(LKAS)的功能。 ](https://github.com/Ewenwan/openpilot) - -[Autoware](https://github.com/Ewenwan/Autoware) - -[udacity/self-driving-car](https://github.com/Ewenwan/self-driving-car) - -[第六十八篇:从ADAS到自动驾驶(一):自动驾驶发展及分级](https://blog.csdn.net/liaojiacai/article/details/55062873) - -# Apollo 相关介绍 - - - -``` -We choose to go to the moon in this decade and do the other things, -not because they are easy, but because they are hard. --- John F. Kennedy, 1962 -``` - -Welcome to the Apollo GitHub. - -[Apollo](http://apollo.auto) 开源自动驾驶平台. -It is a high performance flexible architecture which supports fully autonomous driving capabilities. -For business contact, please visit http://apollo.auto - -**Apollo Team now proudly presents to you the latest [version 2.5](https://github.com/ApolloAuto/apollo/releases/tag/v2.5.0).** - -## 安装 - -推荐在 Docker environment 中安装 - -The steps are: - - 1. Run a machine that runs linux (tested on Ubuntu 16.04 with and without an nVidia GPU) - - 2. Create a docker environment - - 3. Build Apollo from source - - 4. Bootstrap start Apollo - - 5. Download the demonstration loop and run it - - 6. Start a browser session and see the Dreamview user interface - -More instructions are below - -### docker environment 安装 - -First, you need to [install docker-ce properly](https://github.com/ApolloAuto/apollo/blob/master/docker/scripts/README.md#install-docker). -The following scripts will get you into the container - -``` -docker ps # to verify docker works without sudo -bash docker/scripts/dev_start.sh -# if in China, you had better use:bash docker/scripts/dev_start.sh -C to download from the server of docker in china. -bash docker/scripts/dev_into.sh - -``` - -### 源码编译 apollo -``` -# To get a list of build commands -./apollo.sh -# To make sure you start clean -./apollo.sh clean -# This will build the full system and requires that you have an nVidia GPU with nVidia drivers loaded -bash apollo.sh build -``` - -If you do not have an nVidia GPU, the system will run but with the CUDA-based perception and other modules. - -You mustspecify either `dbg` for debug mode or `opt` for optimized code - -``` -./apollo.sh build_no_perception dbg -``` - -If you make modifications to the Dreamview frontend, then you must run `./apollo.sh build_fe` before you run the -full build. - - -## 运行 Apollo - -Follow the steps below to launch Apollo. Note that you must build the system first before you run it. -Note that the bootstrap.sh will actually succeed but the user interface will not come up if you skip the build step. - -### Start Apollo - -Running Apollo will start the ROS core and then startup a web user interface called Dreamview, -this is handled by the bootstrap script, so from within the docker container, you should run: - -``` -# start module monitor -bash scripts/bootstrap.sh -``` - -### Access Dreamview - Access Dreamview by opening your favorite browser, e.g. Chrome, go to http://localhost:8888 - and you should see this screenHowever, there will be nothing running in the system. - -![Access Dreamview](https://github.com/Ewenwan/apollo/docs/demo_guide/images/apollo_bootstrap_screen.png) - -### Select Drive Mode -From the dropdown box selet "Navigation" mode. - -![Navigation Mode](https://github.com/Ewenwan/apollo/docs/demo_guide/images/dreamview_2_5_setup_profile.png) - - -### Replay demo rosbag - -To see if the system works, use the demo 'bag' which feeds the system. - -``` -# get rosbag note that the command download is required -python ./docs/demo_guide/rosbag_helper.py demo_2.5.bag - -# You can now replay this demo "bag" in a loop with the '-l' flag -rosbag play -l demo_2.5.bag -``` - -Dreamview should show a running vehicle now. (The following image might be different due to changes in frontend.) - -![Dreamview with Trajectory](docs/demo_guide/images/dv_trajectory_2.5.png) - -## Documents - -Apollo documents can be found under the [docs](https://github.com/ApolloAuto/apollo/blob/master/docs/) repository. - * [quickstart](https://github.com/ApolloAuto/apollo/blob/master/docs/quickstart/): the quickstart tutorial. - * [demo_guide](https://github.com/ApolloAuto/apollo/blob/master/docs/demo_guide/): the guide for demonstration. - * [![Apollo Offline Demo](https://img.youtube.com/vi/Q4BawiLWl8c/0.jpg)](https://www.youtube.com/watch?v=Q4BawiLWl8c) - * [how to contribute code](https://github.com/ApolloAuto/apollo/blob/master/CONTRIBUTING.md): the guide for contributing code to Apollo. - * [howto](https://github.com/ApolloAuto/apollo/blob/master/docs/howto/): tutorials on how to build, run and modify codes. - * [specs](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/): Specification documents of Apollo. - * [Doxygen APIs](https://apolloauto.github.io/doxygen/apollo/): Apollo Doxygen pages - -## Ask Questions - -You are welcome to submit questions and bug reports as [Github Issues](https://github.com/ApolloAuto/apollo/issues). - -## Copyright and License - -Apollo is provided under the [Apache-2.0 license](LICENSE). - -## Disclaimer -Please refer the Disclaimer of Apollo in [Apollo official website](http://apollo.auto/docs/disclaimer.html). -# =========================== -# Apollo 3.0 技术指南 - -## 概况 -> 了解Apollo3.0基础概念和Apollo3.0快速入门指南 - - * [Apollo 3.0快速入门指南](https://github.com/ApolloAuto/apollo/blob/master/docs/quickstart/apollo_3_0_quick_start_cn.md) - -## 硬件和系统安装 -> 了解Apollo3.0硬件和系统安装过程 - - * [Apollo 3.0硬件和系统安装指南](https://github.com/ApolloAuto/apollo/blob/master/docs/quickstart/apollo_3_0_hardware_system_installation_guide_cn.md) - -## 校准 -> 了解校准的过程 - - * [Apollo激光雷达校准指南](https://github.com/ApolloAuto/apollo/blob/master/docs/quickstart/apollo_1_5_lidar_calibration_guide_cn.md) - * [Apollo 2.0传感器校准指南](https://github.com/ApolloAuto/apollo/blob/master/docs/quickstart/apollo_2_0_sensor_calibration_guide_cn.md) - * [多激光雷达全球导航卫星系统(Multiple-LiDAR GNSS)校准指南](https://github.com/ApolloAuto/apollo/blob/master/docs/quickstart/multiple_lidar_gnss_calibration_guide_cn.md) - * [Apollo坐标系统](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/coordination_cn.md) - -## 软件安装 -> 了解Apollo3.0的软件安装过程 - - * [Apollo软件安装指南](https://github.com/ApolloAuto/apollo/blob/master/docs/quickstart/apollo_software_installation_guide_cn.md) - * [如何调试Dreamview启动问题](https://github.com/ApolloAuto/apollo/blob/master/docs/howto/how_to_debug_dreamview_start_problem_cn.md) - * [运行线下演示](https://github.com/ApolloAuto/apollo/blob/master/docs/demo_guide/README_cn.md) - -## Apollo系统架构和原理 -> 了解核心模块的架构和原理 - - * [Apollo 3.0 软件架构](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/Apollo_3.0_Software_Architecture_cn.md "Apollo software architecture") - * [3D 障碍物感知](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/3d_obstacle_perception_cn.md) - * [Apollo 3.0感知](https://github.com/ApolloAuto/apollo/blob/master/modules/perception/README.md) - * [二次规划(QP)样条路径优化](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/qp_spline_path_optimizer_cn.md) - * [二次规划(QP)样条ST速度优化](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/qp_spline_st_speed_optimizer_cn.md) - * [参考线平滑设定](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/reference_line_smoother_cn.md) - * [交通信号灯感知](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/traffic_light_cn.md) - -## 功能模块和相关扩展知识 -> 了解Apollo功能模块和相关扩展知识 - - * [控制总线模块](https://github.com/ApolloAuto/apollo/blob/master/modules/canbus/README.md) - * [通用模块](https://github.com/ApolloAuto/apollo/blob/master/modules/common/README.md) - * [控制模块](https://github.com/ApolloAuto/apollo/blob/master/modules/control/README.md) - * [数据模块](https://github.com/ApolloAuto/apollo/blob/master/modules/data/README.md) - * [定位模块](https://github.com/ApolloAuto/apollo/blob/master/modules/localization/README.md) - * [感知模块](https://github.com/ApolloAuto/apollo/blob/master/modules/perception/README.md) - * [Planning模块](https://github.com/ApolloAuto/apollo/blob/master/modules/planning/README.md) - * [预测模块](https://github.com/ApolloAuto/apollo/blob/master/modules/prediction/README.md) - * [寻路模块](https://github.com/ApolloAuto/apollo/blob/master/modules/routing/README.md) - - * [如何添加新的GPS接收器](https://github.com/ApolloAuto/apollo/blob/master/docs/howto/how_to_add_a_gps_receiver_cn.md) - * [如何添加新的CAN卡](https://github.com/ApolloAuto/apollo/blob/master/docs/howto/how_to_add_a_new_can_card_cn.md ) - * [如何添加新的控制算法](https://github.com/ApolloAuto/apollo/blob/master/docs/howto/how_to_add_a_new_control_algorithm_cn.md) - * [如何在预测模块中添加新评估器](https://github.com/ApolloAuto/apollo/blob/master/docs/howto/how_to_add_a_new_evaluator_in_prediction_module_cn.md) - * [如何在预测模块中添加一个预测器](https://github.com/ApolloAuto/apollo/blob/master/docs/howto/how_to_add_a_new_predictor_in_prediction_module_cn.md) - * [如何在Apollo中添加新的车辆](https://github.com/ApolloAuto/apollo/blob/master/docs/howto/how_to_add_a_new_vehicle_cn.md) - * [如何添加新的外部依赖项](https://github.com/ApolloAuto/apollo/blob/master/docs/howto/how_to_add_an_external_dependency_cn.md) - - ## 开发者工具 -> 了解开发者工具 - - * [使用VSCode构建、调试Apollo项目](https://github.com/ApolloAuto/apollo/blob/master/docs/howto/how_to_build_and_debug_apollo_in_vscode_cn.md "How to build and debug Apollo in VSCode") - * [DreamView用法介绍](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/dreamview_usage_table_cn.md) - - - -# =============================== -# Apollo具体内容说明 - -## 软件 -- [Apollo 2.0软件系统架构](Apollo_2.0_Software_Architecture.md) -- [Apollo 3.0软件系统架构](Apollo_3.0_Software_Architecture_cn.md) -- [Planning模块架构概述](Class_Architecture_Planning_cn.md) - -## Apollo硬件开发平台 - -我们强烈建议使用者在阅读硬件开发平台文档前浏览我们的免责声明。 - -- [Apollo传感器单元(ASU)](https://github.com/ApolloAuto/apollo/tree/master/docs/specs/Apollo_Sensor_Unit/Apollo_Sensor_Unit_Installation_Guide_cn.md) -- [摄像机](https://github.com/ApolloAuto/apollo/tree/master/docs/specs/Camera/README.md) -- [激光雷达](https://github.com/ApolloAuto/apollo/tree/master/docs/specs/Lidar/README.md) -- [雷达](https://github.com/ApolloAuto/apollo/tree/master/docs/specs/Radar/README.md) -- [导航](https://github.com/ApolloAuto/apollo/tree/master/docs/specs/Navigation/README_cn.md) -- [IPC](https://github.com/ApolloAuto/apollo/tree/master/docs/specs/IPC/Nuvo-6108GC_Installation_Guide_cn.md) -- [软件系统和内核安装指南](https://github.com/ApolloAuto/apollo/tree/master/docs/specs/Software_and_Kernel_Installation_guide_cn.md) - -## 感知 - -- [Apollo 2.5感知系统](https://github.com/ApolloAuto/apollo/tree/master/docs/specs/perception_apollo_2.5.md) -- [Apollo 2.5传感器安装指南](https://github.com/ApolloAuto/apollo/tree/master/docs/specs/Guideline_sensor_Installation_apollo_2.5.md) -- [Apollo 3.0感知系统]https://github.com/ApolloAuto/apollo/tree/master/docs/specs/(perception_apollo_3.0_cn.md) -- [Apollo 3.0传感器安装指南](https://github.com/ApolloAuto/apollo/tree/master/docs/specs/Guideline_sensor_Installation_apollo_3.0_cn.md) -- [激光雷达校准英文版](https://github.com/ApolloAuto/apollo/tree/master/docs/specs/lidar_calibration.pdf) -- [激光雷达校准中文版](https://github.com/ApolloAuto/apollo/tree/master/docs/specs/lidar_calibration_cn.pdf) - -## HMI -- [Dreamview使用方法](https://github.com/ApolloAuto/apollo/tree/master/docs/specs/dreamview_usage_table_cn.md) - -## 算法 -- [三维障碍物感知英文版](https://github.com/ApolloAuto/apollo/tree/master/docs/specs/3d_obstacle_perception.md) -- [三维障碍物感知中文版](https://github.com/ApolloAuto/apollo/tree/master/docs/specs/3d_obstacle_perception_cn.md) -- [二次规划路径样条优化](https://github.com/ApolloAuto/apollo/tree/master/docs/specs/qp_spline_path_optimizer_cn.md) -- [二次规划st速度样条优化](https://github.com/ApolloAuto/apollo/tree/master/docs/specs/qp_spline_st_speed_optimizer_cn.md) -- [参考线平滑设定](https://github.com/ApolloAuto/apollo/tree/master/docs/specs/reference_line_smoother_cn.md) -- [交通信号灯感知](https://github.com/ApolloAuto/apollo/tree/master/docs/specs/traffic_light_cn.md) - -## 其他通用知识 -- [坐标系统](https://github.com/ApolloAuto/apollo/tree/master/docs/specs/coordination_cn.md) -- [Apollo安全更新SDK用户指南](https://github.com/ApolloAuto/apollo/tree/master/docs/specs/apollo_secure_upgrade_user_guide-CN.md) - - -# =============================== -# 工业级PC(IPC)软件安装指南 - -本文档介绍下述软件的安装步骤: - -- Ubuntu Linux -- Apollo Kernel -- Nvidia GPU Driver - -![tip_icon](images/tip_icon.png)成功完成本文档中介绍的软件安装需要使用者有使用Linux系统的经验。 - -## 安装Unbuntu Linux - -按照如下步骤执行: - -1. 创建一个可引导的Ubuntu Linux USB启动盘: - - 下载Ubuntu 14.04(或其他的变种系统如Xubuntu)并[创建一个可引导的USB启动盘](https://tutorials.ubuntu.com/tutorial/tutorial-create-a-usb-stick-on-ubuntu#0)。我们推荐使用Ubuntu 14.04。在系统启动时按下F2(或其他按键,请参考系统文档)进入BIOS设置,我们建议禁用Quick Boot和Quiet Boot设置以更容易的在启动时捕获错误信息。 - -2. 安装Ubuntu Linux: - - a. 将安装Unbuntu的USB启动盘插入USB接口中并启动系统 - - b. 按照屏幕提示执行安装 - -3. 执行软件更新: - - a. 安装结束后重启并进入系统 - - b. 启动Software Update并更新到最新软件包,或在终端程序如GNOME Terminal中执行下述指令完成更新: - - ```shell - sudo apt-get update; sudo apt-get upgrade - ``` - - c. 启动终端程序如GNOME Terminal,执行下述指令安装Linux 4.4内核 - - ```shell - sudo apt-get install linux-generic-lts-xenial - ``` - - ![tip_icon](images/tip_icon.png)IPC必须有网络连接以更新和安装软件。确保IPC的以太网线接入了有互联网访问权限的网络。如果接入的网络没有使用动态主机配置协议(DHCP),使用者可能需要对IPC的网络进行配置。 - -## 安装Apollo内核 - -Apollo在车辆上的运行需要[Apollo内核](https://github.com/ApolloAuto/apollo-kernel)。我们强烈推荐安装预先构建的内核版本。 - -## 使用预先构建的内核版本 - -使用者使用下述指令获取和安装预先构建的内核版本。 - -1. 从GitHub下载发布版本包: - -``` -https://github.com/ApolloAuto/apollo-kernel/releases -``` - -2. 成功下载发布版本包后安装内核: - -``` -tar zxvf linux-4.4.32-apollo-1.5.0.tar.gz -cd install -sudo bash install_kernel.sh -``` - -3. 使用 `reboot` 指令重启系统 -4. 【可选步骤-如果使用者使用了CAN卡】参考CAN卡供应商提供的指令构建CAN卡驱动程序 - -## 构建个人的内核版本 - -如果使用者修改了内核,或者预先构建的版本对使用者的工作平台不是最好的选择,使用者可以使用下述指令构建个人的内核版本: - -1. 从资源库中clone源代码 - -``` -git clone https://github.com/ApolloAuto/apollo-kernel.git -cd apollo-kernel -``` - -2. 参考CAN卡供应商提供的指令加入CAN卡驱动的源代码 -3. 使用下述指令构建内核: - -``` -bash build.sh -``` - -4. 参考上面章节中介绍的如何安装预先构建内核版本的步骤进行内核的安装 - -## 安装NVIDIA GPU驱动 - -Apollo在车辆上的运行需要[NVIDIA GPU驱动](http://www.nvidia.com/download/driverResults.aspx/114708/en-us)。使用者必须使用指定的参数选项安装NVIDIA GPU驱动。 - -1. 下载安装文件 - -``` -wget http://us.download.nvidia.com/XFree86/Linux-x86_64/375.39/NVIDIA-Linux-x86_64-375.39.run -``` - -2. 执行驱动安装 - -``` -sudo bash ./NVIDIA-Linux-x86_64-375.39.run --no-x-check -a -s -``` - -## 参考资料 - -1. [Ubuntu官方网站](https://www.ubuntu.com/desktop) - - -# ============================= -# Apollo 3.0 软件架构 - -自动驾驶Apollo3.0核心软件模块包括: - -- **感知** — 感知模块识别自动驾驶车辆周围的世界。感知中有两个重要的子模块:障碍物检测和交通灯检测。 -- **预测** — 预测模块预测感知障碍物的未来运动轨迹。 -- **路由** — 路由模块告诉自动驾驶车辆如何通过一系列车道或道路到达其目的地。 -- **规划** — 规划模块规划自动驾驶车辆的时间和空间轨迹。 -- **控制** — 控制模块通过产生诸如油门,制动和转向的控制命令来执行规划模块产生的轨迹。 -- **CanBus** — CanBus是将控制命令传递给车辆硬件的接口。它还将底盘信息传递给软件系统。 -- **高精地图** — 该模块类似于库。它不是发布和订阅消息,而是经常用作查询引擎支持,以提供关于道路的特定结构化信息。 -- **定位** — 定位模块利用GPS,LiDAR和IMU的各种信息源来定位自动驾驶车辆的位置。 -- **HMI** — Apollo中的HMI和DreamView是一个用于查看车辆状态,测试其他模块以及实时控制车辆功能的模块. -- **监控** — 车辆中所有模块的监控系统包括硬件。 -- **Guardian** — 新的安全模块,用于干预监控检测到的失败和action center相应的功能。 -执行操作中心功能并进行干预的新安全模块应监控检测故障。 - -``` -注意:下面列出了每个模块的详细信息。 -``` - -这些模块的交互如下图所示。 - -![img](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/Apollo_3.0_SW.png) - -每个模块都作为单独的基于CarOS的ROS节点运行。每个模块节点都发布和订阅特定topic。订阅的topic用作数据输入,而发布的topic用作数据输出。以下各节详细介绍了各模块情况。 - -## 感知 - -感知依赖LiDAR点云数据和相机原始数据。除了这些传感器数据输入之外,交通灯检测依赖定位以及HD-Map。由于实时ad-hoc交通灯检测在计算上是不可行的,因此交通灯检测需要依赖定位确定何时何地开始通过相机捕获的图像检测交通灯。 -对Apollo 3.0的更改: - - CIPV检测/尾随 - 在单个车道内移动。 - - 全线支持 - 粗线支持,可实现远程精确度。相机安装有高低两种不同的安装方式。 - - 异步传感器融合 – 因为不同传感器的帧速率差异——雷达为10ms,相机为33s,LiDAR为100ms,所以异步融合LiDAR,雷达和相机数据,并获取所有信息并得到数据点的功能非常重要。 - - 在线姿态估计 - 在出现颠簸或斜坡时确定与估算角度变化,以确保传感器随汽车移动且角度/姿态相应地变化。 - - 视觉定位 – 基于相机的视觉定位方案正在测试中。 - - 超声波传感器 – 作为安全保障传感器,与Guardian一起用于自动紧急制动和停车。 - -## 预测 - -预测模块负责预测所有感知障碍物的未来运动轨迹。输出预测消息封装了感知信息。预测订阅定位和感知障碍物消息,如下所示。 - -![img](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/prediction.png) - -当接收到定位更新时,预测模块更新其内部状态。当感知发出其发布感知障碍物消息时,触发预测实际执行。 - -## 定位 - -定位模块聚合各种数据以定位自动驾驶车辆。有两种类型的定位模式:OnTimer和多传感器融合。 - -第一种基于RTK的定位方法,通过计时器的回调函数“OnTimer”实现,如下所示。 -![img](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/localization.png) - -另一种定位方法是多传感器融合(MSF)方法,其中注册了一些事件触发的回调函数,如下所示。 - -![img](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/localization_2.png) - -## 路由 -为了计算可通行车道和道路,路由模块需要知道起点和终点。通常,路由起点是自动驾驶车辆位置。重要的数据接口是一个名为`OnRoutingRequest`的事件触发函数,其中`RoutingResponse`的计算和发布如下所示。 - -![img](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/routing.png) - -## 规划 -Apollo 2.0需要使用多个信息源来规划安全无碰撞的行驶轨迹,因此规划模块几乎与其他所有模块进行交互。 - -首先,规划模块获得预测模块的输出。预测输出封装了原始感知障碍物,规划模块订阅交通灯检测输出而不是感知障碍物输出。 -然后,规划模块获取路由输出。在某些情况下,如果当前路由结果不可执行,则规划模块还可以通过发送路由请求来触发新的路由计算。 - -最后,规划模块需要知道定位信息(定位:我在哪里)以及当前的自动驾驶车辆信息(底盘:我的状态是什么)。规划模块由固定频率触发,主数据接口是调用`RunOnce`函数的`OnTimer`回调函数。 - -![img](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/planning_1.png) - -底盘,定位,交通灯和预测等数据依赖关系通过`AdapterManager`类进行管理。核心软件模块同样也由`AdapterManager`类管理。例如,定位通过`AdapterManager :: GetLocalization()`管理,如下所示。 - -![img](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/planning_2.png) - -## 控制 -如规划模块中所述,控制将规划轨迹作为输入,并生成控制命令传递给CanBus。它有三个主要的数据接口:OnPad,OnMonitor和OnTimer。 - -![img](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/control_1.png) - -`OnPad`和`OnMonitor`是仿真和HMI的交互接口。 主要数据接口是`OnTimer`,它定期产生实际的控制命令,如下所示。 - -![img](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/control_2.png) - -## CanBus - -CanBus有两个数据接口。 - -![img](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/canbus_1.png) - -第一个数据接口是基于计时器的发布者,回调函数为“OnTimer”。如果启用,此数据接口会定期发布底盘信息。 - -![img](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/canbus_2.png) - -第二个数据接口是一个基于事件的发布者,回调函数为“OnControlCommand”,当CanBus模块接收到控制命令时会触发该函数。 - - -## HMI -Apollo中的HMI或DreamView是一个Web应用程序: - - 可视化自动驾驶模块的输出,例如,规划轨迹,汽车定位,底盘状态等。 - - 为用户提供人机交互界面,以查看硬件状态,打开/关闭模块,以及启动自动驾驶汽车。 - - 提供调试工具,如PnC Monitor,以有效跟踪模块问题。 - -## 监控 -包括硬件在内的,车辆中所有模块的监控系统。监控模块从其他模块接收数据并传递给HMI,以便司机查看并确保所有模块都正常工作。如果模块或硬件发生故障,监控会向Guardian(新的操作中心模块)发送警报,然后决定需要采取哪些操作来防止系统崩溃。 - -## Guardian -这个新模块根据Monitor发送的数据做出相应决定。Guardian有两个主要功能: - - 所有模块都正常工作 - Guardian允许控制模块正常工作。控制信号被发送到CANBus,就像Guardian不存在一样。 - - 监控检测到模块崩溃 - 如果监控检测到故障,Guardian将阻止控制信号到达CANBus并使汽车停止。 Guardian有三种方式决定如何停车并会依赖最终的Gatekeeper——超声波传感器, - - 如果超声波传感器运行正常而未检测到障碍物,Guardian将使汽车缓慢停止 - - 如果传感器没有响应,Guardian会硬制动,使车马上停止。 - - 这是一种特殊情况,如果HMI通知驾驶员即将发生碰撞并且驾驶员在10秒内没有干预,Guardian会使用硬制动使汽车立即停止。 - -``` -注意: -1.在上述任何一种情况下,如果Monitor检测到任何模块或硬件出现故障,Guardian将始终停止该车。 -2.监控器和Guardian解耦以确保没有单点故障,并且可以为Guardian模块添加其他行为且不影响监控系统,监控还与HMI通信。 -``` - -# ======================= -# 感知 -Apollo 3.0 -June 27, 2018 - -## 简介 - Apollo 3.0 主要针对采用低成本传感器的L2级别自动驾驶车辆。 - 在车道中的自动驾驶车辆通过一个前置摄像头和前置雷达要与关键车辆(在路径上最近的车辆)保持一定的距离。 - Apollo 3.0 支持在高速公路上不依赖地图的高速自动驾驶。 - 深度网路学习处理图像数据,随着搜集更多的数据,深度网络的性能随着时间的推移将得到改善。 - - -***安全警告*** - Apollo 3.0 不支持没有包含本地道路和说明标示的急转弯道路。 - 感知模块是基于采用深度网络并结合有限数据的可视化检测技术。 - 因此,在我们发布更好的网络之前,驾驶员应该小心驾驶并控制好车辆方向而不能依赖与自动驾驶。 - 请在安全和限制区域进行试驾。 - -- ***推荐道路*** - - ***道路两侧有清晰的白色车道线*** - -- ***禁止*** - - ***急转弯道路*** - - ***没有车道线标记的道路*** - - ***路口*** - - ***对接点或虚线车道线*** - - ***公共道路*** - -## 感知模块 -每个模块的流程图如下所示。 - -![Image](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/perception_flow_chart_apollo_3.0.png) - -**图 1: Apollo 3.0的流程图** - -### 深度网络 - 深度网络摄取图像并为Apollo 3.0提供两个检测输出,车道线和对象。 - 目前,对深度学习中使用单一任务还是协同训练任务还存在一些争议。 - 诸如车道检测网络或物体检测网络的单一网络通常比一个协同训练的多任务网络执行得更好。 - 然而,在给定有限资源的情况下,多个单独的网络将是昂贵的并且在处理中消耗更多时间。 - 因此,对于经济设计而言,协同训练是不可避免的,并且在性能上会有一些妥协。 - 在 Apollo 3.0, YOLO [1][2] 被用作对象和车道线检测的基础网络。 - 该对象具有车辆、卡车、骑车人和行人类别,并由表示成具有方向信息的2-D边界框。 - 通过使用具有一些修改的相同网络进行分段来检测车道线。 - 对于整条车道线,我们有一个单独的网络, - 以提供更长的车道线,无论是车道线是离散的还是连续的。 - - -### 物体识别/跟踪 - 在交通场景中,有两类物体: 静态物体和动态物体。 - 静态物体包括车道线、交通信号灯以及数以千计的以各种语言写成的交通标示。 - 除了驾驶之外,道路上还有多个地标,主要用于视觉定位,包括路灯,障碍物,道路上的桥梁或任何天际线。 - 对于静态物体,Apollo 3.0将仅检测车道线. - - 在动态物体中,Apollo在路上关心乘用车,卡车,骑自行车者,行人或任何其他物体,包括动物或身体部位。 - Apollo还可以根据物体所在的车道对物体进行分类。 - 最重要的物体是CIPV(路径中最近的物体)。下一个重要对象将是相邻车道中的物体。 - - -#### 2D-to-3D 边界框 - 给定一个2D盒子,其3D大小和相机方向,该模块搜索相机坐标系统中的3D位置, - 并使用该2D盒子的宽度,高度或2D区域估计精确的3D距离。 - 该模块可在没有准确的外部相机参数的情况下工作。 - -#### 对象跟踪 - 对象跟踪模块利用多种信息,例如3D位置,2D图像补丁,2D框或深度学习ROI特征。 - 跟踪问题通过有效地组合线索来表达为多个假设数据关联, - 以提供路径和检测到的对象之间的最正确关联,从而获得每个对象的正确ID关联。 - -### 车道检测/追踪 - 在静态对象中,我们在Apollo 3.0中将仅处理通道线。 - 该车道用于纵向和横向控制。 - 车道本身引导横向控制,并且在车道内的对象引导纵向控制。 - -#### 车道线 - 我们有两种类型的车道线,车道标记段和整个车道线。 - 车道标记段用于视觉定位,整个车道线用于使车辆保持在车道内。 - 该通道可以由多组折线表示,例如下一个左侧车道线,左侧线,右侧线和下一个右侧线。 - 给定来自深度网络的车道线热图,通过阈值化生成分段的二进制图像。 - 该方法首先找到连接的组件并检测内部轮廓。 - 然后,它基于自我车辆坐标系的地面空间中的轮廓边缘生成车道标记点。 - 之后,它将这些车道标记与具有相应的相对空间(例如,左(L0),右(R0),下左(L1),下(右)(L2)等)标签的若干车道线对象相关联。 - -### CIPV (最近路径车辆) - CIPV是当前车道中最接近的车辆。 - 对象由3D边界框表示,其从上到下视图的2D投影将对象定位在地面上。 - 然后,检查每个对象是否在当前车道中。 - 在当前车道的对象中,最接近的一个将被选为CIPV。 - -### 跟车 - 跟车是跟随前车的一种策略。 - 从跟踪对象和当前车辆运动中,估计对象的轨迹。 - 该轨迹将指导对象如何在道路上作为一组移动并且可以预测未来的轨迹。 - 有两种跟车尾随,一种是跟随特定车辆的纯尾随, - 另一种是CIPV引导的尾随,当检测到无车道线时,当前车辆遵循CIPV的轨迹。 - -输出可视化的快照如图2所示。 -![Image](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/perception_visualization_apollo_3.0.png) - -**图 2: Apollo 3.0中感知输出的可视化。左上角是基于图像的输出。左下角显示了对象的3D边界框。左图显示了车道线和物体的三维俯视图。CIPV标有红色边框。黄线表示每辆车的轨迹** - -### 雷达 + 摄像头融合 - 给定多个传感器,它们的输出应以协同方式组合。 - Apollo 3.0,介绍了一套带雷达和摄像头的传感器。 - 对于此过程,需要校准两个传感器。每个传感器都将使用Apollo 2.0中介绍的相同方法进行校准。 - 校准后,输出将以3-D世界坐标表示,每个输出将通过它们在位置,大小,时间和每个传感器的效用方面的相似性进行融合。 - 在学习了每个传感器的效用函数后,摄像机对横向距离的贡献更大,雷达对纵向距离测量的贡献更大。 - 异步传感器融合算法也作为选项提供。 - -### 伪车道 - 所有车道检测结果将在空间上临时组合以诱导伪车道, - 该车道将被反馈到规划和控制模块。 - 某些车道线在某帧中不正确或缺失。 - 为了提供平滑的车道线输出,使用车辆里程测量的历史车道线。 - 当车辆移动时,保存每个帧的里程表,并且先前帧中的车道线也将保存在历史缓冲器中。 - 检测到的与历史车道线不匹配的车道线将被移除,历史输出将替换车道线并提供给规划模块。 - -### 超声波传感器 - Apollo 3.0支持超声波传感器。每个超声波传感器通过CAN总线提供被检测对象的距离。 - 来自每个超声波传感器的测量数据被收集并作为ROS主题广播。 - 将来,在融合超声波传感器后,物体和边界的地图将作为ROS的输出发布。 - -## 感知输出 -PnC的输入将与之前基于激光雷达的系统的输入完全不同。 - -- 车道线输出 - - 折线和/或多项式曲线 - - 车道类型按位置:L1(左下车道线),L0(左车道线),R0(右车道线),R1(右下车道线 - -- 对象输出 - - 3D长方体 - - 相对速度和方向 - - 类型:CIPV,PIHP,其他 - - 分类:汽车,卡车,自行车,行人 - - Drops:物体的轨迹 - -世界坐标是3D中的当前车辆坐标,其中后中心轴是原点。 - -## 参考 -[1] J Redmon, S Divvala, R Girshick, A Farhadi, "你只看一次:统一的实时物体检测" CVPR 2016 - -[2] J Redmon, A Farhadi, "YOLO9000: 更好, 更快, 更强," arXiv preprint - -# =================================== -# 交通信号灯感知 - -本文档详细的介绍了Apollo2.0中交通信号感知模块的工作原理。 - -## 简介 - -交通信号灯感知模块通过使用摄像头提供精确全面的路面交通信号灯状态。 - -通常情况下,交通信号灯有3种状态: - -- 红 -- 黄 -- 绿 - -然而当信号灯不能正常工作时,它可能是黑色的或者闪烁着红灯或黄灯。有时候在摄像头的视野内找不到信号灯,从而导致无法正确检测信号灯状态。 - -为了覆盖全部的情况,交通信号灯感知模块提供了5种信号灯状态输出: - -- 红 -- 黄 -- 绿 -- 黑 -- 未知 - -该模块的高精地图功能反复的检测车辆前方是否有信号灯出现。在给定车辆的位置后,可以通过查询高精地图获取信号灯的边界,并用边界上的4个点来表示信号灯。如果存在信号灯,则信号灯位置信息将从世界坐标系投射到图片坐标系。 - -Apollo已经证明了仅仅使用一个固定视野的摄像头无法识别所有的信号灯。存在这种限制的原因是: - -- 感知范围应该大于100米 -- 信号灯的高度和路口的宽度变化范围很大 - -结果是Apollo2.0使用了2个摄像头来扩大感知范围。 - -- 一个**远距摄像头**,焦距是25毫米,被用来观察前方远距离的信号灯。远距摄像头捕获的信号灯在图片上展现的非常大而且容易被检测。但是远距摄像头的视野有限制,如果路线不够直或者车辆太过于靠近信号灯,经常无法拍摄到信号灯。 - - -- 一个**广角摄像头**。焦距是6毫米,是对远距摄像头视野不足的补充。 - -该模块会根据当前信号灯的投射状态决定使用哪个摄像头。虽然只有两个摄像头,但是该模块的算法被设计的可以控制多个摄像头。 - -下述图片展示了使用远距摄像头(上图)和广角摄像头(下图)检测到信号灯的图片。 - -![telephoto camera](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/traffic_light/long.jpg) - - -![wide angle camera](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/traffic_light/short.jpg) - - -# 数据管道 - -数据管道有两个主要的部分,会在下面章节中介绍 -- 预处理阶段 - - 信号灯投射 - - 摄像头选择 - - 图像和信号灯缓存同步 -- 处理阶段 - - 调整—提供精确的信号灯边界盒 - - 识别—提供每个边界盒的颜色 - - 修正—根据时间顺序关系修正颜色 - -## 预处理阶段 - -没有必要在每一帧的图像中去检测信号灯。信号灯的变化频率是很低的而且计算机的资源也有限。通常,从不同摄像头输入的图像信息会几乎同时的到达,但是只有一个会进入管道的处理阶段。因此图像的遴选和匹配是很必要的。 - -### 输入输出 - -本章节介绍了预处理阶段的输入输出数据。输入数据可以通过订阅Apollo相关模块数据来获得,或者直接读取本地的存储文件。输出数据被传输到下一层的处理阶段。 - -#### 输入数据 - -- 可以通过订阅以下topic来获取不同摄像头的图像数据: - - - `/apollo/sensor/camera/traffic/image_long` - - `/apollo/sensor/camera/traffic/image_short` - -- 定位信息,通过查询以下topic获得: - - `/tf` - -- 高精地图 - -- 校准结果 - -#### 输出数据 - - - 被选择的摄像头输出的的图像信息 - - 从世界坐标系投射到图像坐标系的信号灯边界盒 - -### 摄像头选择 - -使用一个唯一的ID和其边界上的4个点来表示信号灯,每个点都是世界坐标系中的3维坐标点。 - -下例展示了一个典型的信号灯记录信息`signal info`。给出车辆位置后,4个边界点可以通过查询高精地图获得。 - -```protobuf -signal info: -id { - id: "xxx" -} -boundary { - point { x: ... y: ... z: ... } - point { x: ... y: ... z: ... } - point { x: ... y: ... z: ... } - point { x: ... y: ... z: ... } -} -``` - -3维世界坐标系中的边界点随后被投射到每个摄像头图像的2维坐标系。对每个信号灯而言,远距摄像头图像上展示的4个投射点区域更大,这比广角摄像头更容易检测信号灯。最后会选择具有最长的焦距且能够看到所有信号灯的摄像头图片作为输出图像。投射到该图像上的信号边界盒将作为输出的边界盒。 - -被选择的摄像头的ID和时间戳缓存在队列中: - - - ``` C++ -struct ImageLights { - CarPose pose; - CameraId camera_id; - double timestamp; - size_t num_signal; - ... other ... -}; - ``` - - 至此,我们需要的所有信息包括定位信息、校准结果和高精地图。因为投射不依赖于图像的内容,所以选择可以在任何时间完成。在图像信息到达时进行选择仅仅是为了简单。而且,并不是图像信息一到达就要进行选择,通常会设置选择的时间间隔。 - - -### 图像同步 - -图像信息包含了摄像头ID和时间戳。摄像头ID和时间戳的组合用来找到可能存在的缓存信息。如果能在缓存区找到和该图像的摄像头ID一样且时间戳相差很小的缓存信息,则该图像会被传输到处理阶段。所有不合适的缓存信息会被丢弃。 - -## 处理阶段 - -该阶段分为3个步骤,每个步骤重点执行一个任务: - -- 调整 — 在ROI中检测信号灯边界盒 -- 识别 — 鉴别边界盒的颜色 -- 修正 — 根据信号灯颜色的时间顺序关系修正颜色 - -### 输入输出 - -本章节介绍处理阶段的输入和输出数据。输入数据从预处理阶段获得,输出数据作为鉴别信号灯的结果。 - -#### 输入数据 - -- 被选择的摄像头图像信息 -- 一组边界盒信息 - -#### 输出数据 - - - 一组带有颜色标签的边界盒信息 - - -### 调整 - -被定位信息、校准信息和高精地图信息影响的投射点 ***不是完全可靠的*** 。通过投射的信号灯位置计算的一个大的兴趣区域(Region of Interest ROI)被用来确定信号灯精确的边界盒。 - -在下述图片中,蓝色的长方形表示被投射的信号灯的边界盒,实际上和信号灯的准确位置有一定的偏差。大的黄色长方形是ROI。 - -![example](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/traffic_light/example.jpg) - -信号灯检测是一个常规的卷积神经网络检测任务,它接收带有ROI信息的图像作为输入数据,顺序输出边界盒。输出结果中的信号灯数量可能多于输入数据。 - -Apollo会根据输入信号灯的位置、形状及检测的评分选择合适的信号灯。如果CNN在ROI内找不到任何的信号灯,则输入数据中的信号灯将被标记为未知,且跳过剩下的两个步骤。 - -### 识别 - -信号灯识别是一个常规的卷积神经网络鉴别任务,它接收带有ROI信息的图像和一组边界盒信息作为输入数据。输出数据是一个`$4\times n$ vector`, 表示每个边界盒是黑色、红色、黄色和绿色的概率。 -当且仅当概率足够大时,有最大概率的类别会被识别为信号灯的状态。否则信号灯状态被设置为未知,表示状态未确定。 - -### 修正 - -因为信号灯可能会闪烁或者被遮挡,并且识别阶段也 ***并不是*** 完美的,输出的信号灯状态可能不是真正的状态。修正信号灯状态是很有必要的。 - -如果修正器接收到一个确定的信号灯状态例如红色或者绿色,则修正器保存该状态并直接输出。如果接收到黑色或者未知,修正器会检测状态保存列表。如果信号灯状态已经确定持续了一段时间,那么将保存的状态输出。否则将黑色或者未知输出。 - -因为时间顺序关系的存在,黄色只会在绿色之后红色之前出现,所以为了安全的考虑,在绿色出现之前任何红色之后的黄色都会被设置为红色。 - - - -3D 障碍物感知 -==================== - -Apollo解决的障碍物感知问题: - -- 高精地图ROI过滤器(HDMap ROI Filter) -- 基于卷积神经网络分割(CNN Segmentation) -- MinBox 障碍物边框构建(MinBox Builder) -- HM对象跟踪(HM Object Tracker) - -高精地图ROI过滤器 -------------------------------------- - -ROI(The Region of Interest)指定从高精地图检索到包含路面、路口的可驾驶区域。高精地图 ROI 过滤器(往下简称“过滤器”)处理在ROI之外的激光雷达点,去除背景对象,如路边建筑物和树木等,剩余的点云留待后续处理。 - -给定一个高精地图,每个激光雷达点的关系意味着它在ROI内部还是外部。 -每个激光雷达点可以查询一个车辆周围区域的2D量化的查找表(LUT)。过滤器模块的输入和输出汇总于下表。 - - |输入 |输出 | - |------------------------------------------------------------------------- |---------------------------------------------------------------------------| - |点云: 激光雷达捕捉的3D点数据集 | 由高精地图定义的ROI内的输入点索引。 | - |高精地图: 多边形集合,每个多边形均含有一个有序的点集。 | | - -一般来说,Apollo 高精地图 ROI过滤器有以下三步: - -1. 坐标转换 -2. ROI LUT构造 -3. ROI LUT点查询 - -### 坐标转换 - -对于(高精地图ROI)过滤器来说,高精地图数据接口被定义为一系列多边形集合,每个集合由世界坐标系点组成有序点集。高精地图ROI点查询需要点云和多边形处在相同的坐标系,为此,Apollo将输入点云和HDMap多边形变换为来自激光雷达传感器位置的地方坐标系。 - -### ROI LUT构造 - -Apollo采用网格显示查找表(LUT),将ROI量化为俯视图2D网格,以此决定输入点是在ROI之内还是之外。 - -如图1所示,该LUT覆盖了一个矩形区域,该区域位于高精地图边界上方,以普通视图周围的预定义空间范围为边界。它代表了与ROI关联网格的每个单元格(如用1/0表示在ROI的内部/外部)。 为了计算效率,Apollo使用 **扫描线算法**和 **位图编码**来构建ROI LUT。 - - -
图 1 ROI显示查找表(LUT)
- -蓝色线条标出了高精地图ROI的边界,包含路表与路口。红色加粗点表示对应于激光雷达传感器位置的地方坐标系原始位置。2D网格由8*8个绿色正方形组成,在ROI中的单元格,为蓝色填充的正方形,而之外的是黄色填充的正方形。 - -### ROI LUT点查询 - -基于ROI LUT,查询每个输入点的关系使用两步认证。对于点查询过程,Apollo数据编译输出如下,: - -1. 检查点在ROI LUT矩形区域之内还是之外。 -2. 查询LUT中相对于ROI关联点的相应单元格。 -3. 收集属于ROI的所有点,并输出其相对于输入点云的索引。 - -用户定义的参数可在配置文件`modules/perception/model/hdmap_roi_filter.config`中设置,HDMap ROI Filter 参数使用参考如下表格: - - |参数名称 |使用 |默认 | - |------------------- |------------------------------------------------------------------------------ |------------| - |range | 基于LiDAR传感器点的2D网格ROI LUT的图层范围),如(-70, 70)*(-70, 70) |70.0 米 | - |cell_size | 用于量化2D网格的单元格的大小。 |0.25 米 | - |extend_dist | 从多边形边界扩展ROI的距离。 |0.0 米 | - -基于CNN的障碍物分割 ------------------------------------------------- -高精地图 ROI过滤之后,Apollo得到已过滤、只包含属于ROI内的点云,大部分背景障碍物,如路侧的建筑物、树木等均被移除,ROI内的点云被传递到分割模块。分割模块检测和划分前景障碍物,例如汽车,卡车,自行车和行人。 - - |输入 |输出 | - |----------------------------------------------------------------------------|---------------------------------------------------------------| - |点云(3D数据集) |对应于ROI中的障碍物对象数据集 | - |表示在HDMap中定义的ROI内的点的点索引 | | -Apollo 使用深度卷积神经网络提高障碍物识别与分割的精度,障碍物分割包含以下四步: -- 通道特征提取 -- 基于卷积神经网络的障碍物预测 -- 障碍物集群 -- 后期处理 - -卷积神经网络详细介绍如下: - -### 通道特征提取 - -给定一个点云框架,Apollo在地方坐标系中构建俯视图(即投影到X-Y平面)2D网格。 基于点的X、Y坐标,相对于LiDAR传感器原点的预定范围内,每个点被量化为2D网格的一个单元。 量化后,Apollo计算网格内每个单元格中点的8个统计测量,这将是下一步中传递给CNN的输入通道特征。 - -计算的8个统计测量: - -1. 单元格中点的最大高度 -2. 单元格中最高点的强度 -3. 单元格中点的平均高度 -4. 单元格中点的平均强度 -5. 单元格中的点数 -6. 单元格中心相对于原点的角度 -7. 单元格中心与原点之间的距离 -8. 二进制值标示单元格是空还是被占用 - -### 基于卷积神经网络的障碍物预测 - -基于上述通道特征,Apollo使用深度完全卷积神经网络(FCNN)来预测单元格障碍物属性,包括潜在物体中心的偏移位移(称为中心偏移)、对象性 -积极性和物体高度。如图2所示,网络的输入为 *W* x *H* x *C* 通道图像,其中: - -- *W* 代表网格中的列数 -- *H* 代表网格中的行数 -- *C* 代表通道特征数 - -完全卷积神经网络由三层构成: -- 下游编码层(特征编码器) -- 上游解码层(特征解码器) -- 障碍物属性预测层(预测器) - -特征编码器将通道特征图像作为输入,并且随着特征抽取的增加而连续**下采样**其空间分辨率。 然后特征解码器逐渐对特征图像 **上采样**到输入2D网格的空间分辨率,可以恢复特征图像的空间细节,以促进单元格方向的障碍物位置、速度属性预测。 根据具有非线性激活(即ReLu)层的堆叠卷积/分散层来实现 **下采样**和 **上采样**操作。 - -
- -
图 2 FCNN在单元格方向上的障碍物预测
- -### 障碍物聚类 -在基于CNN的预测之后,Apollo获取单个单元格的预测信息。利用四个单元对象属性图像,其中包含: - -- 中心偏移 -- 对象性 -- 积极性 -- 对象高度 - -为生成障碍物,Apollo基于单元格中心偏移,预测构建有向图,并搜索连接的组件作为候选对象集群。 - -如图3所示,每个单元格是图的一个节点,并且基于单元格的中心偏移预测构建有向边,其指向对应于另一单元的父节点。 - -如图3,Apollo采用压缩的联合查找算法(Union Find algorithm )有效查找连接组件,每个组件都是候选障碍物对象集群。对象是单个单元格成为有效对象的概率。因此,Apollo将非对象单元定义为目标小于0.5的单元格。因此,Apollo过滤出每个候选对象集群的空单元格和非对象集。 - -
- -
图 3 障碍聚类
- -(a) 红色箭头表示每个单元格对象中心偏移预测;蓝色填充对应于物体概率不小于0.5的对象单元。 - -(b) 固体红色多边形内的单元格组成候选对象集群。 - -由五角星填充的红色范围表示对应于连接组件子图的根节点(单元格)。 - -一个候选对象集群可以由其根节点彼此相邻的多个相邻连接组件组成。 - -### 后期处理 - -聚类后,Apollo获得一组候选对象集,每个候选对象集包括若干单元格。 - -在后期处理中,Apollo首先对所涉及的单元格的积极性和物体高度值,平均计算每个候选群体的检测置信度分数和物体高度。 然后,Apollo去除相对于预测物体高度太高的点,并收集每个候选集中的有效单元格的点。 最后,Apollo删除具有非常低的可信度分数或小点数的候选聚类,以输出最终的障碍物集/分段。 - -用户定义的参数可以在`modules/perception/model/cnn_segmentation/cnnseg.conf`的配置文件中设置。 下表说明了CNN细分的参数用法和默认值: - - - |参数名称 |使用说明 |默认值 | - |-----------------------------------|--------------------------------------------------------------------------------------------|-----------| - |objectness_thresh |用于在障碍物聚类步骤中过滤掉非对象单元的对象的阈值。 |0.5 | - |use_all_grids_for_clustering |指定是否使用所有单元格在障碍物聚类步骤中构建图形的选项。如果不是,则仅考虑占用的单元格。 |true | - |confidence_thresh |用于在后期处理过程中滤出候选聚类的检测置信度得分阈值。 |0.1 | - |height_thresh |如果是非负数,则在后处理步骤中将过滤掉高于预测物体高度的点。 |0.5 meters | - |min_pts_num |在后期处理中,删除具有小于min_pts_num点的候选集群。 |3 | - |use_full_cloud |如果设置为true,则原始点云的所有点将用于提取通道特征。 否则仅使用输入点云的点(即,HDMap ROI过滤器之后的点)。 |true | - |gpu_id |在基于CNN的障碍物预测步骤中使用的GPU设备的ID。 |0 | - |feature_param {width} |2D网格的X轴上的单元格数。 |512 | - |feature_param {height} |2D网格的Y轴上的单元格数。 |512 | - |feature_param {range} |2D格栅相对于原点(LiDAR传感器)的范围。 |60 meters | - -**注意:提供的模型是一个样例,仅限于实验所用。** - -MinBox 障碍物边框构建 --------------- - -对象构建器组件为检测到的障碍物建立一个边界框。因为LiDAR传感器的遮挡或距离,形成障碍物的点云可以是稀疏的,并且仅覆盖一部分表面。因此,盒构建器将恢复给定多边形点的完整边界框。即使点云稀疏,边界框的主要目的还是预估障碍物(例如,车辆)的方向。同样地,边框也用于可视化障碍物。 - -算法背后的想法是找到给定多边形点边缘的所有区域。在以下示例中,如果AB是边缘,则Apollo将其他多边形点投影到AB上,并建立具有最大距离的交点对,这是属于边框的边缘之一。然后直接获得边界框的另一边。通过迭代多边形中的所有边,在以下图4所示,Apollo确定了一个6边界边框,将选择具有最小面积的方案作为最终的边界框。 - -
- -
图 4 MinBox 对象构建
- -HM对象跟踪 ------------------ - -HM对象跟踪器跟踪分段检测到的障碍物。通常,它通过将当前检测与现有跟踪列表相关联,来形成和更新跟踪列表,如不再存在,则删除旧的跟踪列表,并在识别出新的检测时生成新的跟踪列表。 更新后的跟踪列表的运动状态将在关联后进行估计。 在HM对象跟踪器中,**匈牙利算法**(Hungarian algorithm)用于检测到跟踪关联,并采用 **鲁棒卡尔曼滤波器**(Robust Kalman Filter) 进行运动估计。 - -### 检测跟踪关联(Detection-to-Track Association) - -当将检测与现有跟踪列表相关联时,Apollo构建了一个二分图,然后使用 **匈牙利算法**以最小成本(距离)找到最佳检测跟踪匹配。 - -**计算关联距离矩阵** - -首先,建立一个关联距离矩阵。根据一系列关联特征(包括运动一致性,外观一致性等)计算给定检测和一条轨迹之间的距离。HM跟踪器距离计算中使用的一些特征如下所示: - - |关联特征名称 |描述 | - |-------------------------|----------------------------------| - |location_distance |评估运动一致性 | - |direction_distance |评估运动一致性 | - |bbox_size_distance |评估外观一致性 | - |point_num_distance |评估外观一致性 | - |histogram_distance |评估外观一致性 | - -此外,还有一些重要的距离权重参数,用于将上述关联特征组合成最终距离测量。 - -**匈牙利算法的二分图匹配** - -给定关联距离矩阵,如图5所示,Apollo构造了一个二分图,并使用 **匈牙利算法**通过最小化距离成本找到最佳的检测跟踪匹配。它解决了O(n\^3)时间复杂度中的赋值问题。 为了提高其计算性能,通过删除距离大于合理的最大距离阈值的顶点,将原始的二分图切割成子图后实现了匈牙利算法。 - -
- -
图 5 二分图匹配(Bipartite Graph Matching)
- -### 跟踪动态预估 (Track Motion Estimation) - -在检测到跟踪关联之后,HM对象跟踪器使用 **鲁棒卡尔曼滤波器**来利用恒定速度运动模型估计当前跟踪列表的运动状态。 运动状态包括锚点和速度,分别对应于3D位置及其3D速度。 为了克服由不完美的检测引起的可能的分心,在跟踪器的滤波算法中实现了鲁棒统计技术。 - -**观察冗余** - -在一系列重复观测中选择速度测量,即滤波算法的输入,包括锚点移位、边界框中心偏移、边界框角点移位等。冗余观测将为滤波测量带来额外的鲁棒性, 因为所有观察失败的概率远远小于单次观察失败的概率。 - -**分解** - -高斯滤波算法 (Gaussian Filter algorithms)总是假设它们的高斯分布产生噪声。 然而,这种假设可能在运动预估问题中失败,因为其测量的噪声可能来自直方分布。 为了克服更新增益的过度估计,在过滤过程中使用故障阈值。 - -**更新关联质量** - -原始卡尔曼滤波器更新其状态不区分其测量的质量。 然而,质量是滤波噪声的有益提示,可以估计。 例如,在关联步骤中计算的距离可以是一个合理的测量质量估计。 根据关联质量更新过滤算法的状态,增强了运动估计问题的鲁棒性和平滑度。 - -HM对象跟踪器的高级工作流程如图6所示。 - -
- -
图 6 HM对象跟踪器工作流
- -1)构造跟踪对象并将其转换为世界坐标。 - -2)预测现有跟踪列表的状态,并对其匹配检测。 - -3)在更新后的跟踪列表中更新运动状态,并收集跟踪结果。 - -## 参考 -- [匈牙利算法](https://zh.wikipedia.org/zh-cn/%E5%8C%88%E7%89%99%E5%88%A9%E7%AE%97%E6%B3%95) -- [地方坐标系](https://baike.baidu.com/item/%E5%9C%B0%E6%96%B9%E5%9D%90%E6%A0%87%E7%B3%BB/5154246) -- [Fully Convolutional Networks for Semantic Segmentation](https://people.eecs.berkeley.edu/~jonlong/long_shelhamer_fcn.pdf) - - - -# ============================== -# Planning模块架构和概述 - -## 数据输入和输出 - -### 输出数据 - -Planning模块的输出数据类型定义在`planning.proto`,如下图所示: - -![img](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/class_architecture_planning/image001.png) - -#### *planning.proto* - -在proto数据的定义中,输出数据包括总时间、总长度和确切的路径信息,输出数据由控制单元解析执行,输出数据结构定义在`repeated apollo.common.TrajectoryPointtrajectory_point`。 - -`trajectory point`类继承自`path_point`类,并新增了speed、acceleration和timing属性。 -定义在`pnc_point.proto`中的`trajectory_point`包含了路径的详细属性。 - -![img](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/class_architecture_planning/image002.png) - -![img](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/class_architecture_planning/image003.png) - -除了路径信息,Planning模块输出了多种注释信息。主要的注释数据包括: - -- Estop -- DecisionResult -- 调试信息 - -`Estop`是标示了错误和异常的指令。例如,当自动驾驶的车辆碰到了障碍物或者无法遵守交通规则时将发送estop信号。`DecisionResult`主要用于展示模拟的输出结果以方便开发者更好的了解Planning模块的计算结果。更多详细的中间值结果会被保存并输出作为调试信息供后续的调试使用。 - -## 输入数据 - -为了计算最终的输出路径,Planning模块需要统一的规划多个输入数据。Planning模块的输入数据包括: - -- Routing -- 感知和预测 -- 车辆状态和定位 -- 高清地图 - -Routing定义了概念性问题“我想去哪儿”,消息定义在`routing.proto`文件中。`RoutingResponse`包含了`RoadSegment`,`RoadSegment`指明了车辆到达目的地应该遵循的路线。 - -![img](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/class_architecture_planning/image004.png) - -关于概念性问题“我周围有什么”的消息定义在`perception_obstacles.proto`和`traffic_light_detection.proto`中。`perception_obstacles.proto`定义了表示车辆周围的障碍物的数据,车辆周围障碍物的数据由感知模块提供。`traffic_light_detection`定义了信号灯状态的数据。除了已被感知的障碍物外,动态障碍物的路径预测对Planning模块也是非常重要的数据,因此`prediction.proto`封装了`perception_obstacle`消息来表示预测路径。请参考下述图片: - -![img](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/class_architecture_planning/image005.png) - -每个预测的路径都有其单独的可能性,而且每个动态障碍物可能有多个预测路径。 - -除了概念性问题“我想去哪儿”和“我周围有什么”,另外一个重要的概念性问题是“我在哪”。关于该问题的数据通过高清地图和定位模块获得。定位信息和车辆车架信息被封装在`VehicleState`消息中,该消息定义在`vehicle_state.proto`,参考下述图片: - -![img](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/class_architecture_planning/image009.png) - -## 代码结构和类层次 - -代码组织方式如下图所示:Planning模块的入口是`planning.cc`。在Planning模块内部,重要的类在下图中展示。 - -![img](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/class_architecture_planning/image006.png) - -`ReferenceLineInfo`对`ReferenceLine`类进行了封装,为Planning模块提供了平滑的指令执行序列。 -**Frame**包含了所有的数据依赖关系,例如包含了预测路径信息的障碍物,自动驾驶车辆的状态等。 -**HD-Ma**p在Planning模块内作为封装了多个数据的库使用,提供不同特点的地图数据查询需求。 -**EM Planne**r执行具体的Planning任务,继承自**Planner**类。Apollo2.0中的**EM Planner**类和之前发布的**RTK Planner**类都继承自Planner类。 - -![img](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/class_architecture_planning/image007.png) - -例如,在EM Planner执行的一次planning循环的内部,采用迭代执行的方法,tasks的三个类别交替执行。“**决策/优化**”类的关系在下述图片中展示: - -![img](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/class_architecture_planning/image008.png) - -- **Deciders** 包括 traffic decider, path decider and speed decider. - -- **Path Optimizers** 为DP/QP path optimizers. - -- **Speed Optimizers** 为DP/QP speed optimizers. - -| **附注:** | -| ---------------------------------------- | -| DP表示动态规划(dynamic programming),QP表示二次规划(quadratic programming)。经过计算步骤后,最终的路径数据经过处理后传递到下一个节点模块进行路径的执行。 | - - - -# ===================== -# 二次规划(QP)样条路径优化 - -_**Tip**: 为了更好的展示本文档中的等式,我们建议使用者使用带有[插件](https://chrome.google.com/webstore/detail/tex-all-the-things/cbimabofgmfdkicghcadidpemeenbffn)的Chrome浏览器,或者将Latex等式拷贝到[在线编辑公式网站](http://www.hostmath.com/)进行浏览。_ - -二次规划(QP)+样条插值 - -## 1. 目标函数 - -### 1.1 获得路径长度 - -路径定义在station-lateral坐标系中。**s**的变化区间为从车辆当前位置点到默认路径的长度。 - -### 1.2 获得样条段 - -将路径划分为**n**段,每段路径用一个多项式来表示。 - -### 1.3 定义样条段函数 - -每个样条段 ***i*** 都有沿着参考线的累加距离$d_i$。每段的路径默认用5介多项式表示。 - -

-$$ -l = f_i(s) - = a_{i0} + a_{i1} \cdot s + a_{i2} \cdot s^2 + a_{i3} \cdot s^3 + a_{i4} \cdot s^4 + a_{i5} \cdot s^5 (0 \leq s \leq d_{i}) -$$ -

- -l=fi(s)=ai0+ai1⋅s+ai2⋅s2+ai3⋅s3+ai4⋅s4+ai5⋅s5(0≤s≤di) - -### 1.4 定义每个样条段优化目标函数 - -

-$$ -cost = \sum_{i=1}^{n} \Big( w_1 \cdot \int\limits_{0}^{d_i} (f_i')^2(s) ds + w_2 \cdot \int\limits_{0}^{d_i} (f_i'')^2(s) ds + w_3 \cdot \int\limits_{0}^{d_i} (f_i^{\prime\prime\prime})^2(s) ds \Big) -$$ -

- -### 1.5 将开销(cost)函数转换为QP公式 - -QP公式: -

-$$ -\begin{aligned} -minimize & \frac{1}{2} \cdot x^T \cdot H \cdot x + f^T \cdot x \\ -s.t. \qquad & LB \leq x \leq UB \\ - & A_{eq}x = b_{eq} \\ - & Ax \geq b -\end{aligned} -$$ -

-下面是将开销(cost)函数转换为QP公式的例子: -

-$$ -f_i(s) = -\begin{vmatrix} 1 & s & s^2 & s^3 & s^4 & s^5 \end{vmatrix} -\cdot -\begin{vmatrix} a_{i0} \\ a_{i1} \\ a_{i2} \\ a_{i3} \\ a_{i4} \\ a_{i5} \end{vmatrix} -$$ -

- -且 -

-$$ -f_i'(s) = -\begin{vmatrix} 0 & 1 & 2s & 3s^2 & 4s^3 & 5s^4 \end{vmatrix} -\cdot -\begin{vmatrix} a_{i0} \\ a_{i1} \\ a_{i2} \\ a_{i3} \\ a_{i4} \\ a_{i5} \end{vmatrix} -$$ -

- - -且 -

-$$ -f_i'(s)^2 = -\begin{vmatrix} a_{i0} & a_{i1} & a_{i2} & a_{i3} & a_{i4} & a_{i5} \end{vmatrix} -\cdot -\begin{vmatrix} 0 \\ 1 \\ 2s \\ 3s^2 \\ 4s^3 \\ 5s^4 \end{vmatrix} -\cdot -\begin{vmatrix} 0 & 1 & 2s & 3s^2 & 4s^3 & 5s^4 \end{vmatrix} -\cdot -\begin{vmatrix} a_{i0} \\ a_{i1} \\ a_{i2} \\ a_{i3} \\ a_{i4} \\ a_{i5} \end{vmatrix} -$$ -

-然后得到, -

-$$ -\int\limits_{0}^{d_i} f_i'(s)^2 ds = -\int\limits_{0}^{d_i} -\begin{vmatrix} a_{i0} & a_{i1} & a_{i2} & a_{i3} & a_{i4} & a_{i5} \end{vmatrix} -\cdot -\begin{vmatrix} 0 \\ 1 \\ 2s \\ 3s^2 \\ 4s^3 \\ 5s^4 \end{vmatrix} -\cdot -\begin{vmatrix} 0 & 1 & 2s & 3s^2 & 4s^3 & 5s^4 \end{vmatrix} -\cdot -\begin{vmatrix} a_{i0} \\ a_{i1} \\ a_{i2} \\ a_{i3} \\ a_{i4} \\ a_{i5} \end{vmatrix} ds -$$ -

- - -从聚合函数中提取出常量得到, -

-$$ -\int\limits_{0}^{d_i} f'(s)^2 ds = -\begin{vmatrix} a_{i0} & a_{i1} & a_{i2} & a_{i3} & a_{i4} & a_{i5} \end{vmatrix} -\cdot -\int\limits_{0}^{d_i} -\begin{vmatrix} 0 \\ 1 \\ 2s \\ 3s^2 \\ 4s^3 \\ 5s^4 \end{vmatrix} -\cdot -\begin{vmatrix} 0 & 1 & 2s & 3s^2 & 4s^3 & 5s^4 \end{vmatrix} ds -\cdot -\begin{vmatrix} a_{i0} \\ a_{i1} \\ a_{i2} \\ a_{i3} \\ a_{i4} \\ a_{i5} \end{vmatrix} -$$ -$$ -=\begin{vmatrix} a_{i0} & a_{i1} & a_{i2} & a_{i3} & a_{i4} & a_{i5} \end{vmatrix} -\cdot \int\limits_{0}^{d_i} -\begin{vmatrix} -0 & 0 &0&0&0&0\\ -0 & 1 & 2s & 3s^2 & 4s^3 & 5s^4\\ -0 & 2s & 4s^2 & 6s^3 & 8s^4 & 10s^5\\ -0 & 3s^2 & 6s^3 & 9s^4 & 12s^5&15s^6 \\ -0 & 4s^3 & 8s^4 &12s^5 &16s^6&20s^7 \\ -0 & 5s^4 & 10s^5 & 15s^6 & 20s^7 & 25s^8 -\end{vmatrix} ds -\cdot -\begin{vmatrix} a_{i0} \\ a_{i1} \\ a_{i2} \\ a_{i3} \\ a_{i4} \\ a_{i5} \end{vmatrix} -$$ -

- -最后得到, - -

-$$ -\int\limits_{0}^{d_i} -f'_i(s)^2 ds =\begin{vmatrix} a_{i0} & a_{i1} & a_{i2} & a_{i3} & a_{i4} & a_{i5} \end{vmatrix} -\cdot \begin{vmatrix} -0 & 0 & 0 & 0 &0&0\\ -0 & d_i & d_i^2 & d_i^3 & d_i^4&d_i^5\\ -0& d_i^2 & \frac{4}{3}d_i^3& \frac{6}{4}d_i^4 & \frac{8}{5}d_i^5&\frac{10}{6}d_i^6\\ -0& d_i^3 & \frac{6}{4}d_i^4 & \frac{9}{5}d_i^5 & \frac{12}{6}d_i^6&\frac{15}{7}d_i^7\\ -0& d_i^4 & \frac{8}{5}d_i^5 & \frac{12}{6}d_i^6 & \frac{16}{7}d_i^7&\frac{20}{8}d_i^8\\ -0& d_i^5 & \frac{10}{6}d_i^6 & \frac{15}{7}d_i^7 & \frac{20}{8}d_i^8&\frac{25}{9}d_i^9 -\end{vmatrix} -\cdot -\begin{vmatrix} a_{i0} \\ a_{i1} \\ a_{i2} \\ a_{i3} \\ a_{i4} \\ a_{i5} \end{vmatrix} -$$ -

- -请注意我们最后得到一个6介的矩阵来表示5介样条插值的衍生开销。 -应用同样的推理方法可以得到2介,3介样条插值的衍生开销。 - -## 2 约束条件 - -### 2.1 初始点约束 - -假设第一个点为 ($s_0$, $l_0$), ($s_0$, $l'_0$) and ($s_0$, $l''_0$),其中$l_0$ , $l'_0$ and $l''_0$表示横向的偏移,并且规划路径的起始点的第一,第二个点的衍生开销可以从$f_i(s)$, $f'_i(s)$, $f_i(s)''$计算得到。 - -将上述约束转换为QP约束等式,使用等式: - -

-$$ -A_{eq}x = b_{eq} -$$ -

- -下面是转换的具体步骤: - -

-$$ -f_i(s_0) = -\begin{vmatrix} 1 & s_0 & s_0^2 & s_0^3 & s_0^4&s_0^5 \end{vmatrix} -\cdot -\begin{vmatrix} a_{i0} \\ a_{i1} \\ a_{i2} \\ a_{i3} \\ a_{i4} \\ a_{i5}\end{vmatrix} = l_0 -$$ -

-且 -

-$$ -f'_i(s_0) = -\begin{vmatrix} 0& 1 & 2s_0 & 3s_0^2 & 4s_0^3 &5 s_0^4 \end{vmatrix} -\cdot -\begin{vmatrix} a_{i0} \\ a_{i1} \\ a_{i2} \\ a_{i3} \\ a_{i4} \\ a_{i5} \end{vmatrix} = l'_0 -$$ -

-且 -

-$$ -f''_i(s_0) = -\begin{vmatrix} 0&0& 2 & 3\times2s_0 & 4\times3s_0^2 & 5\times4s_0^3 \end{vmatrix} -\cdot -\begin{vmatrix} a_{i0} \\ a_{i1} \\ a_{i2} \\ a_{i3} \\ a_{i4} \\ a_{i5} \end{vmatrix} = l''_0 -$$ -

-其中,i是包含$s_0$的样条段的索引值。 - -### 2.2 终点约束 - -和起始点相同,终点$(s_e, l_e)$ 也应当按照起始点的计算方法生成约束条件。 - -将起始点和终点组合在一起,得出约束等式为: - -

-$$ -\begin{vmatrix} - 1 & s_0 & s_0^2 & s_0^3 & s_0^4&s_0^5 \\ - 0&1 & 2s_0 & 3s_0^2 & 4s_0^3 & 5s_0^4 \\ - 0& 0&2 & 3\times2s_0 & 4\times3s_0^2 & 5\times4s_0^3 \\ - 1 & s_e & s_e^2 & s_e^3 & s_e^4&s_e^5 \\ - 0&1 & 2s_e & 3s_e^2 & 4s_e^3 & 5s_e^4 \\ - 0& 0&2 & 3\times2s_e & 4\times3s_e^2 & 5\times4s_e^3 - \end{vmatrix} - \cdot - \begin{vmatrix} a_{i0} \\ a_{i1} \\ a_{i2} \\ a_{i3} \\ a_{i4} \\ a_{i5} \end{vmatrix} - = - \begin{vmatrix} - l_0\\ - l'_0\\ - l''_0\\ - l_e\\ - l'_e\\ - l''_e\\ - \end{vmatrix} -$$ -

- -### 2.3 平滑节点约束 - -该约束的目的是使样条的节点更加平滑。假设两个段$seg_k$ 和$seg_{k+1}$互相连接,且$seg_k$的累计值s为$s_k$。计算约束的等式为: - -

-$$ -f_k(s_k) = f_{k+1} (s_0) -$$ -

-下面是计算的具体步骤: -

-$$ -\begin{vmatrix} - 1 & s_k & s_k^2 & s_k^3 & s_k^4&s_k^5 \\ - \end{vmatrix} - \cdot - \begin{vmatrix} - a_{k0} \\ a_{k1} \\ a_{k2} \\ a_{k3} \\ a_{k4} \\ a_{k5} - \end{vmatrix} - = -\begin{vmatrix} - 1 & s_{0} & s_{0}^2 & s_{0}^3 & s_{0}^4&s_{0}^5 \\ - \end{vmatrix} - \cdot - \begin{vmatrix} - a_{k+1,0} \\ a_{k+1,1} \\ a_{k+1,2} \\ a_{k+1,3} \\ a_{k+1,4} \\ a_{k+1,5} - \end{vmatrix} -$$ -

-然后 -

-$$ -\begin{vmatrix} - 1 & s_k & s_k^2 & s_k^3 & s_k^4&s_k^5 & -1 & -s_{0} & -s_{0}^2 & -s_{0}^3 & -s_{0}^4&-s_{0}^5\\ - \end{vmatrix} - \cdot - \begin{vmatrix} - a_{k0} \\ a_{k1} \\ a_{k2} \\ a_{k3} \\ a_{k4} \\ a_{k5} \\ a_{k+1,0} \\ a_{k+1,1} \\ a_{k+1,2} \\ a_{k+1,3} \\ a_{k+1,4} \\ a_{k+1,5} - \end{vmatrix} - = 0 -$$ -

-将$s_0$ = 0代入等式。 - -同样地,可以为下述等式计算约束等式: -

-$$ -f'_k(s_k) = f'_{k+1} (s_0) -\\ -f''_k(s_k) = f''_{k+1} (s_0) -\\ -f'''_k(s_k) = f'''_{k+1} (s_0) -$$ -

- -### 2.4 点采样边界约束 - -在路径上均匀的取样**m**个点,检查这些点上的障碍物边界。将这些约束转换为QP约束不等式,使用不等式: - -

-$$ -Ax \geq b -$$ -

- -首先基于道路宽度和周围的障碍物找到点 $(s_j, l_j)$的下边界$l_{lb,j}$,且$j\in[0, m]$。计算约束的不等式为: - -

-$$ -\begin{vmatrix} - 1 & s_0 & s_0^2 & s_0^3 & s_0^4&s_0^5 \\ - 1 & s_1 & s_1^2 & s_1^3 & s_1^4&s_1^5 \\ - ...&...&...&...&...&... \\ - 1 & s_m & s_m^2 & s_m^3 & s_m^4&s_m^5 \\ - \end{vmatrix} \cdot \begin{vmatrix}a_{i0} \\ a_{i1} \\ a_{i2} \\ a_{i3} \\ a_{i4} \\ a_{i5} \end{vmatrix} - \geq - \begin{vmatrix} - l_{lb,0}\\ - l_{lb,1}\\ - ...\\ - l_{lb,m}\\ - \end{vmatrix} -$$ -

- - -同样地,对上边界$l_{ub,j}$,计算约束的不等式为: -

-$$ -\begin{vmatrix} - -1 & -s_0 & -s_0^2 & -s_0^3 & -s_0^4&-s_0^5 \\ - -1 & -s_1 & -s_1^2 & -s_1^3 & -s_1^4&-s_1^5 \\ - ...&...-&...&...&...&... \\ - -1 & -s_m & -s_m^2 & -s_m^3 & -s_m^4&-s_m^5 \\ - \end{vmatrix} - \cdot - \begin{vmatrix} a_{i0} \\ a_{i1} \\ a_{i2} \\ a_{i3} \\ a_{i4} \\ a_{i5} \end{vmatrix} - \geq - -1 \cdot - \begin{vmatrix} - l_{ub,0}\\ - l_{ub,1}\\ - ...\\ - l_{ub,m}\\ - \end{vmatrix} -$$ -

- - - - -# ====================== -# Apollo 3.0传感器安装指南 - -## 需要的硬件 - -![Image](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/perception_required_hardware.png) - -外部设备 - -![Image](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/perception_peripherals.png) - -## 坐标系 - -单位:毫米(mm) - -原点:车辆后轮轴中心 - -![Image](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/perception_setup_figure1.png) - -**Figure 1. 原点和坐标系** - -![Image](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/perception_setup_figure2.png) - -**Figure 2. 卡车坐标系和安装摄像机与雷达的示意图** - -## 传感器安装指南 -### IMU/GPS -IMU/GPS需要安装在靠近后车轮毂的位置。GPS天线需要安装在车辆顶部。 -### Radar -远程雷达需要安装在车辆前保险杠上,请参考Figure 1 and Figure 2展示的信息。 -### Camera -一个6mm镜头的摄像机应该面向车辆的前方。前向摄像机应当安装在车辆前部的中心位置,离地面高度为1600mm到2000mm(Camera 1),或者安装在车辆挡风玻璃上(Camera 2)。 - -![Image](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/perception_setup_figure3.png) - -**Figure 3. 安装摄像机的示例图** - -摄像机安装完成后,摄像机w、r、t的物理坐标x、y、z应该被记录在校准文件里。 - -#### 安装摄像机后的检验 - -三个摄像机的方位应当全部设置为0。摄像机安装后,需要车辆在公路以直线开动一段距离并记录一个rosbag,通过rosbag的回放,摄像机的方位需要重新调整以设置间距、偏航角并将角度转置为0度。如果摄像机被正确的安装,地平线应该在画面高度方向上的正中间并且不倾斜。灭点同样应该在画面的正中间。请参考下述图片以将摄像机设置为最佳状态: - -![Image](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/perception_setup_figure4.png) - -**Figure 4. 摄像机安装后的画面示例。地平线应该在画面高度方向上的正中间并且不倾斜。灭点同样应该在画面的正中间。 红色线段显示了画面高度和宽度方向上的中点。** - -估测的平移参数的示例如下所示: -``` -header: - seq: 0 - stamp: - secs: 0 - nsecs: 0 - frame_id: white_mkz -child_frame_id: onsemi_obstacle -transform: - rotation: - x: 0.5 - y: -0.5 - z: 0.5 - w: -0.5 - translation: - x: 1.895 - y: -0.235 - z: 1.256 -``` -如果角度不为0,则上述数据需要重新校准并在四元数中表示(参考上例中的transform->rotation ) - - -# =================== -# Apollo坐标系统 - -我们欢迎每一位开发者加入Apollo开发平台。Apollo系统涉及到了多种坐标系。在本文档中,我们将讨论在Apollo系统中使用的各个坐标系的定义。 - -## 1. 全球地理坐标系统 - -在Apollo系统中,我们采用全球地理坐标系统来表示高精地图(HD Map)中各个元素的地理位置。全球地理坐标系统的通常用途是用来表示纬度、经度和海拔。Apollo采用的是WGS84(World Geodetic System 1984)作为标准坐标系来表示物体的纬度和经度。通过使用该标准坐标系统,我们可以使用2个数字:x坐标和y坐标来唯一的确定地球表面上除北极点之外的所有点,其中x坐标表示经度,y坐标表示纬度。WGS-84常用于GIS服务,例如地图绘制、定位和导航等。全球地理坐标系统的定义在下图中展示。 - -![Image](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/coordination_01.png) - -## 2. 局部坐标系 – 东-北-上(East-North-Up ENU) - -在Apollo系统中,局部坐标系的定义为: - -z轴 – 指向上方(和重力线成一条直线) - -y轴 – 指向北面 - -x轴 – 指向东面 - -![Image](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/coordination_02.png) - -ENU局部坐标系依赖于在地球表面上建立的3D笛卡尔坐标系。 -通用横轴墨卡托正形投影(Universal Transverse Mercator UTM)使用2D的笛卡尔坐标系来给出地球表面点的位置。这不仅只是一次地图的映射。该坐标系统将地球划分为60个区域,每个区域表示为6度的经度带,并且在每个区域上使用割线横轴墨卡托投影。在Apollo系统中,UTM坐标系统在定位、Planning等模块中作为局部坐标系使用。 - -![Image](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/coordination_03.png) - -关于UTM坐标系统的使用,我们遵从国际标准规范。开发者可以参考下述网站获取更多细节: - -[http://geokov.com/education/utm.aspx](http://geokov.com/education/utm.aspx) - -[https://en.wikipedia.org/wiki/Universal_Transverse_Mercator_coordinate_system](https://en.wikipedia.org/wiki/Universal_Transverse_Mercator_coordinate_system) - -## 3. 车辆坐标系 – 右-前-上(Right-Forward-Up RFU) - -车辆坐标系的定义为: - -z轴 – 通过车顶垂直于地面指向上方 - -y轴 – 在行驶的方向上指向车辆前方 - -x轴 – 面向前方时,指向车辆右侧 - -车辆坐标系的原点在车辆后轮轴的中心。 - -![Image](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/coordination_04.png) - -# ============================================== -# DreamView用法介绍 - -DreamView是一个web应用程序,提供如下的功能: -1. 可视化显示当前自动驾驶车辆模块的输出信息,例如规划路径、车辆定位、车架信息等。 -2. 为使用者提供人机交互接口以监测车辆硬件状态,对模块进行开关操作,启动自动驾驶车辆等。 -3. 提供调试工具,例如PnC监视器可以高效的跟踪模块输出的问题 - -## 界面布局和特性 - -该应用程序的界面被划分为多个区域:标题、侧边栏、主视图和工具视图。 - -### 标题 -标题包含4个下拉列表,可以像下述图片所示进行操作: -![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/header.png) - -附注:导航模块是在Apollo 2.5版本引入的满足低成本测试的特性。在该模式下,Baidu或Google地图展现的是车辆的绝对位置,而主视图中展现的是车辆的相对位置。 - -### 侧边栏和工具视图 -![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/sidebar.png) -侧边栏控制着显示在工具视图中的模块 - -### Tasks -在DreamView中使用者可以操作的tasks有: -![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/tasks.png) - -* **Quick Start**: 当前选择的模式支持的指令。通常情况下, - - **setup**: 开启所有模块 - - **reset all**: 关闭所有模块 - - **start auto**: 开始车辆的自动驾驶 -* **Others**: 工具经常使用的开关和按钮 -* **Module Delay**: 从模块中输出的两次事件的时间延迟 -* **Console**: 从Apollo平台输出的监视器信息 - -### Module Controller -监视硬件状态和对模块进行开关操作 -![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/module_controller.png) - -### Layer Menu -显式控制各个元素是否显示的开关 -![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/layer_menu.png) - -### Route Editing -在向Routing模块发送寻路信息请求前可以编辑路径信息的可视化工具 -![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/route_editing.png) - -### Data Recorder -将问题报告给rosbag中的drive event的界面 -![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/data_recorder.png) - -### Default Routing -预先定义的路径或者路径点,该路径点称为兴趣点(POI)。 - -![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/default_routing.png) - -如果打开了路径编辑模式,路径点可被显式的在地图上添加。 - -如果关闭了路径编辑模式,点击一个期望的POI会向服务器发送一次寻路请求。如果只选择了一个点,则寻路请求的起点是自动驾驶车辆的当前点。否则寻路请求的起点是选择路径点中的第一个点。 - -查看Map目录下的[default_end_way_point.txt](https://github.com/ApolloAuto/apollo/blob/master/modules/map/data/demo/default_end_way_point.txt)文件可以编译POI信息。例如,如果选择的地图模式为“Demo”,则在`modules/map/data/demo`目录下可以查看对应的 [default_end_way_point.txt](https://github.com/ApolloAuto/apollo/blob/master/modules/map/data/demo/default_end_way_point.txt) 文件。 - -### 主视图 -主视图在web页面中以动画的方式展示3D计算机图形 - -![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/mainview.png) - -下表列举了主视图中各个元素: - -| Visual Element | Depiction Explanation | -| ---------------------------------------- | ---------------------------------------- | -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image002.png) |
  • 自动驾驶车辆
| -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image004.png) |
  • 车轮转动的比率
  • 左右转向灯的状态
| -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image003.png) |
  • 交通信号灯状态
| -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image005.png) |
  • 驾驶状态(AUTO/DISENGAGED/MANUAL等)
| -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image006.png) |
  • 行驶速度 km/h
  • 加速速率/刹车速率
| -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image026.png) |
  • 红色粗线条表示建议的寻路路径
| -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image038.png) |
  • 轻微移动物体决策—橙色表示应该避开的区域
| -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image062.png) |
  • 绿色的粗曲线条带表示规划的轨迹
| - -#### 障碍物 - -| Visual Element | Depiction Explanation | -| ---------------------------------------- | ---------------------------------------- | -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image010.png) |
  • 车辆障碍物
| -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image012.png) |
  • 行人障碍物
| -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image014.png) |
  • 自行车障碍物
| -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image016.png) |
  • 未知障碍物
| -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image018.png) |
  • 速度方向显示了移动物体的方向,长度随速度按照比率变化
| -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image020.png) |
  • 白色箭头显示了障碍物的移动方向
| -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image022.png) | 黄色文字表示:
  • 障碍物的跟踪ID
  • 自动驾驶车辆和障碍物的距离及障碍物速度
| -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image024.png) |
  • 线条显示了障碍物的预测移动轨迹,线条标记为和障碍物同一个颜色
| - -#### Planning决策 -##### 决策栅栏区 - -决策栅栏区显示了Planning模块对车辆障碍物做出的决策。每种类型的决策会表示为不同的颜色和图标,如下图所示: - -| Visual Element | Depiction Explanation | -| ---------------------------------------- | ---------------------------------------- | -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image028.png) |
  • **停止** 表示物体主要的停止原因
| -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image030.png) |
  • **停止** 表示物体的停止原因n
| -| ![2](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image032.png) |
  • **跟车** 物体
| -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image034.png) |
  • **让行** 物体决策—点状的线条连接了各个物体
| -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image036.png) |
  • **超车** 物体决策—点状的线条连接了各个物体
| - -线路变更是一个特殊的决策,因此不显示决策栅栏区,而是将路线变更的图标显示在车辆上。 - -| Visual Element | Depiction Explanation | -| ---------------------------------------- | ---------------------------------------- | -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/change-lane-left.png) |
  • 变更到**左**车道
| -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/change-lane-right.png) |
  • 变更到**右**车道
| - -在优先通行的规则下,当在交叉路口的停车标志处做出让行决策时,被让行的物体在头顶会显示让行图标 - -| Visual Element | Depiction Explanation | -| ---------------------------------------------------- | ------------------------------ | -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image037.png) | 停止标志处的让行物体 | - -##### 停止原因 - -如果显示了停止决策栅栏区,则停止原因展示在停止图标的右侧。可能的停止原因和对应的图标为: - -| Visual Element | Depiction Explanation | -| ---------------------------------------- | ---------------------------------------- | -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image040.png) |
  • **前方道路侧边区域**
| -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image042.png) |
  • **前方人行道**
| -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image044.png) |
  • **到达目的地**
| -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image046.png) |
  • **紧急停车**
| -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image048.png) |
  • **自动驾驶模式未准备好**
| -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image050.png) |
  • **障碍物阻塞道路**
| -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image052.png) |
  • **前方行人穿越**
| -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image054.png) |
  • **黄/红信号灯**
| -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image056.png) |
  • **前方有车辆**
| -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image058.png) |
  • **前方停止标志**
| -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/0clip_image060.png) |
  • **前方让行标志**
| - -#### 视图 -可以在主视图中展示多种从**Layer Menu**选择的视图模式: - -| Visual Element | Point of View | -| ---------------------------------------- | ---------------------------------------- | -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/default_view.png) |
  • **默认视图**
| | -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/near_view.png) |
  • **近距离视图**
| | -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/overhead_view.png) |
  • **俯瞰视图**
| | -| ![](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/images/dreamview_usage_table/map_view.png) | **地图**
  • 放大/缩小:滚动鼠标滚轮或使用两根手指滑动
  • 移动:按下右键并拖拽或或使用三根手指滑动
| - - - - -[雷达校准](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/lidar_calibration_cn.pdf) - -[雷达IMU校准](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/apollo_lidar_imu_calibration_guide.md) - - -# ================================ -# Apollo导航模式教程 - -## 1. 教程简介 - -无人驾驶系统利用实时感知信息和静态地图信息构建出完整驾驶环境,并在构建的环境中,依据routing数据,规划出行车轨迹,并由控制模块执行完成。Apollo导航模式在上述的框架下,针对高速、乡村道路等简单道路场景,进行了以下的提升: - -1. Apollo导航模式以提高安全性和稳定性为目的,在驾驶环境中加入了静态引导信息,引导在驾驶环境中的轨迹规划,使其更安全更舒适。同时,引导信息也降低了对驾驶环境的完整性的要求 -- 即降低了对地图信息的要求。 -2. Apollo导航模式使用了相对/车身坐标系。减少了sensor数据的转化。同时也支持各种驾驶模式之间的转化,以应对不同的驾驶场景和条件。 -3. Apollo导航模式引入了百度地图的Routing功能,考虑实时路况信息,使得Routing的结果更实用,更精确,更稳定。也使得Apollo系统更易于落地和商用。 - - - -## 在本教程中,你将完成 - -学习完本教程后,你将能够在导航模式下进行规划模块(planning)的线下调试和开发。 - -## 在本教教中,你将掌握 - -- 如何设置Apollo导航模式 -- 如何利用云端指引者发送指引线 -- 如何利用录制的ros bag产生指引线并用线下指引者发送 -- 如何进行规划模块的调试 - - - -## 在本教程中,你需要如下准备 - -- 下载并编译Apollo最新源码([Howto](https://github.com/ApolloAuto/apollo/tree/master/docs/demo_guide)) - -- 下载 [Apollo2.5 demo bag](https://github.com/ApolloAuto/apollo/releases/download/v2.5.0/demo_2.5.bag) - - -## 2. 配置导航模式 - -在导航模式下,有以下几个参数需要进行配置: - -- 感知方案:目前支持摄像头方案(CAMERA)和基于Mobileye的方案(MOBILEYE) -- Apollo UTM Zone -- 规划模块的Planner:目前支持EM, LATTICE, 和NAVI三种 -- 系统限速:单位为米/秒 - -## 在Docker下修改配置文件 - -配置文件位于: - -```bash -/apollo/modules/tools/navigation/config/default.ini -``` - -默认配置为: - -```bash -[PerceptionConf] -# three perception solutions: MOBILEYE, CAMERA, and VELODYNE64 -perception = CAMERA - -[LocalizationConf] -utm_zone = 10 - -[PlanningConf] -# three planners are available: EM, LATTICE, NAVI -planner_type = EM - -# highest speed for planning algorithms, unit is meter per second -speed_limit = 5 -``` - -该默认配置为Apollo 2.5 Demo bag录制时的配置,在此教程中,我们直接使用。 - -## 生效配置信息 - -为了使配置生效,在Docker内的Apollo根目录下,运行如下命令 - -```bash -in_dev_docker:/apollo$ cd /apollo/modules/tools/navigation/config/ -in_dev_docker:/apollo/modules/tools/navigation/config$ python navi_config.py default.ini -``` - -## 3. 云端指引者的使用 - -## 回放demo bag - -在进入Docker,启动Apollo之前,我们把[Apollo2.5 demo bag](https://github.com/ApolloAuto/apollo/releases/download/v2.5.0/demo_2.5.bag) 拷贝到Apollo代码根目录下的data目录中。 - -在Docker内编译成功后,我们用如下命令启动Dreamview: - -```bash -in_dev_docker:/apollo$ ./scripts/bootstrap.sh start -``` - -并在本地浏览器中打开 - -```bash -http://localhost:8888 -``` - -如下图所示,在模式框中选择“Navigation”。 - -![img](https://github.com/ApolloAuto/apollo/blob/master/docs/technical_tutorial/images/navigation_mode_tutorial/navigation_mode_1_init.png) - -然后在Docker内的apollo根目录下运行如下命令进行bag播放 - -```bash -in_dev_docker:/apollo$cd data -in_dev_docker:/apollo/data$rosbag play demo_2.5.bag -``` - -播放开始后,可以看到Dreamview界面如下 - -![img](https://github.com/ApolloAuto/apollo/blob/master/docs/technical_tutorial/images/navigation_mode_tutorial/navigation_mode_2_play.png) - -## 请求云端指引线 - -在地图中选择一个目的地(沿canada路),点击地图视图中的红色Route按钮,云端指引者会接收到这个请求,并返回指引线,该指引线会被显示在地图视图中。如下图所示。 - -![img](https://github.com/ApolloAuto/apollo/blob/master/docs/technical_tutorial/images/navigation_mode_tutorial/navigation_mode_3_cloud.png) - -以上就是云端指引者的调用过程。 - -## 4. 离线指引者工具的使用 - -目前云端指引者只覆盖了有限的区域。除了云端的服务之外,我们还提供了离线指引者工具来制作和发送线下指引线。在本教程中,我们以[Apollo2.5 demo bag](https://github.com/ApolloAuto/apollo/releases/download/v2.5.0/demo_2.5.bag)为例来生成指引线。 - -## 指引线的制作 - -生成指引线的步骤为 - -- 从bag中提取路径数据 - -```bash -in_dev_docker:/apollo$cd modules/tools/navigator -in_dev_docker:/apollo/modules/tools/navigator$python extractor.py /apollo/data/demo_2.5.bag -``` - -提取出来的路径数据在路径 - -```bash -in_dev_docker:/apollo/modules/tools/navigator$ -``` - -中的 - -```bash -path_demo_2.5.bag.txt -``` - -- 平滑路径数据 - -```bash -in_dev_docker:/apollo/modules/tools/navigator$bash smooth.sh path_demo_2.5.bag.txt 200 -``` - -平滑后的的数据在 - -```bash -in_dev_docker:/apollo/modules/tools/navigator$path_demo_2.5.bag.txt.smoothed -``` - -## 指引线的发送 - -得到平滑后的数据就可以发送到Apollo系统中,作为指引线,步骤为: - -```bash -in_dev_docker:/apollo/modules/tools/navigator$python navigator.py path_demo_2.5.bag.txt.smoothed -``` - -发送完成后,Dreamview的地图视图中的红色指引线会更新为如下图所示: - -![img](https://github.com/ApolloAuto/apollo/blob/master/docs/technical_tutorial/images/navigation_mode_tutorial/navigation_mode_4_offline.png) - -## 5. 规划模块的调试 - -## 调试数据准备 - -利用bag来进行模块调试,首先要把bag中的相应ros message过滤掉。假设我们想要调试规划模块,我们需要把消息 - -``` -/apollo/planning -``` - -过滤,使用以下命令 - -```bash -in_dev_docker:/apollo$cd data -in_dev_docker:/apollo/data$rosbag filter demo_2.5.bag demo_2.5_no_planning.bag "topic != '/apollo/planning'" -``` - -过滤后的bag位于 - -```bash -in_dev_docker:/apollo/data$demo_2.5_no_planning.bag -``` - -## 规划轨迹的产生 - -我们播放没有规划的bag,用下面的命令 - -```bash -in_dev_docker:/apollo/data$rosbag play demo_2.5_no_planning.bag -``` - -在Dreamview中我们会看到车辆的规划轨迹没有输出,如下图 - -![img](https://github.com/ApolloAuto/apollo/blob/master/docs/technical_tutorial/images/navigation_mode_tutorial/navigation_mode_5_no_planning.png) - -我们在Dreamview中打开Navi Planning模块,如下图 - -![img](https://github.com/ApolloAuto/apollo/blob/master/docs/technical_tutorial/images/navigation_mode_tutorial/navigation_mode_6_live_planning.png) - -我们看到实时计算的车辆的规划轨迹显示在Dreamview中。这时你可以试着更改一些规划模块的配置 - -``` -in_dev_docker:/apollo/modules/planning/conf$planning_config_navi.pb.txt -``` - -去了解,这些参数会对规划结果有什么影响。或者修改规划算法的代码,进行调试。 - -## 6.结束 - -恭喜你完成了本教程。现在你应该了解 - -- 如何设置Apollo导航模式 -- 如何利用云端指引者发送指引线 -- 如何利用录制的ros bag产生指引线并用线下指引者发送 -- 如何进行规划模块的调试 - -你也可以试着利用demo bag对其他一些模块进行调试。 - - -# ========================= -# 多激光雷达全球导航卫星系统(Multiple-LiDAR GNSS)校准指南 - -欢迎使用多激光雷达全球导航卫星系统校准工具。本指南将向您展示如何成功校准多个LiDAR的步骤。 - -## 内容 - -- 概述 -- 准备 -- 使用校准工具 -- 结果与验证 - -## 概述 - -在许多自动驾驶任务,如HDMap的制作,多个激光雷达扫描结果需要注册在一个统一的坐标系统。在这种情况下,需要对多个LIDARs的外部参数进行仔细校准。为了解决这个问题,开发了多激光雷达GNSS校准工具。 - -## 准备 - -下载校准工具,并将文件提取到$APOLLO_HOME/modules /calibration。$APOLLO_HOME是APOLLO repository的根目录。 -根据Apollo 1.5提供的校准指南选择校准位置。 -确保GNSS处于良好状态。为了验证这一点,使用‘rostopic echo /apollo/sensor/gnss/best_pose’并检查关键词latitude_std_dev, longitude_std_dev 和height_std_dev后的数量,偏差越小,校准质量越好。 我们强烈建议在偏差小于0.02时校准传感器。 -## 使用校准工具 - -### 记录校准数据 - -当LIDARS和GNSS准备就绪时,使用/apollo/modules/calibration/multi_lidar_gnss/record.sh记录校准数据。请注意,此脚本仅用于记录velodyne HDL64 和VLP16。为了其他目的,需要修改这个脚本,或者只需要使用rosbag record来做同样的事情。通常,2分钟的数据长度就足够了。在数据捕获之后,运行/apollo/modules/calibration/multi_lidar_gnss/calibrate.sh校准传感器。脚本由以下两个步骤组成。 - -### 出口数据 - -一旦校准包被记录,使用/apollo/modules/calibration/exporter/export_msgs --config /apollo/modules/calibration/exporter/conf/export_config.yaml获得传感器数据。exporter的唯一输入是一个YAML配置文件,如下所示。 -```bash -bag_path: "/apollo/data/bag/calibration/" # The path where the calibration bag is placed. -dump_dir: "/apollo/data/bag/calibration/export/" # The path where the sensor data will be placed using exporter -topics: - - /apollo/sensor/gnss/odometry: # Odometry topic name - type: ApolloOdometry # Odometry type - - /apollo/sensor/velodyne16/PointCloud2: # vlp16 topic name - type: PointCloud2 # vlp16 type - - /apollo/sensor/velodyne64/PointCloud2: # hdl64 topic name - type: PointCloud2 # hdl64 type -``` - -如果将新topic按如下的规则添加到文件中,也可以导出PointCloud2 types的其他topic。 -```bash - - TOPIC_NAME: # topic name - type: PointCloud2 -``` - -到目前为止,我们只支持ApolloOdometry和PointCloud2。 - -### 运行校准工具 - -如果输出所有传感器数据,运行/apollo/modules/calibration/lidar_gnss_calibrator/multi_lidar_gnss_calibrator --config /apollo/modules/calibration/lidar_gnss_calibrator/conf/multi_lidar_gnss_calibrator_config.yaml将得到结果。该工具的输入是一个YAML配置文件,如下所示。 -```bash -# multi-LiDAR-GNSS calibration configurations -data: - odometry: "/apollo/data/bag/calibration/export/multi_lidar_gnss/_apollo_sensor_gnss_odometry/odometry" - lidars: - - velodyne16: - path: "/apollo/data/bag/calibration/export/multi_lidar_gnss/_apollo_sensor_velodyne16_PointCloud2/" - - velodyne64: - path: "/apollo/data/bag/calibration/export/multi_lidar_gnss/_apollo_sensor_velodyne64_PointCloud2/" - result: "/apollo/data/bag/calibration/export/multi_lidar_gnss/result/" -calibration: - init_extrinsics: - velodyne16: - translation: - x: 0.0 - y: 1.77 - z: 1.1 - rotation: - x: 0.183014 - y: -0.183014 - z: 0.683008 - w: 0.683008 - velodyne64: - translation: - x: 0.0 - y: 1.57 - z: 1.3 - rotation: - x: 0.0 - y: 0.0 - z: 0.707 - w: 0.707 - steps: - - source_lidars: ["velodyne64"] - target_lidars: ["velodyne64"] - lidar_type: "multiple" - fix_target_lidars: false - fix_z: true - iteration: 3 - - source_lidars: ["velodyne16"] - target_lidars: ["velodyne16"] - lidar_type: "multiple" - fix_target_lidars: false - fix_z: true - iteration: 3 - - source_lidars: ["velodyne16"] - target_lidars: ["velodyne64"] - lidar_type: "multiple" - fix_target_lidars: true - fix_z: false - iteration: 3 -``` - -数据部分告诉工具在哪里获取点云和测距文件,以及在哪里保存结果。注意,LIDAR节点中的关键字将被识别为LiDARs的Frame ID。 - -校准部分提供了外部信息的初始猜测。所有的外部信息都是从激光雷达到GNSS,这意味着这种变换将激光雷达坐标系中定义的点的坐标映射到GNSS坐标系中定义的这一点的坐标。初始猜测要求旋转角度误差小于5度,平移误差小于0.1米。 - -步骤部分详细说明了校准过程。每个步骤被如下定义并且它们的含义在注释中。 -```bash -- source_lidars: ["velodyne16"] # Source LiDAR in point cloud registration. - target_lidars: ["velodyne64"] # Target LiDAR in point cloud registration. - lidar_type: "multiple" # "multiple" for multi-beam LiDAR, otherwise "single" - fix_target_lidars: true # Whether to fix extrinsics of target LiDARS. Only "true" when align different LiDARs. - fix_z: false # Whether to fix the z component of translation. Only "false" when align different LiDARs. - iteration: 3 # Iteration number -``` -## 结果和验证 -校准工具将结果保存到结果路径中。 -```bash -. -└── calib_result - ├── velodyne16_novatel_extrinsics.yaml - ├── velodyne16_result.pcd - ├── velodyne16_result_rgb.pcd - ├── velodyne64_novatel_extrinsics.yaml - ├── velodyne64_result.pcd - └── velodyne64_result_rgb.pcd -``` -这两个YAML文件是外部的。为了验证结果,使用pcl_viewer *_result.pcd检查注册质量。如果传感器校准好了,大量的细节可以从点云中识别出来。欲了解更多详情,请参阅校准指南Apollo 1.5。 - - - -# ====================== -# Apollo 2.0 传感器标定方法使用指南 - -欢迎使用Apollo传感器标定服务。本文档提供在Apollo 2.0中新增的3项传感器标定程序的使用流程说明,分别为:相机到相机的标定,相机到多线激光雷达的标定,以及毫米波雷达到相机的标定。 - -## 文档概览 - -* 概述 -* 准备工作 -* 标定流程 -* 标定结果获取 -* 标定结果验证 - -## 概述 - -在Apollo 2.0中,我们新增了3项标定功能:相机到相机的标定,相机到多线激光雷达的标定,以及毫米波雷达到相机的标定。对于多线激光雷达到组合惯导的标定,请参考多线激光雷达-组合惯导标定说明。Velodyne HDL64用户还可以使用Apollo 1.5提供的标定服务平台。标定工具均以车载可执行程序的方式提供。用户仅需要启动相应的标定程序,即可实时完成标定工作并进行结果验证。标定结果以 `.yaml` 文件形式返回。 - -## 准备工作 - -1. 下载[标定工具](https://github.com/ApolloAuto/apollo/releases/download/v2.0.0/calibration.tar.gz),并解压缩到`$APOLLO_HOME/modules/calibration`目录下。(APOLLO_HOME是apollo代码的根目录) - -2. 相机内参文件 - - 内参包含相机的焦距、主点和畸变系数等信息,可以通过一些成熟的相机标定工具来获得,例如 [ROS Camera Calibration Tools](http://wiki.ros.org/camera_calibration/Tutorials/MonocularCalibration) 和 [Camera Calibration Toolbox for Matlab](http://www.vision.caltech.edu/bouguetj/calib_doc/)。内参标定完成后,需将结果转换为 `.yaml` 格式的文件。下面是一个正确的内参文件样例: - - ```bash - header: - seq: 0 - stamp: - secs: 0 - nsecs: 0 - frame_id: short_camera - height: 1080 - width: 1920 - distortion_model: plumb_bob - D: [-0.535253, 0.259291, 0.004276, -0.000503, 0.0] - K: [1959.678185, 0.0, 1003.592207, 0.0, 1953.786100, 507.820634, 0.0, 0.0, 1.0] - R: [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0] - P: [1665.387817, 0.0, 1018.703332, 0.0, 0.0, 1867.912842, 506.628623, 0.0, 0.0, 0.0, 1.0, 0.0] - binning_x: 0 - binning_y: 0 - roi: - x_offset: 0 - y_offset: 0 - height: 0 - width: 0 - do_rectify: False - ``` - - 我们建议每一只相机都需要单独进行内参标定,而不是使用统一的内参结果。这样可以提高外参标定的准确性。 - -3. 初始外参文件 - - 本工具需要用户提供初始的外参值作为参考。一个良好的初始值可以帮助算法得到更精确的结果。下面是一个正确的相机到激光雷达的初始外参文件样例,其中translation为相机相对激光雷达的平移距离关系,rotation为旋转矩阵的四元数表达形式: - - ```bash - header: - seq: 0 - stamp: - secs: 0 - nsecs: 0 - frame_id: velodyne64 - child_frame_id: short_camera - transform: - rotation: - y: 0.5 - x: -0.5 - w: 0.5 - z: -0.5 - translation: - x: 0.0 - y: 1.5 - z: 2.0 - ``` - - 注意:相机到激光雷达的标定方法比较依赖于初始外参值的选取,一个偏差较大的外参,有可能导致标定失败。所以,请在条件允许的情况下,尽可能提供更加精准的初始外参值。 - -4. 标定场地 - - 我们的标定方法是基于自然场景的,所以一个理想的标定场地可以显著地提高标定结果的准确度。我们建议选取一个纹理丰富的场地,如有树木,电线杆,路灯,交通标志牌,静止的物体和清晰车道线。图1是一个较好的标定环境示例: - - ![](https://github.com/ApolloAuto/apollo/tree/master/docs/quickstart/images/calibration/sensor_calibration/calibration_place.png) -

图1 一个良好的标定场地

- -5. 所需Topics - - 确认程序所需传感器数据的topics均有输出。如何查看传感器有数据输出? - - 各个程序所需的topics如下表1-表3所示: - - 表1. 相机到相机标定所需topics - - | 传感器 | Topic名称 |Topic发送频率(Hz)| - | ------------ | ----------------------------------------- | ----------------- | - | Short_Camera | /apollo/sensor/camera/traffic/image_short | 9 | - | Long_Camera | /apollo/sensor/camera/traffic/image_long | 9 | - | INS | /apollo/sensor/gnss/odometry | 100 | - | INS | /apollo/sensor/gnss/ins_stat | 2 | - - 表2. 相机到64线激光雷达标定所需topics - - | 传感器 | Topic名称 |Topic发送频率(Hz)| - | ------------ | ----------------------------------------- | ----------------- | - | Short_Camera | /apollo/sensor/camera/traffic/image_short | 9 | - | LiDAR | /apollo/sensor/velodyne64/compensator/PointCloud2 | 10 | - | INS | /apollo/sensor/gnss/odometry | 100 | - | INS | /apollo/sensor/gnss/ins_stat | 2 | - - 表3. 毫米波雷达到相机标定所需topics - - | 传感器 | Topic名称 |Topic发送频率(Hz)| - | ------------ | ----------------------------------------- | ----------------- | - | Short_Camera | /apollo/sensor/camera/traffic/image_short | 9 | - | INS | /apollo/sensor/gnss/odometry | 100 | - | INS | /apollo/sensor/gnss/ins_stat | 2 | - -## 标定流程 - -所有标定程序需要用到车辆的定位结果。请确认车辆定位状态为56,否则标定程序不会开始采集数据。输入以下命令可查询车辆定位状态: - - ```bash - rostopic echo /apollo/sensor/gnss/ins_stat - ``` - -### 相机到相机 - -1. 运行方法 - - 使用以下命令来启动标定工具: - - ```bash - cd /apollo/scripts - bash sensor_calibration.sh camera_camera - ``` - -2. 采集标定数据 - * 由于两个相机的成像时间无法完全同步,所以在录制数据的时候,尽量将车辆进行慢速行驶,可以有效地缓解因时间差异所引起的图像不匹配问题。 - * 两个相机需有尽量大的图像重叠区域,否则该工具将无法进行外参标定运算。 - -3. 配置参数 - - 配置文件保存在以下路径,详细说明请参照表4。 - - ```bash - /apollo/modules/calibration/camera_camera_calibrator/conf/camera_camera_calibrtor.conf - ``` - - 表4. 相机到相机标定程序配置项说明 - - |配置项 | 说明 | - |----------------- | ---------------- | - |long_image_topic | 长焦相机的图像topic | - |short_image_topic | 广角相机的图像topic | - |odometry_topic | 车辆定位topic | - |ins_stat_topic | 车辆定位状态topic | - |long_camera_intrinsics_filename | 长焦相机的内参文件路径 | - |short_camera_intrinsics_filename | 广角相机的内参文件路径 | - |init_extrinsics_filename | 初始外参文件路径 | - |output_path | 标定结果输出路径 | - |max_speed_kmh | 最大车速限制,单位km/h | - -4. 输出内容 - - * 外参文件: 长焦相机到广角相机的外参文件。 - * 验证参考图片:包括一张长焦相机图像、一张广角相机图像及一张长焦相机依据标定后的外参投影到广角相机的去畸变融合图像。 - -### 相机到多线激光雷达 - -1. 运行方法 - - 使用以下命令来启动标定工具: - - ```bash - cd /apollo/scripts - bash sensor_calibration.sh lidar_camera - ``` - -2. 采集标定数据 - * 为避免时间戳不同步,在录制数据的时候,尽量将车辆进行慢速行驶,可以有效地缓解因时间差异所引起的标定问题。 - * 相机中需看到一定数量的投影点云,否则该工具将无法进行外参标定运算。因此,我们建议使用短焦距相机来进行相机-激光雷达的标定。 - -3. 配置参数 - - 配置文件保存在以下路径,详细说明请参照表5。 - - ```bash - /apollo/modules/calibration/lidar_camera_calibrator/conf/lidar_camera_calibrtor.conf - ``` - - 表5. 相机到多线激光雷达标定程序配置项说明 - - 配置项 | 说明 - --- | --- - image_topic | 相机的图像topic - lidar_topic | LiDAR的点云topic - odometry_topic | 车辆定位topic - ins_stat_topic | 车辆定位状态topic - camera_intrinsics_filename | 相机的内参文件路径 - init_extrinsics_filename | 初始外参文件路径 - output_path | 标定结果输出路径 - calib_stop_count | 标定所需截取的数据站数 - max_speed_kmh | 最大车速限制,单位km/h - -4. 输出内容 - - * 外参文件:相机到多线激光雷达的外参文件。 - * 验证参考图片:两张激光雷达点云利用标定结果外参投影到相机图像上的融合图像,分别是依据点云深度渲染的融合图像,和依据点云反射值渲染的融合图像。 - -### 毫米波雷达到相机 - -1. 运行方法 - - 使用以下命令来启动标定工具: - - ```bash - cd /apollo/scripts - bash sensor_calibration.sh radar_camera - ``` - -2. 采集标定数据 - - * 请将车辆进行低速直线行驶,标定程序仅会在该条件下开始采集数据。 - -3. 配置参数 - - 配置文件保存在以下路径,详细说明请参照表6。 - - ```bash - /apollo/modules/calibration/radar_camera_calibrator/conf/radar_camera_calibrtor.conf - ``` - - 表6. 相机到毫米波雷达标定程序配置项说明 - - 配置项 | 说明 - --- | --- - image_topic | 相机的图像topic - radar_topic | Radar的数据topic - odometry_topic | 车辆定位topic - ins_stat_topic | 车辆定位状态topic - camera_intrinsics_filename | 相机的内参文件路径 - init_extrinsics_filename | 初始外参文件路径 - output_path | 标定结果输出路径 - max_speed_kmh | 最大车速限制,单位km/h - -4. 输出内容 - - * 外参文件:毫米波雷达到短焦相机的外参文件。 - * 验证参考图片:将毫米波雷达投影到激光雷达坐标系的结果,需运行 `radar_lidar_visualizer` 工具。具体方法可参阅 `标定结果验证` 章节。 - -## 标定结果获取 - -所有标定结果均保存在配置文件中所设定的 `output` 路径下,标定后的外参以 `yaml` 格式的文件提供。此外,根据传感器的不同,标定结果会保存在 `output` 目录下的不同文件夹中,具体如表7所示: - -表7. 标定结果保存路径 - -| 传感器 | 外参保存路径 | -| ------------ | -----------------------| -| Short_Camera | [output]/camera_params | -| Long_Camera | [output]/camera_params | -| Radar | [output]/radar_params | - -## 标定结果验证 - -当标定完成后,会在 `[output]/validation` 目录下生成相应的标定结果验证图片。下面会详细介绍每一类验证图片的基本原理和查看方法。 - -### 相机到相机标定 - -* 基本方法:根据长焦相机投影到短焦相机的融合图像进行判断,绿色通道为短焦相机图像,红色和蓝色通道是长焦投影后的图像,目视判断检验对齐情况。在融合图像中的融合区域,选择场景中距离较远处(50米以外)的景物进行对齐判断,能够重合则精度高,出现粉色或绿色重影(错位),则存在误差,当误差大于一定范围时(范围依据实际使用情况而定),标定失败,需重新标定(正常情况下,近处物体因受视差影响,在水平方向存在错位,且距离越近错位量越大,此为正常现象。垂直方向不受视差影响)。 - -* 结果示例:如下图所示,图2为满足精度要求外参效果,图3为不满足精度要求的现象,请重新进行标定过程。 - -![](https://github.com/ApolloAuto/apollo/tree/master/docs/quickstart/images/calibration/sensor_calibration/cam_cam_good.png) -

图2 良好的相机到相机标定结果

- -![](https://github.com/ApolloAuto/apollo/tree/master/docs/quickstart/images/calibration/sensor_calibration/cam_cam_error.png) -

图3 错误的相机到相机标定结果

- -### 相机到多线激光雷达标定 - -* 基本方法:在产生的点云投影图像内,可寻找其中具有明显边缘的物体和标志物,查看其边缘轮廓对齐情况。如果50米以内的目标,点云边缘和图像边缘能够重合,则可以证明标定结果的精度很高。反之,若出现错位现象,则说明标定结果存在误差。当误差大于一定范围时(范围依据实际使用情况而定),该外参不可用。 - -* 结果示例:如下图所示,图4为准确外参的点云投影效果,图5为有偏差外参的点云投影效果 - -![](https://github.com/ApolloAuto/apollo/tree/master/docs/quickstart/images/calibration/sensor_calibration/cam_lidar_good.png) -

图4 良好的相机到多线激光雷达标定结果

- -![](https://github.com/ApolloAuto/apollo/tree/master/docs/quickstart/images/calibration/sensor_calibration/cam_lidar_error.png) -

图5 错误的相机到多线激光雷达标定结果

- -### 毫米波雷达到相机 - -* 基本方法:为了更好地验证毫米波雷达与相机间外参的标定结果,引入激光雷达作为桥梁,通过同一系统中毫米波雷达与相机的外参和相机与激光雷达的外参,计算得到毫米波雷达与激光雷达的外参,将毫米波雷达数据投影到激光雷达坐标系中与激光点云进行融合,并画出相应的鸟瞰图进行辅助验证。在融合图像中,白色点为激光雷达点云,绿色实心圆为毫米波雷达目标,通过图中毫米波雷达目标是否与激光雷达检测目标是否重合匹配进行判断,如果大部分目标均能对应匹配,则满足精度要求,否则不满足,需重新标定。 - -* 结果示例:如下图所示,图6为满足精度要求外参效果,图7为不满足精度要求外参效果。 - -![](https://github.com/ApolloAuto/apollo/tree/master/docs/quickstart/images/calibration/sensor_calibration/radar_cam_good.png) -

图6 良好的毫米波雷达到激光雷达投影结果

- -![](https://github.com/ApolloAuto/apollo/tree/master/docs/quickstart/images/calibration/sensor_calibration/radar_cam_error.png) -

图7 错误的毫米波雷达到激光雷达投影结果

- -* 注意事项: - * 为了得到毫米波雷达目标和激光雷达点云融合的验证图像,系统会自动或手动调用毫米波雷达到激光雷达的投影工具(`radar_lidar_visualizer`)进行图像绘制和生成过程。该投影工具在启动时会自动载入毫米波雷达与相机的外参文件及相机与激光雷达的外参文件,因此在启动之前,需要先进行相应的标定工具或将两文件以特定的文件名放在相应路径中,以备工具调用。 - - * 使用以下命令来启动 `radar_lidar_visualizer` 工具: - - ```bash - cd /apollo/scripts - bash sensor_calibration.sh visualizer - ``` - - * `radar_lidar_visualizer` 工具的配置文件在以下路径,详细说明请参照表8。 - - ```bash - /apollo/modules/calibration/radar_lidar_visualizer/conf/radar_lidar_visualizer.conf - ``` - - 表8. 毫米波雷达到激光雷达投影工具配置项说明 - - 配置项 | 说明 - --- | --- - radar_topic | Radar的数据topic - lidar_topic | LiDAR的点云topic - radar_camera_extrinsics_filename | 毫米波雷达到相机的外参文件 - camera_lidar_extrinsics_filename | 相机到激光雷达的外参文件 - output_path | 标定结果输出路径 - - * 验证图片同样保存在 `[output]/validation` 目录下。 - - -# =================== -# Apollo 2.5地图采集功能使用指南 - -本文档主要用来说明如何在Apollo2.5中使用地图数据采集的功能.重点介绍了数据采集所需的软硬件环境,数据采集的流程和注意事项. - -## 软硬件环境准备 -1、硬件安装方法参见[Apollo 2.5硬件安装指南](https://github.com/ApolloAuto/apollo/blob/master/docs/quickstart/apollo_2_5_hardware_system_installation_guide_v1.md) - - -2、软件安装方法参见[Apollo 软件安装指南](https://github.com/ApolloAuto/apollo/blob/master/docs/quickstart/apollo_software_installation_guide_cn.md) - - -3、传感器标定方法参见[Apollo 传感器标定方法使用指南](https://github.com/ApolloAuto/apollo/blob/master/docs/quickstart/multiple_lidar_gnss_calibration_guide.md) - -4、NVMe SSD硬盘。为了解决由于IO瓶颈导致可能的数据丢帧问题,建议工控机中安装NVME SSD硬盘。 - -5、卫星基站。为了得到精确的制图结果,需要搭建卫星基站,并且保证整个采集过程中采集车的RTK可以正常工作。 - -## 数据采集流程 - -1、启动地图采集模式 -Apollo环境启动参见[Apollo 2.5快速上手指南](https://github.com/ApolloAuto/apollo/blob/master/docs/quickstart/apollo_2_5_quick_start_cn.md) - -选择[Module Controller]、[Map Collection],打开[GPS]、[Camera]、[Velodyne]、[Velodyne16]开关。 - -![](https://github.com/ApolloAuto/apollo/tree/master/docs/quickstart/images/map_collection_sensor_open.png) - -确认各个传感器状态是否OK。 - -![](https://github.com/ApolloAuto/apollo/tree/master/docs/quickstart/images/map_collection_sensor_check.png) - -2、待确认各个传感器状态OK后,打开[Record Bag]开关,开始录制地图数据。 - -![](https://github.com/ApolloAuto/apollo/tree/master/docs/quickstart/images/map_collection_sensor_start_record.png) - -正式采集数据之前,需要车辆静止5分钟,8字绕行5分钟。 -采集过程中需要保证双向车道全覆盖采集五圈以上,车速60KM/h以下,尽量每圈走不同的车道,覆盖完全。在路口区域无需刻意停留,慢速通过即可。路口区域需对各方向道路外延采集至少50m,保障道路各方向的红绿灯及车道线完整清晰。 -数据采集完成后,需要8字绕行五分钟,然后再静止五分钟。 - -3、所有采集完成后,关闭[Record Bag]开关结束采集,然后关闭[GPS]、[Camera]、[Velodyne]、[Velodyne16]开关。 - -![](https://github.com/ApolloAuto/apollo/tree/master/docs/quickstart/images/map_collection_sensor_stop_record.png) - -4、数据上传 - -采集的数据放置在/apollo/data/bag/(采集开始时间,例如2018-04-14-21-20-24)目录,把该目录下的数据打包为tar.gz压缩文件,到[Apollo数据官网](http://data.apollo.auto/hd_map_intro/?locale=zh-cn)进行数据上传。 - -## 地图数据生产服务 - -1、数据权限申请 - -首先需要注册一个百度账号,登陆百度账号,申请地图制作服务使用权限(仅需申请一次),如果已经申请过,跳过此步。 -![](https://github.com/ApolloAuto/apollo/tree/master/docs/quickstart/images/map_collection_request_ch.png) - -2、地图技术服务 - -用户可以在该页面进行新建区域、创建制图任务、管理地图数据、跟踪制图进度,下载地图数据。 -![](https://github.com/ApolloAuto/apollo/tree/master/docs/quickstart/images/map_collection_Area_ch.png) - -3、数据管理 - -用户点击“采集数据管理”后可以进入采集数据管理页面,在该页面可以上传多份采集数据,所有数据上传上传后可以提交采集数据,之后进入制图流程,不能再对数据进行编辑操作。 - -![](https://github.com/ApolloAuto/apollo/tree/master/docs/quickstart/images/map_collection_Management_ch.png) - -4、数据下载 - -当需求状态是"已发布"时,点击“下载地图”可进行地图数据下载。如果需要更新地图,请点击“更新地图数据”发起制图流程,需重新进行数据上传及制图流程。 - -![](https://github.com/ApolloAuto/apollo/tree/master/docs/quickstart/images/map_collection_Download_ch.png) - - -# =================== -# 如何添加新的GPS接收器 - -## 简介 -GPS接收器是一种从GPS卫星上接收信息,然后根据这些信息计算设备地理位置、速度和精确时间的设备。这种设备通常包括一个接收器,一个IMU(Inertial measurement unit,惯性测量单元),一个针对轮编码器的接口以及一个将各传感器获取的数据融合到一起的融合引擎。Apollo系统中默认使用Novatel 板卡,该说明详细介绍如何添加并使用一个新的GPS接收器。 - -## 添加GPS新接收器的步骤 -请按照下面的步骤添加新的GPS接收器. - 1. 通过继承基类“Parser”,实现新GPS接收器的数据解析器 - 2. 在Parser类中为新GPS接收器添加新接口 - 3. 在文件`config.proto`中, 为新GPS接收器添加新数据格式 - 4. 在函数`create_parser`(见文件data_parser.cpp), 为新GPS接收器添加新解析器实例 - -下面让我们用上面的方法来添加u-blox GPS接收器。 - -### 步骤 1 - -通过继承类“Parser”,为新GPS接收器实现新的数据解析器: - -```cpp -class UbloxParser : public Parser { -public: - UbloxParser(); - - virtual MessageType get_message(MessagePtr& message_ptr); - -private: - bool verify_checksum(); - - Parser::MessageType prepare_message(MessagePtr& message_ptr); - - // The handle_xxx functions return whether a message is ready. - bool handle_esf_raw(const ublox::EsfRaw* raw, size_t data_size); - bool handle_esf_ins(const ublox::EsfIns* ins); - bool handle_hnr_pvt(const ublox::HnrPvt* pvt); - bool handle_nav_att(const ublox::NavAtt *att); - bool handle_nav_pvt(const ublox::NavPvt* pvt); - bool handle_nav_cov(const ublox::NavCov *cov); - bool handle_rxm_rawx(const ublox::RxmRawx *raw); - - double _gps_seconds_base = -1.0; - - double _gyro_scale = 0.0; - - double _accel_scale = 0.0; - - float _imu_measurement_span = 0.0; - - int _imu_frame_mapping = 5; - - double _imu_measurement_time_previous = -1.0; - - std::vector _buffer; - - size_t _total_length = 0; - - ::apollo::drivers::gnss::Gnss _gnss; - ::apollo::drivers::gnss::Imu _imu; - ::apollo::drivers::gnss::Ins _ins; -}; - -``` - -### 步骤 2 - -在Parser类中,为新GPS接收器添加新的接口: - -在Parser类中添加函数‘create_ublox‘: - -```cpp -class Parser { -public: - // Return a pointer to a NovAtel parser. The caller should take ownership. - static Parser* create_novatel(); - - // Return a pointer to a u-blox parser. The caller should take ownership. - static Parser* create_ublox(); - - virtual ~Parser() {} - - // Updates the parser with new data. The caller must keep the data valid until get_message() - // returns NONE. - void update(const uint8_t* data, size_t length) { - _data = data; - _data_end = data + length; - } - - void update(const std::string& data) { - update(reinterpret_cast(data.data()), data.size()); - } - - enum class MessageType { - NONE, - GNSS, - GNSS_RANGE, - IMU, - INS, - WHEEL, - EPHEMERIDES, - OBSERVATION, - GPGGA, - }; - - // Gets a parsed protobuf message. The caller must consume the message before calling another - // get_message() or update(); - virtual MessageType get_message(MessagePtr& message_ptr) = 0; - -protected: - Parser() {} - - // Point to the beginning and end of data. Do not take ownership. - const uint8_t* _data = nullptr; - const uint8_t* _data_end = nullptr; - -private: - DISABLE_COPY_AND_ASSIGN(Parser); -}; - -Parser* Parser::create_ublox() { - return new UbloxParser(); -} -``` - -### 步骤 3 - -在config.proto文件中, 为新的GPS接收器添加新的数据格式定义: - -在配置文件(modules/drivers/gnss/proto/config.proto)中添加`UBLOX_TEXT` and `UBLOX_BINARY` - -```txt -message Stream { - enum Format { - UNKNOWN = 0; - NMEA = 1; - RTCM_V2 = 2; - RTCM_V3 = 3; - - NOVATEL_TEXT = 10; - NOVATEL_BINARY = 11; - - UBLOX_TEXT = 20; - UBLOX_BINARY = 21; - } -... ... -``` - -### 步骤 4 - -在函数`create_parser`(见data_parser.cpp), 为新GPS接收器添加新解析器实例. -我们将通过添加处理`config::Stream::UBLOX_BINARY`的代码实现上面的步骤,具体如下。 - -``` cpp -Parser* create_parser(config::Stream::Format format, bool is_base_station = false) { - switch (format) { - case config::Stream::NOVATEL_BINARY: - return Parser::create_novatel(); - - case config::Stream::UBLOX_BINARY: - return Parser::create_ubloxl(); - - default: - return nullptr; - } -} - -``` - -# =========================== -# 如何添加新的CAN卡 - -## 简介 -控制器区域网络(CAN)是在许多微控制器和设备中密集使用的网络,用于在没有主计算机帮助的情况下在设备之间传输数据。 - -Apollo中使用的默认CAN卡是 **ESD CAN-PCIe卡**。您可以使用以下步骤添加新的CAN卡: - -## 添加新CAN卡 -添加新的CAN卡需要完成以下几个步骤: - -1. 实现新CAN卡的`CanClient`类。 -2. 在`CanClientFactory`中注册新的CAN卡。 -3. 更新配置文件。 - -以下步骤展示了如何添加新的CAN卡 - 示例添加CAN卡到您的工程。 - -### 步骤 1 - -实现新CAN卡的CanClient类 -下面的代码展示了如何实现 `CANClient` 类: - -```cpp -#include -#include - -#include "hermes_can/include/bcan.h" -#include "modules/canbus/can_client/can_client.h" -#include "modules/canbus/common/canbus_consts.h" -#include "modules/common/proto/error_code.pb.h" - -/** - * @namespace apollo::canbus::can - * @brief apollo::canbus::can - */ -namespace apollo { -namespace canbus { -namespace can { - -/** - * @class ExampleCanClient - * @brief The class which defines a Example CAN client which inherits CanClient. - */ -class ExampleCanClient : public CanClient { - public: - /** - * @brief Initialize the Example CAN client by specified CAN card parameters. - * @param parameter CAN card parameters to initialize the CAN client. - * @return If the initialization is successful. - */ - bool Init(const CANCardParameter& parameter) override; - - /** - * @brief Destructor - */ - virtual ~ExampleCanClient() = default; - - /** - * @brief Start the Example CAN client. - * @return The status of the start action which is defined by - * apollo::common::ErrorCode. - */ - apollo::common::ErrorCode Start() override; - - /** - * @brief Stop the Example CAN client. - */ - void Stop() override; - - /** - * @brief Send messages - * @param frames The messages to send. - * @param frame_num The amount of messages to send. - * @return The status of the sending action which is defined by - * apollo::common::ErrorCode. - */ - apollo::common::ErrorCode Send(const std::vector& frames, - int32_t* const frame_num) override; - - /** - * @brief Receive messages - * @param frames The messages to receive. - * @param frame_num The amount of messages to receive. - * @return The status of the receiving action which is defined by - * apollo::common::ErrorCode. - */ - apollo::common::ErrorCode Receive(std::vector* const frames, - int32_t* const frame_num) override; - - /** - * @brief Get the error string. - * @param status The status to get the error string. - */ - std::string GetErrorString(const int32_t status) override; - - private: - ... - ... -}; - -} // namespace can -} // namespace canbus -} // namespace apollo -``` - -### 步骤 2 -在CanClientFactory中注册新CAN卡, -在 `CanClientFactory`中添加如下代码: -```cpp -void CanClientFactory::RegisterCanClients() { - Register(CANCardParameter::ESD_CAN, - []() -> CanClient* { return new can::EsdCanClient(); }); - - // register the new CAN card here. - Register(CANCardParameter::EXAMPLE_CAN, - []() -> CanClient* { return new can::ExampleCanClient(); }); -} -``` - -### 步骤 3 - -接下来,需要更新配置文件 -在`/modules/canbus/proto/can_card_parameter.proto`添加 EXAMPLE_CAN - -```proto -message CANCardParameter { - enum CANCardBrand { - FAKE_CAN = 0; - ESD_CAN = 1; - EXAMPLE_CAN = 2; // add new CAN card here. - } - ... ... -} -``` -Update `/modules/canbus/conf/canbus_conf.pb.txt` - -```txt -... ... -can_card_parameter { - brand:EXAMPLE_CAN - type: PCI_CARD // suppose the new can card is PCI_CARD - channel_id: CHANNEL_ID_ZERO // suppose the new can card has CHANNEL_ID_ZERO -} -... ... -``` - - -# ===================== -# 如何添加新的控制算法 - -Apollo中的控制算法由一个或多个控制器组成,可以轻松更改或替换为不同的算法。 每个控制器将一个或多个控制命令输出到`CANbus`。 Apollo中的默认控制算法包含横向控制器(LatController)和纵向控制器(LonController)。 它们分别负责横向和纵向的车辆控制。 - -新的控制算法不必遵循默认模式,例如,一个横向控制器+一个纵向控制器。 它可以是单个控制器,也可以是任意数量控制器的组合。 - -添加新的控制算法的步骤: - -1. 创建一个控制器 -2. 在文件`control_config` 中添加新控制器的配置信息 -3. 注册新控制器 - -为了更好的理解,下面对每个步骤进行详细的阐述: - -## 创建一个控制器 - -所有控制器都必须继承基类`Controller`,它定义了一组接口。 以下是控制器实现的示例: - -```c++ -namespace apollo { -namespace control { - -class NewController : public Controller { - public: - NewController(); - virtual ~NewController(); - Status Init(const ControlConf* control_conf) override; - Status ComputeControlCommand( - const localization::LocalizationEstimate* localization, - const canbus::Chassis* chassis, const planning::ADCTrajectory* trajectory, - ControlCommand* cmd) override; - Status Reset() override; - void Stop() override; - std::string Name() const override; -}; -} // namespace control -} // namespace apollo -``` - - - -## 在文件`control_config` 中添加新控制器的配置信息 - -按照下面的步骤添加新控制器的配置信息: - -1. 根据算法要求为新控制器配置和参数定义`proto`。作为示例,可以参考以下位置的`LatController`的`proto`定义:`modules/control/proto/ lat_controller_conf.proto` -2. 定义新的控制器`proto`之后,例如`new_controller_conf.proto`,输入以下内容: - - ```protobuf - syntax = "proto2"; +![](https://github.com/Ewenwan/MVision/blob/master/UMCar/img/sdc.PNG) - package apollo.control; +[百度apollo课程 1-5 ](https://www.bilibili.com/video/BV1yJ411d7xu/?spm_id_from=333.788.videocard.16) - message NewControllerConf { - double parameter1 = 1; - int32 parameter2 = 2; - } - ``` +[百度apollo课程 6-8](https://www.bilibili.com/video/BV1iJ411d7XA/?spm_id_from=333.788.videocard.0) -3. 参考如下内容更新 `modules/control/proto/control_conf.proto`文件: +[七月在线 无人驾驶系列知识入门到提高](https://www.bilibili.com/video/BV137411E7oC/?spm_id_from=333.788.videocard.0) - ```protobuf - optional apollo.control.NewControllerConf new_controller_conf = 15; - ``` +当今,自动驾驶技术已经成为整个汽车产业的最新发展方向。应用自动驾驶技术可以全面提升汽车驾驶的安全性、舒适性,满足更高层次的市场需求等。自动驾驶技术得益于人工智能技术的应用及推广,在环境感知、精准定位、决策与规划、控制与执行、高精地图与车联网V2X 等方面实现了全面提升。科研院校、汽车制造厂商、科技公司、自动驾驶汽车创业公司以及汽车零部件供应商在自动驾驶技术领域进行不断地探索,寻求通过人工智能技术来获得技术上的新突破。 -4. 参考以内容更新 `ControllerType`(在`modules/control/proto/control_conf.proto` 中): +自动驾驶汽车(Automated Vehicle;Intelligent Vehicle;Autonomous Vehicle;Self-drivingCar;Driverless Car)又称智能汽车、自主汽车、自动驾驶汽车或轮式移动机器人,是一种通过计算机实现自动驾驶的智能汽车。 - ```protobuf - enum ControllerType { - LAT_CONTROLLER = 0; - LON_CONTROLLER = 1; - NEW_CONTROLLER = 2; - }; - ``` +自动驾驶汽车等级标准,SAE J3016 标准(Level0~Level 5 共6 个级别)、 -5. `protobuf`定义完成后,在`modules/control/conf/lincoln.pb.txt`中相应更新控制配置文件。 +* Level 0:无自动化,由人类驾驶员全程操控汽车,但可以得到示警式或须干预的辅助信息。 +* Level 1:辅助驾驶,利用环境感知信息对转向或纵向加减速进行闭环控制,其余工作由人类驾驶员完成。 +* Level 2:部分自动化,利用环境感知信息同时对转向和纵向加减速进行闭环控制,其余工作由人类驾驶员完成。 +* Level 3:有条件自动化,由自动驾驶系统完成所有驾驶操作,人类驾驶员根据系统请求进行干预。 +* Level 4:高度自动化,由自动驾驶系统完成所有驾驶操作,无需人类驾驶员进行任何干预,但须限定道路和功能。 +* Level 5:完全自动化,由自动驾驶系统完成所有的驾驶操作,人类驾驶员能够应付的所有道路和环境,系统也能完全自动完成。 -``` -注意:上面的"control/conf"文件是Apollo的默认文件。您的项目可能使用不同的控制配置文件. -``` +目前对于自动驾驶汽车的研究有两条不同的技术路线:一条是渐进提高汽车驾驶的自动化水平;另一条是“一步到位”的无人驾驶技术发展路线。由SAE J3016 标准可以看出,通常大家谈论的无人驾驶汽车对应该标准的Level 4 和Level 5 级。无人驾驶汽车是自动驾驶的一种表现形式,它具有整个道路环境中所有与车辆安全性相关的控制功能,不需要驾驶员对车辆实施控制。 -## 注册新控制器 -要激活Apollo系统中的新控制器,请在如下文件中的“ControllerAgent”中注册新控制器: +〉 自动驾驶技术的价值 -> modules/control/controller/controller_agent.cc +* 1. 改善交通安全。驾驶员的过失责任是交通事故的主要因素。无人驾驶汽车不受人的心理和情绪干扰,保证遵守交通法规,按照规划路线行驶,可以有效地减少人为疏失所造成的交通事故。 -按照如下示例添加注册信息: +* 2. 实现节能减排。由于通过合理调度实现共享享出行,减少了私家车购买数量,车辆绝对量的减少,将使温室气体排量大幅降低。 -```c++ -void ControllerAgent::RegisterControllers() { - controller_factory_.Register( - ControlConf::NEW_CONTROLLER, - []() -> Controller * { return new NewController(); }); -} -``` +* 3. 消除交通拥堵,提升社会效率。自动驾驶汽车可以通过提高车速、缩小车距以及选择更有效路线来减少通勤所耗时间。 +* 4. 个人移动能力更加便利,不再需要找停车场。 +* 5. 拉动汽车、电子、通信、服务、社会管理等协同发展,对促进我国产业转型升级具有重大战略意义。 -在完成以上步骤后,您的新控制器便可在Apollo系统中生效。 +# 实战 -# ===================== -# 如何在预测模块中添加新评估器 +自动驾驶汽车关键技术包括环境感知、精准定位、决策与规划、控制与执行、高精地图与车联网V2X 以及自动驾驶汽车测试与验证技术;人工智能在自动驾驶汽车中的应用包括人工智能在环境感知中的应用、人工智能在决策规划中的应用、人工智能在车辆控制中的应用。 -## 简介 -评估器通过应用预训练的深度学习模型生成特征(来自障碍物和当前车辆的原始信息)以获得模型输出。 -## 添加评估器的步骤 -按照下面的步骤添加名称为`NewEvaluator`的评估器。 -1. 在proto中添加一个字段 -2. 声明一个从`Evaluator`类继承的类`NewEvaluator` -3. 实现类`NewEvaluator` -4. 更新预测配置 -5. 更新评估器管理 + 计算机视觉(处理摄像头,分割、检测、识别) + 定位(算法+HD MAP) 路径规划 控制 + 传感器融合fusion(激光雷达等) -### 声明一个从`Evaluator`类继承的类`NewEvaluator` - `modules/prediction/evaluator/vehicle`目录下新建文件`new_evaluator.h`。声明如下: -```cpp -#include "modules/prediction/evaluator/evaluator.h" -namespace apollo { -namespace prediction { + 以百度apollo 无人驾驶平台介绍相关的技术 + + 1. 感知 + 2. 定位 + 3. 规划 + 4. 控制 + 5. 高精度地图和车联网 基础设施 + +[comma.ai(无人驾驶公司)的这两千行Python/tf代码 Learning a Driving Simulator](https://github.com/Ewenwan/research) -class NewEvaluator : public Evaluator { - public: - NewEvaluator(); - virtual ~NewEvaluator(); - void Evaluate(Obstacle* obstacle_ptr) override; - // Other useful functions and fields. -}; +[openpilot 一个开源的自动驾驶(驾驶代理),它实行 Hondas 和 Acuras 的自适应巡航控制(ACC)和车道保持辅助系统(LKAS)的功能。 ](https://github.com/Ewenwan/openpilot) -} // namespace prediction -} // namespace apollo -``` +[Autoware](https://github.com/Ewenwan/Autoware) -### 实现类 `NewEvaluator` -在`new_evaluator.h`所在目录下新建文件`new_evaluator.cc`。实现如下: -```cpp -#include "modules/prediction/evaluator/vehicle/new_evaluator.h" +[udacity/self-driving-car](https://github.com/Ewenwan/self-driving-car) -namespace apollo { -namespace prediction { +[第六十八篇:从ADAS到自动驾驶(一):自动驾驶发展及分级](https://blog.csdn.net/liaojiacai/article/details/55062873) -NewEvaluator::NewEvaluator() { - // Implement -} +## 1.环境感知,起着人类驾驶员“眼睛”“耳朵”的作用 -NewEvaluator::~NewEvaluator() { - // Implement -} +* 摄像机可以识别车辆行驶环境中的车辆、行人、车道线、路标、交通标志、交通信号灯等。它具有较高的图像稳定性、抗干扰能力和传输能力等特点。 +* 激光雷达是以发射激光束来探测目标空间位置的主动测量设备。 +* 毫米波雷达是指工作在毫米波波段、频率在30—300GHz 之间的雷达。根据测量原理的不同,毫米波雷达可分为脉冲方式毫米波雷达和调频连续波方式毫米波雷达两种。 +* 超声波雷达的数据处理简单快速,检测距离较短,多用于近距离障碍物检测。 -NewEvaluator::Evaluate(Obstacle* obstacle_ptr)() { - // Extract features - // Compute new_output by applying pre-trained model -} +目前,环境感知技术有两种技术路线,一种是以摄像机为主导的多传感器融合方案,典型代表是特斯拉。另一种是以激光雷达为主导,其他传感器为辅助的技术方案,典型企业代表如谷歌、百度等。 -// Other functions +摄像机捕获图像(RGB图像) -> 预处理(缩放、旋转、格式转换) -> 提取特征 -> 物体检测/分类/语义分割/识别等 -} // namespace prediction -} // namespace apollo +激光雷达捕获距离数据(点云数据) -> 预处理(PCL点云处理,降采样,聚类分割等) -> 提取特征(形状、表面纹理) -> 三维检测框(三维框+类别) -``` +后两步,现在一般使用DCNN深度神经网络来实现。 -### 在proto中添加新评估器 -在`prediction_conf.proto`中添加新评估器类型: -```cpp - enum EvaluatorType { - MLP_EVALUATOR = 0; - NEW_EVALUATOR = 1; - } -``` +检测 -> 跟踪(连续帧,检测出的物体匹配关联(利用局部二值模式特征/方向梯度直方图等特征进行匹配)) -> 判断速度(辅助雷达数据(三维点云数据,含有精确的距离信息)) -> 预测物体轨迹(未来的速度和位置) +-> 检测出 动态物体 和 车道线 -> 用于规划和决策 -### 更新prediction_conf文件 -在 `modules/prediction/conf/prediction_conf.pb.txt`中,按照如下方式更新字段`evaluator_type`: -``` -obstacle_conf { - obstacle_type: VEHICLE - obstacle_status: ON_LANE - evaluator_type: NEW_EVALUATOR - predictor_type: NEW_PREDICTOR -} -``` +透视变换 和 滑动窗口跟踪 -### 更新评估器管理 -按照如下方式更新`CreateEvluator( ... )` : -```cpp - case ObstacleConf::NEW_EVALUATOR: { - evaluator_ptr.reset(new NewEvaluator()); - break; - } -``` -按照如下方式更新`RegisterEvaluators()` : -```cpp - RegisterEvaluator(ObstacleConf::NEW_EVALUATOR); -``` +语义分割理解环境障碍物道路等,CNN卷积网络**编码**得到特征 -> 反卷积(或池化索引上采样+卷积)**解码**网络 -完成上述步骤后,新评估器便创建成功了。 - -## 添加新特性 -如果你想添加新特性,请按照如下的步骤进行操作: -### 在proto中添加一个字段 -假设新的评估结果名称是`new_output`且类型是`int32`。如果输出直接与障碍物相关,可以将它添加到`modules/prediction/proto/feature.proto`中,如下所示: -```cpp -message Feature { - // Other existing features - optional int32 new_output = 1000; -} -``` -如果输出与车道相关,请将其添加到`modules/prediction/proto/lane_graph.proto`中,如下所示: -```cpp -message LaneSequence { - // Other existing features - optional int32 new_output = 1000; -} -``` +高精度地图中,设定ROI感兴趣三维(点云)/二维(图像)区域,以缩小 查询匹配范围,加快感知,实际检测的静态物体(交通灯等)会在HD map中查找,辅助实际环境中的感知过程 -# ===================== -# 如何在预测模块中添加一个预测器 -## 简介 +相机 雷达radar 激光雷达LiDAR 在各种使用场景和环境下个有优缺点,所以需要结合他们的优点,达到在各种场景中最优,所以需要**传感器融合技术** -预测器为每个障碍物生成预测轨迹。在这里,假设我们想给我们的车辆增加一个新的预测器,用于其他类型的障碍,步骤如下: +雷达radar 激光雷达LiDAR 检测障碍物,传感器融合的算法为 卡尔曼滤波(预测+测量误差更新) -1. 定义一个继承基类 `Predictor` 的类 -2. 实现新类 `NewPredictor` -3. 在 `prediction_conf.proto`中添加一个新的预测期类型 -4. 更新 prediction_conf -5. 更新预测器管理器(Predictor manager) +数据同步融合 / 数据异步融合 -## 添加新预测器的步骤 -如下步骤将会指导您在预测器中添加一个 `NewPredictor`。 +有数据级融合,特征级融合,目标级融合,应用于不同的场景,融合策略就不同。 -### 定义一个继承基类 `Predictor` 的类 -在文件夹 `modules/prediction/predictor/vehicle`中创建一个名为`new_predictor.h`的文件,文件内容如下: -```cpp +## 2.精准定位 -#include "modules/prediction/predictor/predictor.h" +* 惯性导航系统由陀螺仪和加速度计构成,通过测量运动载体的线加速度和角速率数据,并将这些数据对时间进行积分运算,从而得到速度、位置和姿态。 -namespace apollo { -namespace prediction { +车辆速度 时间 初始位置 和 初始速度 车辆加速度。 -class NewPredictor : public Predictor { - public: - void Predict(Obstacle* obstacle) override; - // Other useful functions and fields. -}; -} // namespace prediction -} // namespace apollo -``` +短时间内准确,长时间内,由于IMU数据飘逸,变得的不准确,可以和GPS结合 -### Implement the class `NewPredictor` -在创建了 `new_predictor.h`的文件夹中创建文件 `new_predictor.cc`。 文件内容如下: -```cpp -#include "modules/prediction/predictor/vehicle/new_predictor.h" -namespace apollo { -namespace prediction { +* 轮速编码器与航迹推算.可以通过轮速编码器推算出自动驾驶汽车的位置。通常轮速编码器安装在汽车的前轮,分别记录左轮与右轮的总转数。通过分析每个时间段里左右轮的转数,可以推算出车辆向前走了多远,向左右转了多少度等。由于在不同地面材质(如冰面与水泥地)上转数对距离转换存在偏差,随着时间推进,测量偏差会越来越大,因此单靠轮测距器并不能精准估计自动驾驶汽车的位姿。 -NewPredictor::Predict(Obstacle* obstacle)() { - // Get the results from evaluator - // Generate the predicted trajectory -} +* 卫星导航系统.目前全球卫星导航系统包括美国的GPS、俄罗斯的GLONASS、中国的北斗卫星导航系统。 -// Other functions +卫星 <---> 地面控制站 gps接收器。 -} // namespace prediction -} // namespace apollo + 时间*光速 距离 ,时间有误差 -``` -### 在 `prediction_conf.proto`中添加一个新的预测期类型 -``` - enum PredictorType { - LANE_SEQUENCE_PREDICTOR = 0; - FREE_MOVE_PREDICTOR = 1; - REGIONAL_PREDICTOR = 2; - MOVE_SEQUENCE_PREDICTOR = 3; - NEW_PREDICTOR = 4; - } -``` +差分GPS: 使用两个GPS定位装置,两者都有误差,通过两个数据差分,来消除误差 -### 更新 prediction_conf -在 `modules/prediction/conf/prediction_conf.pb.txt`中, 更新 `predictor_type`部分如下: -``` -obstacle_conf { - obstacle_type: VEHICLE - obstacle_status: ON_LANE - evaluator_type: NEW_EVALUATOR - predictor_type: NEW_PREDICTOR -} -``` +实时运动定位 RTK, 通过地面基站计算GPS定位误差,gps接收器该误差来进行校正。 -### 更新预测器管理器(Predictor manager) -更新 `CreateEvluator( ... )` 如下: -```cpp - case ObstacleConf::NEW_PREDICTOR: { - predictor_ptr.reset(new NewPredictor()); - break; - } -``` -更新 `RegisterPredictors()` 如下: -```cpp - RegisterPredictor(ObstacleConf::NEW_PREDICTOR); -``` +缺点: 大型建筑物阻挡信号 -在完成以上步骤以后,一个新的预测器就创建好了。 -======= -# 如何在预测模块中添加一个预测器 -## 简介 +* SLAM 自主导航系统.目前主流有两种SLAM 策略。 -预测器为每个障碍物生成预测轨迹。在这里,假设我们想给我们的车辆增加一个新的预测器,用于其他类型的障碍,步骤如下: +第一种是基于激光雷达的SLAM,以谷歌汽车为例。车辆携带有GPS,通过GPS 对位置进行判断,并以激光雷达SLAM 点云图像与高精度地图进行坐标配准,匹配后确认自身位姿。 -1. 定义一个继承基类 `Predictor` 的类 -2. 实现新类 `NewPredictor` -3. 在 `prediction_conf.proto`中添加一个新的预测期类型 -4. 更新 prediction_conf -5. 更新预测器管理器(Predictor manager) -## 添加新预测器的步骤 +高精度地图定位,利用雷达数据和地图数据进行匹配,滤波算法定位 -如下步骤将会指导您在预测器中添加一个 `NewPredictor`。 +gps不能正常使用时: -### 定义一个继承自基类 `Predictor` 的类 +车辆将其传感器识别的地标,通过坐标变换,与高精度地图数据进行匹配。 -在文件夹 `modules/prediction/predictor/vehicle`中创建一个名为`new_predictor.h`的文件,文件内容如下: -```cpp +距离三个地标的信息,来定位,三角定位,三个圆圈的交汇点。 -#include "modules/prediction/predictor/predictor.h" +传感器 雷达数据获取的点云数据 和 MAP 利用点云匹配算法(ICP,迭代最近点) -namespace apollo { -namespace prediction { +滤波算法定位,直方图滤波,kaman滤波 -class NewPredictor : public Predictor { - public: - void Predict(Obstacle* obstacle) override; - // Other useful functions and fields. -}; -} // namespace prediction -} // namespace apollo -``` -### Implement the class `NewPredictor` -在创建了 `new_predictor.h`的文件夹中创建文件 `new_predictor.cc`。文件内容如下: -```cpp -#include "modules/prediction/predictor/vehicle/new_predictor.h" +第二种是基于视觉的SLAM,以Mobileye 为例。Mobileye 提出一种SLAM 的变种定位方法——REM。车辆通过采集包括信号灯、指示牌、车道线等标识,得到了一个简单的三维坐标数据,再通过视觉识别车道线等信息,获取一个一维数据。摄像机中的图像 与 高精度地图数据 进行配准,即可完成定位。 -namespace apollo { -namespace prediction { +粒子滤波定位, 使用检测出的地图点 匹配定位,多中粒子点可能性,最后真实位置,保留了下来。 -NewPredictor::Predict(Obstacle* obstacle)() { - // Get the results from evaluator - // Generate the predicted trajectory -} -// Other functions +## 3.决策与规划 -} // namespace prediction -} // namespace apollo +自动驾驶汽车的行为决策与路径规划是指依据环境感知和导航子系统输出信息,通过一些特定的约束条件如无碰撞、安全到达终点等,规划出给定起止点之间多条可选安全路径,并在这些路径中选取一条最优的路径作为车辆行驶轨迹。 -``` +* A. 驾驶任务规划(路线规划,A点到B点的最佳路线):即**全局路径规划**,主要的规划内容是指行驶路径范围的规划。当自动驾驶汽车上路行驶时,驾驶任务规划会为汽车的自主驾驶提供方向引导方面的行为决策方案,通过GPS 技术进行即将需要前进行驶的路段和途径区域的规划与顺序排列。 -### 在 `prediction_conf.proto`中添加一个新的预测器类型 -``` - enum PredictorType { - LANE_SEQUENCE_PREDICTOR = 0; - FREE_MOVE_PREDICTOR = 1; - REGIONAL_PREDICTOR = 2; - MOVE_SEQUENCE_PREDICTOR = 3; - NEW_PREDICTOR = 4; - } -``` +路线规划 输入 地图 + 当前位置 + 目标位置, 地图被转换为 节点连接图,A* 图路径搜索算法,最短路径搜索(当前节点成本+候选节点成本最小) -### 更新 prediction_conf -在 `modules/prediction/conf/prediction_conf.pb.txt`中,更新 `predictor_type`部分如下: -``` -obstacle_conf { - obstacle_type: VEHICLE - obstacle_status: ON_LANE - evaluator_type: NEW_EVALUATOR - predictor_type: NEW_PREDICTOR -} -``` +* 路径规划(轨迹规划,轨迹点序列):即 路径**局部规划**时,自动驾驶车辆中的路径规划算法会在行驶任务设定之后将完成任务的最佳路径选取出来,避免碰撞和保持安全距离。在此过程中,会对路径的曲率和弧长等进行综合考量,从而实现路径选择的最优化。 -### 更新预测器管理器(Predictor manager) -更新 `CreateEvluator( ... )` 如下: -```cpp - case ObstacleConf::NEW_PREDICTOR: { - predictor_ptr.reset(new NewPredictor()); - break; - } -``` -更新 `RegisterPredictors()` 如下: -```cpp - RegisterPredictor(ObstacleConf::NEW_PREDICTOR); -``` +轨迹点序列 = 2D位置点 + 时间 = 3D轨迹序列 -完成以上步骤后,一个新的预测器就创建好了。 +轨迹成本函数(偏离道路中心 、 碰撞可能性、速度限制、轨迹乘客舒适度(轨迹曲率加速度)) -# ================= -# 如何在Apollo中添加新的车辆 +规划前需要 预测外界环境将会发生什么: -## 简介 -本文描述了如何向Apollo中添加新的车辆。 +动态物体(动态障碍物) 路径轨迹预测 -``` -注意: Apollo控制算法将林肯MKZ配置为默认车辆 -``` +基于模式(直行模式和右转模式)的预测 / 基于数据驱动(机器学习模型)的预测 -添加新的车辆时,如果您的车辆需要不同于Apollo控制算法提供的属性,请参考: +十字路口 车辆行为预测 (车道线序列(空间标号),车道序列框架,利用RNN来预测,根据时序数据,来预测物体行为) -- 使用适合您的车辆的其它控制算法。 -- 修改现有算法的参数以获得更好的结果。 +apollo 使用RNN 模型 预测 车辆的 目标车道 ,然后根据车辆目标车道序列,预测车辆行为轨迹 -## 增加新车辆 -完成以下任务以添加新车辆: +**Frenet坐标系**是一种以比传统**x,y笛卡尔坐标系**更直观的方式表示道路位置的方式。用Frenet坐标,我们使用变量 s和d描述车辆在道路上的位置。该s坐标表示沿道路的距离(也称为纵向位移)和d坐标表示道路上的左右位置(也称为横向位移)。 -* 实现新的车辆控制器。 +由于通常道路都是曲折的,这样的话用笛卡尔坐标系描述道路会非常复杂,但是如果采用Frenet坐标系,Frenet坐标系是一道路中间线为坐标系分割轴 -* 实现新的消息管理器。 +离散化解决: -* 实施新的车辆工厂。 +路径规划,生成车辆可行的 轨迹(道路分成格子(单元格),格子分为序列点,点连线),使用成本函数进行评估 -* 更新配置文件。 +速度规划,速度曲线规划,ST图,速度-时间二维图,图中标记动态障碍物的区域。 -### 实现新的车辆控制器 -新的车辆控制器是从 `VehicleController`类继承的。 下面提供了一个头文件示例。 -```cpp -/** - * @class NewVehicleController - * - * @brief this class implements the vehicle controller for a new vehicle. - */ -class NewVehicleController final : public VehicleController { - public: - /** - * @brief initialize the new vehicle controller. - * @return init error_code - */ - ::apollo::common::ErrorCode Init( - const VehicleParameter& params, CanSender* const can_sender, - MessageManager* const message_manager) override; +折线段-----通过**二次规划**,使用平滑的非线性曲面来拟合这个 折线段 - /** - * @brief start the new vehicle controller. - * @return true if successfully started. - */ - bool Start() override; +然后使用 Lattice规划 轨迹生成方法 - /** - * @brief stop the new vehicle controller. - */ - void Stop() override; +三维轨迹 分解为 ST (纵向时间轨迹)轨迹 和 SL(横向时间)轨迹 ,分别求取,然后合并。 - /** - * @brief calculate and return the chassis. - * @returns a copy of chassis. Use copy here to avoid multi-thread issues. - */ - Chassis chassis() override; +定速巡航模式、跟随模式、停止模式 - // more functions implemented here - ... +**自动驾驶汽车主要使用的行为决策算法有以下3 种** +* 基于神经网络:自动驾驶汽车的决策系统主要采用神经网络确定具体的场景并做出适当的行为决策。 +* 基于规则:工程师想出所有可能的“if-then 规则”的组合,然后再用基于规则的技术路线对汽车的决策系统进行编程。 -}; -``` -### 实现新的消息管理器 -新的消息管理器是从 `MessageManager` 类继承的。 下面提供了一个头文件示例。 -```cpp -/** - * @class NewVehicleMessageManager - * - * @brief implementation of MessageManager for the new vehicle - */ -class NewVehicleMessageManager : public MessageManager { - public: - /** - * @brief construct a lincoln message manager. protocol data for send and - * receive are added in the construction. - */ - NewVehicleMessageManager(); - virtual ~NewVehicleMessageManager(); - - // define more functions here. - ... -}; -``` +* 混合路线:结合了以上两种决策方式,通过集中性神经网络优化,通过“if-then 规则”完善。混合路线是最流行的技术路线。 -### 实施新的车辆工厂 -新的车辆工厂是从 `AbstractVehicleFactory` 类继承的。下面提供了一个头文件示例。 -```cpp -/** - * @class NewVehicleFactory - * - * @brief this class is inherited from AbstractVehicleFactory. It can be used to - * create controller and message manager for lincoln vehicle. - */ -class NewVehicleFactory : public AbstractVehicleFactory { - public: - /** - * @brief destructor - */ - virtual ~NewVehicleFactory() = default; - - /** - * @brief create lincoln vehicle controller - * @returns a unique_ptr that points to the created controller - */ - std::unique_ptr CreateVehicleController() override; - - /** - * @brief create lincoln message manager - * @returns a unique_ptr that points to the created message manager - */ - std::unique_ptr CreateMessageManager() override; -}; -``` -一个.cc示例文件如下: -```cpp -std::unique_ptr -NewVehicleFactory::CreateVehicleController() { - return std::unique_ptr(new lincoln::LincolnController()); -} - -std::unique_ptr NewVehicleFactory::CreateMessageManager() { - return std::unique_ptr(new lincoln::LincolnMessageManager()); -} -``` +感知与决策技术的核心是人工智能算法与芯片。人工智能算法的实现需要强大的计算能力做支撑,特别是深度学习算法的大规模使用,对计算能力提出了更高的要求。随着人工智能业界对于计算能力要求的快速提升,进入2015 年后,业界开始研发针对人工智能的专用芯片,通过更好的硬件和芯片架构,在计算效率上进一步带来大幅的提升。 -Apollo提供可以用于实现新的车辆协议的基类 `ProtocolData`。 -### 更新配置文件 +## 4.控制与执行 -在`modules/canbus/vehicle/vehicle_factory.cc`里注册新的车辆。 下面提供了一个头文件示例。 -```cpp -void VehicleFactory::RegisterVehicleFactory() { - Register(VehicleParameter::LINCOLN_MKZ, []() -> AbstractVehicleFactory* { - return new LincolnVehicleFactory(); - }); +自动驾驶汽车的车辆控制系统是自动驾驶汽车行驶的基础,包括车辆的纵向控制和横向控制。纵向控制,即车辆的驱动与制动控制,是指通过对油门和制动的协调,实现对期望车速的精确跟随。横向控制,即通过方向盘角度的调整以及轮胎力的控制,实现自动驾驶汽车的路径跟踪。 - // register the new vehicle here. - Register(VehicleParameter::NEW_VEHICLE_BRAND, []() -> AbstractVehicleFactory* { - return new NewVehicleFactory(); - }); -} -``` -### 更新配置文件 -在 `modules/canbus/conf/canbus_conf.pb.txt` 中更新配置,在Apollo系统中激活车辆。 -```config -vehicle_parameter { - brand: NEW_VEHICLE_BRAND - // put other parameters below - ... -} -``` -======= -# 如何在Apollo中添加新的车辆 +* 纵向控制.自动驾驶汽车采用油门和制动综合控制的方法来实现对预定车速的跟踪,各种电机-发动机-传动模型、汽车运行模型和刹车过程模型与不同的控制算法相结合,构成了各种各样的纵向控制模式。 -## 简介 -本文阐述了如何向Apollo中添加新的车辆。 +* 横向控制.车辆横向控制主要有两种基本设计方法:基于驾驶员模拟的方法和基于车辆动力学模型的控制方法。 -``` -注意: Apollo控制算法将林肯MKZ配置为默认车辆。 -``` +基于驾驶员模拟的方法:一种是使用较简单的动力学模型和驾驶员操纵规则设计控制器;另一种是用驾驶员操纵过程的数据训练控制器获取控制算法。 -添加新的车辆时,如果您的车辆需要不同于Apollo控制算法提供的属性,请参考: +基于车辆动力学模型的方法:需要建立较精确的汽车横向运动模型。典型模型如单轨模型,该模型认为汽车左右两侧特性相同。 -- 使用适合您的车辆的其它控制算法。 -- 修改现有算法的参数以获得更好的结果。 +* 车辆控制平台.车辆控制平台是无人车的核心部件,控制着车辆的各种控制系统。其主要包括电子控制单元(ECU)和通信总线两部分。ECU 主要用来实现控制算法,通信总线主要用来实现ECU与机械部件间的通信功能. -## 增加新车辆 +* 通信总线:目前,车用总线技术被国际自动机工程师学会(SEA)下的汽车网络委员会按照协议特性分为A、B、C、D 共4类. -按照以下步骤以实现新车辆的添加: -* 实现新的车辆控制器 +规划 输出了一系列 三维轨迹点 位置x,y,速度,时间 -* 实现新的消息管理器 +控制的目的是,尽可能地按照规划的路径,使车辆舒适的通过。 -* 实现新的车辆工厂 + 利用转向 修正 轨迹 符合 目标轨迹(x,y) + 利用油门/制动 修正速度 符合 目标速度 -* 注册新的车辆 +控制有三种策略: -* 更新配置文件 +> **比例积分微分控制器 PID控制器 :** + + P 比例控制 Kp * 误差 误差 = 目标值 - 实际测量值 + D 微分控制 Kd * 误差导数 误差导数 = 误差变化的快慢 + I 积分控制 Ki * 误差积分 累计误差 = 误差累计 误差和时间的面积 + + 仅是线性控制器 + + 对于速度的控制 和 轨迹的控制 需要分开控制 解耦控制 + -### 实现新的车辆控制器 -新的车辆控制器是从 `VehicleController`类继承的。 下面提供了一个头文件示例。 -```cpp -/** - * @class NewVehicleController - * - * @brief this class implements the vehicle controller for a new vehicle. - */ -class NewVehicleController final : public VehicleController { - public: - /** - * @brief initialize the new vehicle controller. - * @return init error_code - */ - ::apollo::common::ErrorCode Init( - const VehicleParameter& params, CanSender* const can_sender, - MessageManager* const message_manager) override; +> **线性二次调节器 LQR控制器 也处理线性控制** + + 基于模型的控制器:利用车辆状态 来使误差最小化 + + apollo 使用 LQR 完成 横向控制 即 转向控制 + + 输入 汽车状态 x : 与目标轨迹的横向误差、横向误差变化率、与目标轨迹的朝向误差,朝向误差变化率 + 当前输出状态 u :转向、油门、刹车 + + + x'(导数) = A * x + B * u + + 利用最小化 输入 和输出 来求解 + + cost函数 = 积分(x转置Qx + u转置Ru)dt + + 其中 u = -k * x, 输入可以由 输入x求解优化计算得出 + + - /** - * @brief start the new vehicle controller. - * @return true if successfully started. - */ - bool Start() override; +> **模型预测控制器 MPC** - /** - * @brief stop the new vehicle controller. - */ - void Stop() override; +一种更复杂的控制器,非常依赖于数学优化 - /** - * @brief calculate and return the chassis. - * @returns a copy of chassis. Use copy here to avoid multi-thread issues. - */ - Chassis chassis() override; +1. 建立车辆模型, - // more functions implemented here - ... +根据车辆状态x 和控制输入 得出 汽车轨迹的模型 -}; -``` -### 实现新的消息管理器 -新的消息管理器是从 `MessageManager` 类继承的。 下面提供了一个头文件示例。 -```cpp -/** - * @class NewVehicleMessageManager - * - * @brief implementation of MessageManager for the new vehicle - */ -class NewVehicleMessageManager : public MessageManager { - public: - /** - * @brief construct a lincoln message manager. protocol data for send and - * receive are added in the construction. - */ - NewVehicleMessageManager(); - virtual ~NewVehicleMessageManager(); - - // define more functions here. - ... -}; -``` +2. 使用优化引擎计算有限时间范围内的控制输入 序列 -### 实施新的车辆工厂 -新的车辆工厂是从 `AbstractVehicleFactory` 类继承的。下面提供了一个头文件示例。 -```cpp -/** - * @class NewVehicleFactory - * - * @brief this class is inherited from AbstractVehicleFactory. It can be used to - * create controller and message manager for lincoln vehicle. - */ -class NewVehicleFactory : public AbstractVehicleFactory { - public: - /** - * @brief destructor - */ - virtual ~NewVehicleFactory() = default; - - /** - * @brief create lincoln vehicle controller - * @returns a unique_ptr that points to the created controller - */ - std::unique_ptr CreateVehicleController() override; - - /** - * @brief create lincoln message manager - * @returns a unique_ptr that points to the created message manager - */ - std::unique_ptr CreateMessageManager() override; -}; -``` -一个.cc示例文件如下: -```cpp -std::unique_ptr -NewVehicleFactory::CreateVehicleController() { - return std::unique_ptr(new lincoln::LincolnController()); -} - -std::unique_ptr NewVehicleFactory::CreateMessageManager() { - return std::unique_ptr(new lincoln::LincolnMessageManager()); -} -``` +利用 车辆模型和其约束条件,在可行域空间内搜索最优 轨迹策略,利用评价函数进行筛选 -Apollo提供可以用于实现新车辆协议的基类 `ProtocolData`。 +3. 执行第一组控制输入 -### 注册新的车辆 +重复 1、2、3 -在`modules/canbus/vehicle/vehicle_factory.cc`里注册新车辆。 下面提供了一个头文件示例。 -```cpp -void VehicleFactory::RegisterVehicleFactory() { - Register(VehicleParameter::LINCOLN_MKZ, []() -> AbstractVehicleFactory* { - return new LincolnVehicleFactory(); - }); - // register the new vehicle here. - Register(VehicleParameter::NEW_VEHICLE_BRAND, []() -> AbstractVehicleFactory* { - return new NewVehicleFactory(); - }); -} -``` -### 更新配置文件 -在 `modules/canbus/conf/canbus_conf.pb.txt` 中更新配置,在Apollo系统中激活车辆。 -```config -vehicle_parameter { - brand: NEW_VEHICLE_BRAND - // put other parameters below - ... -} -``` -# ==================== -[使用VSCode构建、调试Apollo项目](https://github.com/ApolloAuto/apollo/blob/master/docs/howto/how_to_build_and_debug_apollo_in_vscode_cn.md) +## 5.高精地图与车联网V2X +* 高精地图拥有精确的车辆位置信息和丰富的道路元素数据信息,起到构建类似于人脑对于空间的整体记忆与认知的功能,可以帮助汽车预知路面复杂信息,如坡度、曲率、航向等,更好地规避潜在的风险,是自动驾驶汽车的核心技术之一。 -# ===================== -## 如何调试Dreamview启动问题 +高精地图相比服务于GPS 导航系统的传统地图而言,最显著的特征是其表征路面特征的精准性。传统地图只需要做到米量级的精度就可以实现基于GPS 的导航,而高精地图需要至少十倍以上的精度,即达到厘米级的精度才能保证自动驾驶汽车行驶的安全。 -### Dreamview的启动步骤 +同时,高精地图还需要有比传统地图更高的实时性。由于道路路网经常会发生变化,如道路整修、标识线磨损或重漆、交通标识改变等。这些改变都要及时反映在高精地图上,以确保自动驾驶汽车的行车安全。 -如果在`docker / scripts / dev`序列中启动Dreamview时遇到问题,请首先检查是否使用了如下所示的正确命令。 -```bash -$ bash docker/scripts/dev_start.sh -$ bash docker/scripts/dev_into.sh -$ cd /apollo -$ bash apollo.sh build -$ bash scripts/dreamview.sh -``` -### Dreamview启动失败 +**百度高精度地图 openDrive** -如果Dreamview无法启动,请使用下面的脚本检查Dreamview的启动日志并重新启动Dreamview。 +数据收集(实车带传感器实地跑) -> 数据处理(整理、分类、清洗) -> 目标检测分类(车道线、路标、交通标示、电线杆) -> 人工验证 -> 地图发布 -```bash -# Start Dreamview in foreground to see any error message it prints out during startup -$ bash scripts/dreamview.sh start_fe -# check dreamview startup log -$ cat data/log/dreamview.out -terminate called after throwing an instance of 'CivetException' - what(): null context when constructing CivetServer. Possible problem binding to port. +* 车联网V2X -$ sudo apt-get install psmisc +V2X 表示Vehicle to X,其中X 表示基础设施(Infrastructure)、车辆(Vehicle)、行人(Pedestrian)、道路(Road)等。V2X 网联通信集成了V2N、V2V、V2I 和V2P 共四类关健技术。 -# to check if dreamview is running from other terminal -$ sudo lsof -i :8888 +V2N(Vehicle to Network,车-互联网),通过网络将车辆连接到云服务器,能够使用云服务器上的娱乐、导航等功能。 -# kill other running/pending dreamview -$ sudo fuser -k 8888/tcp +V2V(Vehicle to Vehicle,车-车),指不同车辆之间的信息互通。 -# restart dreamview again -$ bash scripts/dreamview.sh -``` +V2I(Vehicle to Infrastructure,车-基础设施),包括车辆与路障、道路、交通灯等设施之间的通信,用于获取路障位置、交通灯信号时序等道路管理信息。 -### 用gdb调试 +V2P(Vehicle to Pedestrian,车-行人),指车辆与行人或非机动车之间的交互,主要是提供安全警告。 -如果dreamview的启动日志中没有任何有效内容,您可以尝试使用gdb调试dreamview,请使用以下命令: +V2X 技术的实现一般基于RFID、拍照设备、车载传感器等硬件平台。V2X 网联通信产业分为DSRC 和LTE-V2X 两个标准和产业阵营。 -``` -$ gdb --args /apollo/bazel-bin/modules/dreamview/dreamview --flagfile=/apollo/modules/dreamview/conf/dreamview.conf -# or -$ source scripts/apollo_base.sh; -$ start_gdb dreamview -``` -一旦gdb启动,按下`r`和`enter`键运行,如果dreamview崩溃,然后用`bt`获得回溯。 +〉6.自动驾驶汽车测试与验证技术 -如果您在gdb backtrace中看到错误“非法指令”以及与 **libpcl_sample_consensus.so.1.7** 相关的内容,那么您可能需要自己从源代码重建pcl lib并替换docker中的那个。 +* 实测.让车辆行驶数百万公里,以确定设计的系统是否安全并按照预期运行。该方法的困难在于必须累积的测试里程数,这可能要花费大量的时间。 -这通常发生在您尝试在CPU不支持FMA/FMA3指令的机器上运行Apollo/dreamview时,它会失败,因为docker image附带的预构建的pcl lib是使用FMA/ FMA3支持编译的。 +* 软件在环或模型在环仿真.另一种更可行的方法是将现实世界的测试与仿真相结合。在仿真软件所构建的各种场景中,通过算法控制车辆进行相应的应对操作,来证明所设计的系统确实可以在各种场景下做出正确的决定,这可以大大减少必须完成的测试里程数。 -# ================== -# 如何在本地运行多传感器融合定位模块 +* 硬件在环仿真.为了验证真实硬件的运行情况,硬件在环仿真可以对其进行测试,并将预先记录的传感器数据提供给系统,此种技术路线可以降低车辆测试和验证的成本。 -本文档提供了如何在本地运行多传感器融合定位模块的方法。 +## 人工智能在自动驾驶汽车中的应用 +### 工智能在环境感知中的应用 +环境感知包括:可行驶路面检测、车道线检测、路缘检测、护栏检测、行人检测、机动车检测、非机动车检测、路标检测、交通标志检测、交通信号灯检测等。 -## 1. 事先准备 - - 从[GitHub网站](https://github.com/ApolloAuto/apollo)下载Apollo源代码 - - 按照[教程](https://github.com/ApolloAuto/apollo/blob/master/README_cn.md)设置Docker环境并搭建Apollo工程 - - 从[Apllo数据平台](http://data.apollo.auto/?name=sensor%20data&data_key=multisensor&data_type=1&locale=en-us&lang=en)下载多传感器融合定位数据(仅限美国地区) +对于如此复杂的路况检测,深度学习能够满足视觉感知的高精度需求。基于深度学习的计算机视觉,可获得较接近于人的感知能力。有研究报告指出深度学习在算法和样本量足够的情况下,视觉感知的准确率可以达到99.9%以上,而传统视觉算法的检测精度极限在93%左右,人感知的准确率一般是95%左右。 -## 2. 配置定位模块 -为了使定位模块正确运行,需要对地图路径和传感器外参进行配置。假设下载的定位数据的所在路径为DATA_PATH。 +### 人工智能在决策与规划中的应用 -在进行以下步骤前,首先确定你在docker容器中。 +行为决策与路径规划是人工智能在自动驾驶汽车领域中的另一个重要应用。前期决策树、贝叶斯网络等人工智能方法已有大量应用。近年来兴起的深度卷积神经网络与深度强化学习,能通过大量学习实现对复杂工况的决策,并能进行在线学习优化,由于需要较多的计算资源,当前是计算机与互联网领域研究自动驾驶汽车的决策与规划处理的热门技术。随着深度强化学习的兴起,越来越多的公司和研究者把强化学习应用到无人车的行为与决策中,并取得了不错的效果. -### 2.1 配置传感器外参 -将定位数据中的传感器外参拷贝至指定文件夹下。 +可学习部分是将无人车所处的环境映射成一系列抽象策略的过程。他们设计了一张策略选项图,主要包含无人车的加减速、转向以及对周围车辆的反应,并利用策略网络来选择合适的应对选项。其中,策略网络在给定的车辆环境下,评估每一种应对的可能影响,从而选择最合适的策略。不可学习部分则是将学习到的抽象策略转化成对车辆的实际控制动作,该部分主要对车辆动作进行具体规划,检查抽象策略是否可执行,或者执行满足策略的动作,从而充分保证系统的安全性。 -``` - cp DATA_PATH/params/ant_imu_leverarm.yaml /apollo/modules/localization/msf/params/gnss_params/ - cp DATA_PATH/params/velodyne64_novatel_extrinsics_example.yaml /apollo/modules/localization/msf/params/velodyne_params/ - cp DATA_PATH/params/velodyne64_height.yaml /apollo/modules/localization/msf/params/velodyne_params/ -``` -各个外参的意义 - - ant_imu_leverarm.yaml: 杆臂值参数,GNSS天线相对Imu的距离 - - velodyne64_novatel_extrinsics_example.yaml: Lidar相对Imu的外参 - - velodyne64_height.yaml: Lidar相对地面的高度 +### 人工智能在车辆控制中的应用 -### 2.2 配置地图路径 -在/apollo/modules/localization/conf/localization.conf中添加关于地图路径的配置 +相对于传统的车辆控制方法,智能控制方法主要体现在对控制对象模型的运用和综合信息学习运用上,包括神经网络控制和深度学习方法等,这些算法已逐步在车辆控制中广泛应用。 -``` -# Redefine the map_dir in global_flagfile.txt ---map_dir=DATA_PATH -``` -这将会覆盖global_flagfile.txt中的默认值。 +* **神经控制**,是研究和利用人脑的某些结构机理以及人的知识和经验对系统的控制。利用神经网络,可以把控制问题看成模式识别问题,被识别的模式映射成“行为”信号的“变化”信号。神经控制最显著的特点是具有学习能力。它是通过不断修正神经元之间的连接权值,并离散存储在连接网络中来实现的。它对非线性系统和难以建模的系统的控制具有良好效果。 -## 3. 运行多传感器融合定位模块 -``` -./scripts/localization.sh -``` -定位程序将在后台运行,可以通过以下命令进行查看。 -``` -ps -e | grep localization -``` -在/apollo/data/log目录下,可以看到定位模块输出的相关文件。 +* **深度神经网络学习**,源于神经网络的研究,可理解为深层的神经网络。通过它可以获得深层次的特征表示,免除人工选取特征的繁复冗杂和高维数据的维度灾难问题。深度学习在特征提取与模型拟合方面显示了其潜力和优势。对于存在高维数据的控制系统,引入深度学习具有一定的意义。自动驾驶系统需要尽量减少人的参与或者没有人的参与,深度学习自动学习状态特征的能力使得深度学习在自动驾驶系统的研究中具有先天的优势。 - - localization.INFO : INFO级别的log信息 - - localization.WARNING : WARNING级别的log信息 - - localization.ERROR : ERROR级别的log信息 - - localization.out : 标准输出重定向文件 - - localizaiton.flags : 启动localization模块使用的配置 +* **深度强化学习**,强化学习的灵感来源于生物学中的动物行为训练,训练员通过奖励与惩罚的方式让动物学会一种行为与状态之间的某种联系规则。强化学习就是要解决这类问题:一个能够感知环境的智能体怎样通过学习选择达到其目标的最优动作。 -## 4. 播放演示rosbag -``` -cd DATA_PATH/bag -rosbag play *.bag -``` -从播放数据到定位模块开始输出定位消息,大约需要30s左右。 -## 5. 记录与可视化定位结果(可选) -### 记录定位结果 -``` -./scripts/record_bag.sh -``` -该脚本会在后台运行录包程序,并将存放路径输出到终端上。 -### 可视化定位结果 +## 应用篇 -运行可视化工具 +业界普遍认为,自动驾驶技术在公共交通领域和特定场所的使用将早于在个人乘用车市场的普及。自动驾驶汽车将最先应用的行业包括公共交通、快递运输、服务于老年人和残疾人. -``` -./scripts/localization_online_visualizer.sh -``` -该可视化工具首先根据定位地图生成用于可视化的缓存文件,存放在/apollo/data/map_visual目录下。 +自动驾驶巴士、无人驾驶出租车、物流运输、服务于残疾人 -然后接收以下topic并进行可视化绘制。 +自动驾驶巴士被认为是解决城市“最后一公里”难题的有效方案,大多用于机场、旅游景区和办公园区等封闭的场所。 - - /apollo/sensor/velodyne64/compensator/PointCloud2 - - /apollo/localization/msf_lidar - - /apollo/localization/msf_gnss - - /apollo/localization/pose +自动驾驶汽车在公共交通领域的另一个重要应用是出租车。 -可视化效果如下 -![1](https://github.com/ApolloAuto/apollo/tree/master/docs/howto/images/msf_localization/online_visualizer.png) +快递用车和“列队”卡车将是另外一个较快采用自动驾驶汽车的领域。 +随着全球老龄化问题的加剧,自动驾驶技术在快递等行业的应用将极大地弥补劳动力不足的问题,并且随着自动驾驶技术的成熟与市场普及程度的提高,无人配送将成为必然的趋势。 -如果发现可视化工具运行时卡顿,可使用如下命令重新编译可视化工具 +自动驾驶汽车已经开始在老年人和残疾人这两个消费群体中有所应用。自动驾驶汽车不仅可增强老年人的移动能力,也能帮助残疾人旅行。 -``` -cd /apollo -bazel build -c opt //modules/localization/msf/local_tool/local_visualization/online_visual:online_local_visualizer -``` -编译选项-c opt优化程序性能,从而使可视化工具可以实时运行。 +## 困难和挑战 -## 6. 结束运行定位模块 +自动驾驶的一个很重要的用途是用于某些特殊的环境下,由于在某些特殊的环境下,人员生存困难,自动驾驶能克服这些问题,但是其也要解决如极寒、道路条件复杂等各种极端环境的影响,这同样也是自动驾驶未来发展所应面临的困难。 -``` -./scripts/localization.sh stop -``` +由于人工智能的大量应用,自动驾驶技术更依赖于网络,如通过云端获取的高精地图、精准导航等的数据,其安全性显得尤为突出。如何打造安全可靠的数据链路,不被黑客侵扰等也将是需要长期面临的困难与挑战。 -如果之前有运行步骤5的录包脚本,还需执行 -``` -./scripts/record_bag.sh stop -``` +# Apollo 相关介绍 -## 7. 验证定位结果(可选) -假设步骤5中录取的数据存放路径为OUTPUT_PATH,杆臂值外参的路径为ANT_IMU_PATH -运行脚本 ``` -./scripts/msf_local_evaluation.sh OUTPUT_PATH ANT_IMU_PATH +We choose to go to the moon in this decade and do the other things, +not because they are easy, but because they are hard. +-- John F. Kennedy, 1962 ``` -该脚本会以RTK定位模式为基准,将多传感器融合模式的定位结果进行对比。 - -(注意只有在GNSS信号良好,RTK定位模式运行良好的区域,这样的对比才是有意义的。) - -获得如下统计结果: - -![2](https://github.com/ApolloAuto/apollo/tree/master/docs/howto/images/msf_localization/localization_result.png) - -可以看到两组统计结果,第一组是组合导航(输出频率200hz)的统计结果,第二组是点云定位(输出频率5hz)的统计结果,第三组是GNSS定位(输出频率约1hz)的统计结果。 - -表格中各项的意义, - - error: 平面误差,单位为米 - - error lon: 车前进方向的误差,单位为米 - - error lat: 车横向方向的误差,单位为米 - - error roll: 翻滚角误差,单位为度 - - error pit: 俯仰角误差,单位为度 - - error yaw: 偏航角误差,单位为度 - - mean: 误差的平均值 - - std: 误差的标准差 - - max: 误差的最大值 - - <30cm: 距离误差少于30cm的帧所占的百分比 - - <1.0d: 角度误差小于1.0d的帧所占的百分比 - - con_frame(): 满足括号内条件的最大连续帧数 - - - # =========================== - # 如何调节控制参数 - -## 引言 -控制模块的目标是基于计划轨迹和当前车辆状态生成控制命令给车辆。 - -## 背景 - -### 输入/输出 - -#### 输入 -* 规划轨迹 -* 当前的车辆状态 -* HMI驱动模式更改请求 -* 监控系统 - -#### 输出 -输出控制命令管理`canbus`中的转向、节流和制动等功能。 - -### 控制器介绍 -控制器包括管理转向指令的横向控制器和管理节气门和制动器命令的纵向控制器。 - -#### 横向控制器 -横向控制器是基于LQR的最优控制器。 该控制器的动力学模型是一个简单的带有侧滑的自行车模型。它被分为两类,包括闭环和开环。 - -- 闭环提供具有4种状态的离散反馈LQR控制器: - - 横向误差 - - 横向误差率 - - 航向误差 - - 航向误差率 -- 开环利用路径曲率信息消除恒定稳态航向误差。 - - -#### 纵向控制器 -纵向控制器配置为级联PID +校准表。它被分为两类,包括闭环和开环。 -- 闭环是一个级联PID(站PID +速度PID),它将以下数据作为控制器输入: - - 站误差 - - 速度误差 -- 开环提供了一个校准表,将加速度映射到节气门/制动百分比。 - - -## 控制器调谐 +Welcome to the Apollo GitHub. -### 实用工具 -类似于[诊断](https://github.com/ApolloAuto/apollo/tree/master/modules/tools/diagnostics) 和 [realtime_plot](https://github.com/ApolloAuto/apollo/tree/master/modules/tools/realtime_plot) 可用于控制器调优,并且可以在`apollo/modules/tools/`中找到. -### 横向控制器的整定 -横向控制器设计用于最小调谐力。“所有”车辆的基础横向控制器调谐步骤如下: +[Apollo](http://apollo.auto) 开源自动驾驶平台. +It is a high performance flexible architecture which supports fully autonomous driving capabilities. +For business contact, please visit http://apollo.auto -1. 将`matrix_q` 中所有元素设置为零. +**Apollo Team now proudly presents to you the latest [version 2.5](https://github.com/ApolloAuto/apollo/releases/tag/v2.5.0).** -2. 增加`matrix_q`中的第三个元素,它定义了航向误差加权,以最小化航向误差。 +## 安装 -3. 增加`matrix_q`的第一个元素,它定义横向误差加权以最小化横向误差。 +推荐在 Docker environment 中安装 -#### 林肯MKZ调谐 +The steps are: + - 1. Run a machine that runs linux (tested on Ubuntu 16.04 with and without an nVidia GPU) + - 2. Create a docker environment + - 3. Build Apollo from source + - 4. Bootstrap start Apollo + - 5. Download the demonstration loop and run it + - 6. Start a browser session and see the Dreamview user interface -对于Lincoln MKZ,有四个元素指的是状态加权矩阵Q的对角线元素: +More instructions are below -- 横向误差加权 -- 横向误差率加权 -- 航向误差加权 -- 航向差错率加权 +### docker environment 安装 -通过在横向控制器调谐中列出的基本横向控制器调整步骤来调整加权参数。下面是一个例子。 +First, you need to [install docker-ce properly](https://github.com/ApolloAuto/apollo/blob/master/docker/scripts/README.md#install-docker). +The following scripts will get you into the container ``` -lat_controller_conf { - matrix_q: 0.05 - matrix_q: 0.0 - matrix_q: 1.0 - matrix_q: 0.0 -} -``` - -#### 调谐附加车辆类型 +docker ps # to verify docker works without sudo +bash docker/scripts/dev_start.sh +# if in China, you had better use:bash docker/scripts/dev_start.sh -C to download from the server of docker in china. +bash docker/scripts/dev_into.sh -当调整除林肯MKZ以外的车辆类型时,首先更新车辆相关的物理参数,如下面的示例所示。然后,按照上面列出的基本横向控制器调整步骤*横向控制器调谐*和定义矩阵Q参数。 +``` -下面是一个例子. +### 源码编译 apollo ``` -lat_controller_conf { - cf: 155494.663 - cr: 155494.663 - wheelbase: 2.85 - mass_fl: 520 - mass_fr: 520 - mass_rl: 520 - mass_rr: 520 - eps: 0.01 - steer_transmission_ratio: 16 - steer_single_direction_max_degree: 470 -} +# To get a list of build commands +./apollo.sh +# To make sure you start clean +./apollo.sh clean +# This will build the full system and requires that you have an nVidia GPU with nVidia drivers loaded +bash apollo.sh build ``` -### 纵控制器的调谐 -纵向控制器由级联的PID控制器组成,该控制器包括一个站控制器和一个具有不同速度增益的高速/低速控制器。Apollo管理开环和闭环的调谐通过: - -- 开环: 校准表生成。请参阅[how_to_update_vehicle_calibration.md](https://github.com/ApolloAuto/apollo/blob/master/docs/howto/how_to_update_vehicle_calibration.md)的详细步骤 -- 闭环: 基于高速控制器->低速控制器->站控制器的顺序。 - -#### 高/低速控制器的调谐 +If you do not have an nVidia GPU, the system will run but with the CUDA-based perception and other modules. -高速控制器代码主要用于跟踪高于某一速度值的期望速度。例如: +You mustspecify either `dbg` for debug mode or `opt` for optimized code ``` -high_speed_pid_conf { - integrator_enable: true - integrator_saturation_level: 0.3 - kp: 1.0 - ki: 0.3 - kd: 0.0 -} -``` -1. 首先将`kp`, `ki`, 和 `kd` 的值设为0. -2. 然后开始增加`kp`的值,以减小阶跃响应对速度变化的上升时间。 -3. 最后,增加`ki`以降低速度控制器稳态误差。 - -一旦获得较高速度的相对准确的速度跟踪性能,就可以开始从起点开始调整低速PID控制器以获得一个舒适的加速率。 - - ``` - low_speed_pid_conf { - integrator_enable: true - integrator_saturation_level: 0.3 - kp: 0.5 - ki: 0.3 - kd: 0.0 - } - ``` -*注意:* 当设备切换到 *Drive*时,Apollo 通常将速度设置为滑行速度。 - -#### 站控制器调谐 - -Apollo 使用车辆的站控制器来跟踪车辆轨迹基准与车辆位置之间的站误差。 一个站控制器调谐示例如下所示。 -``` -station_pid_conf { - integrator_enable: true - integrator_saturation_level: 0.3 - kp: 0.3 - ki: 0.0 - kd: 0.0 -} +./apollo.sh build_no_perception dbg ``` -## 参考文献 -1. "Vehicle dynamics and control." Rajamani, Rajesh. Springer Science & Business Media, 2011. - -2. "Optimal Trajectory generation for dynamic street scenarios in a Frenet - Frame", M. Werling et., ICRA2010 - -# ===================== -# 如何标定车辆油门和制动 - -## 介绍 - -车辆校准的目的是找到准确产生从控制模块请求的加速量的油门和制动命令 -## 准备 - -按如下顺序完成准备工作: -- 访问相关代码 -- 改变驾驶模式 -- 选择测试地点 - -### 访问相关代码 -* Canbus, 包括以下模块: - * GPS 驱动 - * 定位 - -### 改变驾驶模式 - 在`modules/canbus/conf/canbus_conf.pb.txt`中,设置驾驶模式为 `AUTO_SPEED_ONLY`. -### 选择测试地点 - 理想的测试地点是平坦的长直路 - -## 更新车辆标定 - -以上准备工作完成后, 在`modules/tools/calibration`中按顺序完成如下工作 - -- 采集数据 -- 处理数据 -- 绘制结果 -- 转换结果为`protobuf`格式 - -### 采集数据 -1. 运行 `python data_collector.py`,参数如 x y z, x 代表了加速的控制指令, y 代表了限制速度(mps), z 是减速指令,正值标识油门量,负值标识刹车量.且每条命令运行多次,其中 `data_collector.py`在modules/tools/calibration/ -2. 根据车辆反应情况,调整命令脚本 -3. 运行 `python plot_data.py ` 使采集到的数据可视化 - -比如输出指令 `15 5.2 -10`,将会生成名为`t15b-10r0.csv`的文件。 - -### 处理数据 -对每个记录的日志分别运行`process_data.sh {dir}`,其中dir为`t15b-10r0.csv`所在的目录。每个数据日志被处理成`t15b-10r0.csv.result`。 - -### 绘制结果 -通过运行`python plot_results.py t15b-10r0.csv`得到可视化最终结果,检查是否有异常 - -### 转换结果为`protobuf`格式 -如果一切正常,运行`result2pb.sh`,把校准结果result.csv转换成控制模块定义的`protobuf`格式 - - -# ==================== -# 运行线下演示 - -如果你没有车辆及车载硬件, Apollo还提供了一个计算机模拟环境,可用于演示和代码调试。 - -线下演示需要设置docker的release环境,请参照 [how_to_build_and_release](https://github.com/ApolloAuto/apollo/blob/master/docs/howto/how_to_build_and_release.md)文档中的[Install docker](https://github.com/ApolloAuto/apollo/blob/master/docs/howto/how_to_build_and_release.md#docker)章节。 +If you make modifications to the Dreamview frontend, then you must run `./apollo.sh build_fe` before you run the +full build. -Apollo演示的安装步骤: -1. 运行如下命令启动docker的release环境: +## 运行 Apollo - ``` - bash docker/scripts/release_start.sh - ``` +Follow the steps below to launch Apollo. Note that you must build the system first before you run it. +Note that the bootstrap.sh will actually succeed but the user interface will not come up if you skip the build step. -2. 运行如下命令进入docker的release环境: +### Start Apollo - ``` - bash docker/scripts/release_into.sh - ``` +Running Apollo will start the ROS core and then startup a web user interface called Dreamview, +this is handled by the bootstrap script, so from within the docker container, you should run: -3. 运行如下命令回放位rosbag: +``` +# start module monitor +bash scripts/bootstrap.sh +``` - ``` - python docs/demo_guide/rosbag_helper.py demo_1.5.bag # 下载rosbag - rosbag play demo_1.5.bag --loop - ``` +### Access Dreamview + Access Dreamview by opening your favorite browser, e.g. Chrome, go to http://localhost:8888 + and you should see this screenHowever, there will be nothing running in the system. - 选项 `--loop` 用于设置循环回放模式. +![Access Dreamview](https://github.com/Ewenwan/apollo/docs/demo_guide/images/apollo_bootstrap_screen.png) -4. 打开Chrome浏览器,在地址栏输入**localhost:8888**即可访问Apollo Dreamview,如下图所示: - ![](https://github.com/ApolloAuto/apollo/tree/master/docs/demo_guide/images/dv_trajectory.png) - 现在你能看到有一辆汽车在模拟器里移动! +### Select Drive Mode +From the dropdown box selet "Navigation" mode. -恭喜你完成了Apollo的演示步骤! +![Navigation Mode](https://github.com/Ewenwan/apollo/docs/demo_guide/images/dreamview_2_5_setup_profile.png) -# ================= -# 传感器标定 FAQs +### Replay demo rosbag -## 如何查看传感器是否有数据输出? +To see if the system works, use the demo 'bag' which feeds the system. -使用 rostopic 命令。例如,查看 HDL-64ES3 的输出,可以在终端中输入: +``` +# get rosbag note that the command download is required +python ./docs/demo_guide/rosbag_helper.py demo_2.5.bag -```bash - rostopic echo /apollo/sensor/velodyne64/VelodyneScanUnified +# You can now replay this demo "bag" in a loop with the '-l' flag +rosbag play -l demo_2.5.bag ``` - 若该 topic 的数据会显示在终端上,则激光雷达工作正常。 -## 如何查看车辆的定位状态? +Dreamview should show a running vehicle now. (The following image might be different due to changes in frontend.) -以使用 Novatel 组合惯导为例,在终端中输入: +![Dreamview with Trajectory](docs/demo_guide/images/dv_trajectory_2.5.png) -```bash -rostopic echo /apollo/sensor/gnss/ins_stat -``` +## Documents -找到“pos_type”字段,若该字段的值为 56,则表示进入了良好的定位状态 (RTK_FIXED),可以用于标定。若不为 56,则无法获得可靠的标定结果。 +Apollo documents can be found under the [docs](https://github.com/ApolloAuto/apollo/blob/master/docs/) repository. + * [quickstart](https://github.com/ApolloAuto/apollo/blob/master/docs/quickstart/): the quickstart tutorial. + * [demo_guide](https://github.com/ApolloAuto/apollo/blob/master/docs/demo_guide/): the guide for demonstration. + * [![Apollo Offline Demo](https://img.youtube.com/vi/Q4BawiLWl8c/0.jpg)](https://www.youtube.com/watch?v=Q4BawiLWl8c) + * [how to contribute code](https://github.com/ApolloAuto/apollo/blob/master/CONTRIBUTING.md): the guide for contributing code to Apollo. + * [howto](https://github.com/ApolloAuto/apollo/blob/master/docs/howto/): tutorials on how to build, run and modify codes. + * [specs](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/): Specification documents of Apollo. + * [Doxygen APIs](https://apolloauto.github.io/doxygen/apollo/): Apollo Doxygen pages -## 如何进行质检? +## Ask Questions -目前进行质检方法主要通过人工来完成。标定完成后,页面会提供标定过程中拼接得到的点云。若标定结果良好,会得到锐利和清晰的拼接点云,可反映出标定场地的细节。通常质检的参照物有平整的建筑立面、路灯和电线杆以及路沿等。若标定质量较差,则会使拼接点云出现一些模糊、重影的效果。图1是两张不同标定质量的拼接点云对比。 +You are welcome to submit questions and bug reports as [Github Issues](https://github.com/ApolloAuto/apollo/issues). -![](https://github.com/ApolloAuto/apollo/blob/master/docs/quickstart/images/calibration/lidar_calibration/good_calib.png) -

-(a) -

+## Copyright and License -![](https://github.com/ApolloAuto/apollo/blob/master/docs/quickstart/images/calibration/lidar_calibration/poor_calib.png) -

-(b) -

+Apollo is provided under the [Apache-2.0 license](LICENSE). -

-图1. (a) 高质量的标定结果 (b) 质量较差的标定结果。 -

+## Disclaimer +Please refer the Disclaimer of Apollo in [Apollo official website](http://apollo.auto/docs/disclaimer.html). +# =========================== +# Apollo 3.0 技术指南 -## 如何解决标定程序权限错误? +## 概况 +> 了解Apollo3.0基础概念和Apollo3.0快速入门指南 -Output path需要`write`权限来创建文件夹以及保存标定结果,若缺少相关权限,则会出现如下错误: + * [Apollo 3.0快速入门指南](https://github.com/ApolloAuto/apollo/blob/master/docs/quickstart/apollo_3_0_quick_start_cn.md) + +## 硬件和系统安装 +> 了解Apollo3.0硬件和系统安装过程 -```bash -terminate called after throwing an instance of ‘boost::filesystem::filesystem_error’ what(): boost::filesystem::create_directories: permission denied: “***” -``` + * [Apollo 3.0硬件和系统安装指南](https://github.com/ApolloAuto/apollo/blob/master/docs/quickstart/apollo_3_0_hardware_system_installation_guide_cn.md) -输入以下命令,来为Output path添加`write`权限: +## 校准 +> 了解校准的过程 -```bash -# 为output path(如:/apollo/modules/calibration/data/mkz8)添加write权限 -sudo chmod a+w /apollo/modules/calibration/data/mkz8 -R -``` + * [Apollo激光雷达校准指南](https://github.com/ApolloAuto/apollo/blob/master/docs/quickstart/apollo_1_5_lidar_calibration_guide_cn.md) + * [Apollo 2.0传感器校准指南](https://github.com/ApolloAuto/apollo/blob/master/docs/quickstart/apollo_2_0_sensor_calibration_guide_cn.md) + * [多激光雷达全球导航卫星系统(Multiple-LiDAR GNSS)校准指南](https://github.com/ApolloAuto/apollo/blob/master/docs/quickstart/multiple_lidar_gnss_calibration_guide_cn.md) + * [Apollo坐标系统](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/coordination_cn.md) -## 如何解决执行sensor_calibration.sh时出现的权限错误? +## 软件安装 +> 了解Apollo3.0的软件安装过程 -Log存储文件夹需要`write`权限来创建日志,若缺少相关权限,则会出现如下错误: + * [Apollo软件安装指南](https://github.com/ApolloAuto/apollo/blob/master/docs/quickstart/apollo_software_installation_guide_cn.md) + * [如何调试Dreamview启动问题](https://github.com/ApolloAuto/apollo/blob/master/docs/howto/how_to_debug_dreamview_start_problem_cn.md) + * [运行线下演示](https://github.com/ApolloAuto/apollo/blob/master/docs/demo_guide/README_cn.md) + +## Apollo系统架构和原理 +> 了解核心模块的架构和原理 -```bash -tee: /apollo/data/log/***.out: permission denied -``` + * [Apollo 3.0 软件架构](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/Apollo_3.0_Software_Architecture_cn.md "Apollo software architecture") + * [3D 障碍物感知](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/3d_obstacle_perception_cn.md) + * [Apollo 3.0感知](https://github.com/ApolloAuto/apollo/blob/master/modules/perception/README.md) + * [二次规划(QP)样条路径优化](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/qp_spline_path_optimizer_cn.md) + * [二次规划(QP)样条ST速度优化](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/qp_spline_st_speed_optimizer_cn.md) + * [参考线平滑设定](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/reference_line_smoother_cn.md) + * [交通信号灯感知](https://github.com/ApolloAuto/apollo/blob/master/docs/specs/traffic_light_cn.md) + +## 功能模块和相关扩展知识 +> 了解Apollo功能模块和相关扩展知识 -输入以下命令,来为脚本添加`write`权限: + * [控制总线模块](https://github.com/ApolloAuto/apollo/blob/master/modules/canbus/README.md) + * [通用模块](https://github.com/ApolloAuto/apollo/blob/master/modules/common/README.md) + * [控制模块](https://github.com/ApolloAuto/apollo/blob/master/modules/control/README.md) + * [数据模块](https://github.com/ApolloAuto/apollo/blob/master/modules/data/README.md) + * [定位模块](https://github.com/ApolloAuto/apollo/blob/master/modules/localization/README.md) + * [感知模块](https://github.com/ApolloAuto/apollo/blob/master/modules/perception/README.md) + * [Planning模块](https://github.com/ApolloAuto/apollo/blob/master/modules/planning/README.md) + * [预测模块](https://github.com/ApolloAuto/apollo/blob/master/modules/prediction/README.md) + * [寻路模块](https://github.com/ApolloAuto/apollo/blob/master/modules/routing/README.md) -```bash -sudo chmod a+x /apollo/data/log -``` + * [如何添加新的GPS接收器](https://github.com/ApolloAuto/apollo/blob/master/docs/howto/how_to_add_a_gps_receiver_cn.md) + * [如何添加新的CAN卡](https://github.com/ApolloAuto/apollo/blob/master/docs/howto/how_to_add_a_new_can_card_cn.md ) + * [如何添加新的控制算法](https://github.com/ApolloAuto/apollo/blob/master/docs/howto/how_to_add_a_new_control_algorithm_cn.md) + * [如何在预测模块中添加新评估器](https://github.com/ApolloAuto/apollo/blob/master/docs/howto/how_to_add_a_new_evaluator_in_prediction_module_cn.md) + * [如何在预测模块中添加一个预测器](https://github.com/ApolloAuto/apollo/blob/master/docs/howto/how_to_add_a_new_predictor_in_prediction_module_cn.md) + * [如何在Apollo中添加新的车辆](https://github.com/ApolloAuto/apollo/blob/master/docs/howto/how_to_add_a_new_vehicle_cn.md) + * [如何添加新的外部依赖项](https://github.com/ApolloAuto/apollo/blob/master/docs/howto/how_to_add_an_external_dependency_cn.md) + + ## 开发者工具 +> 了解开发者工具 -# ===================== + * [使用VSCode构建、调试Apollo项目](https://github.com/ApolloAuto/apollo/blob/master/docs/howto/how_to_build_and_debug_apollo_in_vs diff --git "a/UMCar/\350\207\252\345\212\250\351\251\276\351\251\266\347\240\224\347\251\266\346\212\245\345\221\212.pdf" "b/UMCar/\350\207\252\345\212\250\351\251\276\351\251\266\347\240\224\347\251\266\346\212\245\345\221\212.pdf" new file mode 100644 index 00000000..2776109b Binary files /dev/null and "b/UMCar/\350\207\252\345\212\250\351\251\276\351\251\266\347\240\224\347\251\266\346\212\245\345\221\212.pdf" differ diff --git a/darknect/PyTorch/readme.md b/darknect/PyTorch/readme.md new file mode 100644 index 00000000..4b6e2398 --- /dev/null +++ b/darknect/PyTorch/readme.md @@ -0,0 +1,259 @@ +# PyTorch +[参考](https://blog.csdn.net/zzulp/article/details/80573331) + +[PyTorch_Tutorials PyTorch 实战教程 待整合](https://github.com/Ewenwan/PyTorch_Tutorials) + +[PyTorch_Tutorials 2 ](https://github.com/Ewenwan/PyTorch-Tutorial-1) + +[pytorch-tutorial 2 ](https://github.com/Ewenwan/pytorch-tutorial) + +[PyTorch 中文手册 (pytorch handbook)](https://github.com/Ewenwan/pytorch-handbook) + +很多人都会拿PyTorch和Google的Tensorflow进行比较,这个肯定是没有问题的,因为他们是最火的两个深度学习框架了。 + +但是说到PyTorch,其实应该先说Torch。 + + + Pytorch是torch的python版本, + 是由Facebook开源的神经网络框架。 + 与Tensorflow的静态计算图不同, + pytorch的计算图是动态的, + 可以根据计算需要实时改变计算图。 + + Torch英译中:火炬 + Torch是一个与Numpy类似的张量(Tensor)操作库, + 与Numpy不同的是Torch对GPU支持的很好,Lua是Torch的上层包装。 + + PyTorch是一个基于Torch的Python开源机器学习库,用于自然语言处理等应用程序。 + 它主要由Facebook的人工智能研究小组开发。Uber的"Pyro"也是使用的这个库。 + + 安装: + + pip install torch torchvision # for python2.7 + pip3 install torch torchvision # for python3 + + PyTorch是一个Python包,提供两个高级功能: + 1. 具有强大的GPU加速的张量计算(如NumPy) + 2. 包含自动求导系统的的深度神经网络 + + +## 特点 + + 1. Numpy风格的Tensor操作。pytorch中tensor提供的API参考了Numpy的设计, + 因此熟悉Numpy的用户基本上可以无缝理解,并创建和操作tensor, + 同时torch中的数组和Numpy数组对象可以无缝的对接。 + 2. 变量自动求导。在一序列计算过程形成的计算图中, + 参与的变量可以方便的计算自己对目标函数的梯度。 + 这样就可以方便的实现神经网络的后向传播过程。 + 3. 神经网络层与损失函数优化等高层封装。 + 网络层的封装存在于torch.nn模块, + 损失函数由torch.nn.functional模块提供, + 优化函数由torch.optim模块提供。 + +## Tensor类型 + Torch 定义了七种 CPU tensor 类型和八种 GPU tensor 类型: + + Data type CPU tensor GPU tensor + 32-bit floating point torch.FloatTensor torch.cuda.FloatTensor + 64-bit floating point torch.DoubleTensor torch.cuda.DoubleTensor + 16-bit floating point torch.HalfTensor torch.cuda.HalfTensor + 8-bit integer (unsigned) torch.ByteTensor torch.cuda.ByteTensor + 8-bit integer (signed) torch.CharTensor torch.cuda.CharTensor + 16-bit integer (signed) torch.ShortTensor torch.cuda.ShortTensor + 32-bit integer (signed) torch.IntTensor torch.cuda.IntTensor + 64-bit integer (signed) torch.LongTensor torch.cuda.LongTensor + ### 创建接口 + 方法名 说明 + Tensor() 直接从参数构造一个的张量,参数支持list,numpy数组 + eye(row, column) 创建指定行数,列数的二维单位tensor + linspace(start,end,count) 在区间[s,e]上创建c个tensor + logspace(s,e,c) 在区间[10^s, 10^e]上创建c个tensor + ones(*size) 返回指定shape的张量,元素初始为1 + zeros(*size) 返回指定shape的张量,元素初始为0 + ones_like(t) 返回与t的shape相同的张量,且元素初始为1 + zeros_like(t) 返回与t的shape相同的张量,且元素初始为0 + arange(s,e,sep) 在区间[s,e)上以间隔sep生成一个序列张量 +```python +# 创建一个 a 5x3 矩阵, 但是未初始化: +x = torch.empty(5, 3) # 全0 + +# 创建一个随机初始化的矩阵: +x = torch.rand(5, 3) # 0~1直接 + +# 创建一个0填充的矩阵,数据类型为long: +x = torch.zeros(5, 3, dtype=torch.long) + +# 创建tensor并使用现有数据初始化: +x = torch.tensor([5.5, 3]) +# tensor([5.5000, 3.0000]) + +# 根据现有的张量创建张量。 这些方法将重用输入张量的属性,例如, dtype,除非设置新的值进行覆盖 +x = x.new_ones(5, 3, dtype=torch.double) # new_* 方法来创建对象 全1 + +x = torch.randn_like(x, dtype=torch.float) # 覆盖 dtype! 0~1数据 + # 对象的size 是相同的,只是值和类型发生了变化 + +``` +### 随机采样 + 方法名 说明 + rand(*size) 在区间[0,1)返回一个均匀分布的随机数张量 + uniform(s,e) 在指定区间[s,e]上生成一个均匀分布的张量 + randn(*size) 返回正态分布N(0,1)取样的随机数张量 + normal(means, std 返回一个正态分布N(means, std) + + +### 数学操作 + 这些方法均为逐元素处理方法 + + 方法名 说明 + abs 绝对值 + add 加法 + addcdiv(t, v, t1, t2) t1与t2的按元素除后,乘v加t + addcmul(t, v, t1, t2) t1与t2的按元素乘后,乘v加t + ceil 向上取整,天花板 + floor 向下取整,地面 + clamp(t, min, max) 将张量元素限制在指定区间 + exp 指数 + log 对数 + pow 幂 + mul 逐元素乘法 + neg 取反 + sigmoid 指数归一化 exp(-xi)/sum(exp(-xi)) + sign 取符号 + sqrt 开根号 + tanh + +```python +y=torch.rand(5, 3) +print(x + y) +print(torch.add(x, y)) +# 提供输出tensor作为参数 +result = torch.empty(5, 3) +torch.add(x, y, out=result) + +# 使用方法 +y.add_(x) +# 任何 以``_`` 结尾的操作都会用结果替换原变量. 例如: ``x.copy_(y)``, ``x.t_()``, 都会改变 ``x``. + +# 第2列 +x[:, 1] + +# NumPy 转换, 使用from_numpy自动转化 +import numpy as np +a = np.ones(5) +b = torch.from_numpy(a) +np.add(a, 1, out=a) + +``` + +CUDA 张量,使用.to 方法 可以将Tensor被移动到任何设备中 +```python +# is_available 函数判断是否有cuda可以使用 +# ``torch.device``将张量移动到指定的设备中 +if torch.cuda.is_available(): + device = torch.device("cuda") # a CUDA 设备对象 + y = torch.ones_like(x, device=device) # 直接从GPU创建张量 + x = x.to(device) # 或者直接使用``.to("cuda")``将张量移动到cuda中 + z = x + y + print(z) + print(z.to("cpu", torch.double)) # ``.to`` 也会对变量的类型做更改 + +``` + +### 归约方法 + 方法名 说明 + cumprod(t, axis) 在指定维度对t进行累积 + cumsum 在指定维度对t进行累加 + dist(a,b,p=2) 返回a,b之间的p阶范数 + mean 均值 + median 中位数 + std 标准差 + var 方差 + norm(t,p=2) 返回t的p阶范数 + prod(t) 返回t所有元素的积 + sum(t) 返回t所有元素的和 + +### 比较方法 + 方法名 说明 + eq 比较tensor是否相等,支持broadcast + equal 比较tensor是否有相同的shape与值 + ge/le 大于/小于比较 + gt/lt 大于等于/小于等于比较 + max/min(t,axis) 返回最值,若指定axis,则额外返回下标 + topk(t,k,axis) 在指定的axis维上取最高的K个值 + +### 他操作 + 方法名 说明 + cat(iterable, axis) 在指定的维度上拼接序列 + chunk(tensor, c, axis) 在指定的维度上分割tensor + squeeze(input,dim) 将张量维度为1的dim进行压缩,不指定dim则压缩所有维度为1的维 + unsqueeze(dim) squeeze操作的逆操作 + transpose(t) 计算矩阵的转置换 + cross(a, b, axis) 在指定维度上计算向量积 + diag 返回对角线元素 + hist(t, bins) 计算直方图 + trace 返回迹 + +### 矩阵操作 + 方法名 说明 + dot(t1, t2) 计算张量的内积 + mm(t1, t2) 计算矩阵乘法 + mv(t1, v1) 计算矩阵与向量乘法 + qr(t) 计算t的QR分解 + svd(t) 计算t的SVD分解 + +### tensor对象的方法 + 方法名 作用 + size() 返回张量的shape属性值 + numel(input) 计算tensor的元素个数 + view(*shape) 修改tensor的shape,与np.reshape类似,view返回的对象共享内存 + resize 类似于view,但在size超出时会重新分配内存空间 + item 若为单元素tensor,则返回pyton的scalar + from_numpy 从numpy数据填充 + numpy 返回ndarray类型 + +### 使用pytorch进行线性回归 +```python +import torch +import torch.optim as optim +import matplotlib.pyplot as plt + +def get_fake_data(batch_size=32): + ''' y=x*2+3 ''' + x = torch.randn(batch_size, 1) * 20 + y = x * 2 + 3 + torch.randn(batch_size, 1) + return x, y + +x, y = get_fake_data() + +class LinerRegress(torch.nn.Module): + def __init__(self): + super(LinerRegress, self).__init__() + self.fc1 = torch.nn.Linear(1, 1) + + def forward(self, x): + return self.fc1(x) + + +net = LinerRegress() +loss_func = torch.nn.MSELoss() +optimzer = optim.SGD(net.parameters()) + +for i in range(40000): + optimzer.zero_grad() + + out = net(x) + loss = loss_func(out, y) + loss.backward() + + optimzer.step() + +w, b = [param.item() for param in net.parameters()] +print w, b # 2.01146, 3.184525 + +# 显示原始点与拟合直线 +plt.scatter(x.squeeze().numpy(), y.squeeze().numpy()) +plt.plot(x.squeeze().numpy(), (x*w + b).squeeze().numpy()) +plt.show() +``` + diff --git a/darknect/caffe/Caffe-Python-Tutorial/readme.md b/darknect/caffe/Caffe-Python-Tutorial/readme.md new file mode 100644 index 00000000..0c44c854 --- /dev/null +++ b/darknect/caffe/Caffe-Python-Tutorial/readme.md @@ -0,0 +1,1173 @@ +# Caffe-Python接口 数据集生成 训练 分类 检测 剪枝 量化 等 +[参考](https://github.com/Ewenwan/Caffe-Python-Tutorial) + +## 数据集生成 +generate_lmdb.py +```py +# -*- coding:utf-8 -*- +# 将图像数据生成lmdb数据集 +# 1. 生成分类图像数据集 +# 2. 生成目标检测图像数据集 +import os +import sys +import numpy as np +import random +from caffe.proto import caffe_pb2 +from xml.dom.minidom import parse + +# 生成分类标签文件 +def labelmap(labelmap_file, label_info): + labelmap = caffe_pb2.LabelMap() + for i in range(len(label_info)): + labelmapitem = caffe_pb2.LabelMapItem() + labelmapitem.name = label_info[i]['name'] + labelmapitem.label = label_info[i]['label'] + labelmapitem.display_name = label_info[i]['display_name'] + labelmap.item.add().MergeFrom(labelmapitem) + with open(labelmap_file, 'w') as f: + f.write(str(labelmap)) + +def rename_img(Img_dir): + # 重新命名Img,这里假设图像名称表示为000011.jpg、003456.jpg、000000.jpg格式,最高6位,前补0 + # 列出图像,并将图像改为序号名称 + listfile=os.listdir(Img_dir) # 提取图像名称列表 + total_num = 0 + for line in listfile: #把目录下的文件都赋值给line这个参数 + if line[-4:] == '.jpg': + newname = '{:0>6}'.format(total_num) +'.jpg' + os.rename(os.path.join(Img_dir, line), os.path.join(Img_dir, newname)) + total_num+=1 #统计所有图像 + +def get_img_size(): + pass + +def create_annoset(anno_args): + if anno_args.anno_type == "detection": + cmd = "E:\Code\windows-ssd/Build/x64/Release/convert_annoset.exe" \ + " --anno_type={}" \ + " --label_type={}" \ + " --label_map_file={}" \ + " --check_label={}" \ + " --min_dim={}" \ + " --max_dim={}" \ + " --resize_height={}" \ + " --resize_width={}" \ + " --backend={}" \ + " --shuffle={}" \ + " --check_size={}" \ + " --encode_type={}" \ + " --encoded={}" \ + " --gray={}" \ + " {} {} {}" \ + .format(anno_args.anno_type, anno_args.label_type, anno_args.label_map_file, anno_args.check_label, + anno_args.min_dim, anno_args.max_dim, anno_args.resize_height, anno_args.resize_width, anno_args.backend, anno_args.shuffle, + anno_args.check_size, anno_args.encode_type, anno_args.encoded, anno_args.gray, anno_args.root_dir, anno_args.list_file, anno_args.out_dir) + elif anno_args.anno_type == "classification": + cmd = "E:\Code\windows-ssd/Build/x64/Release/convert_annoset.exe" \ + " --anno_type={}" \ + " --min_dim={}" \ + " --max_dim={}" \ + " --resize_height={}" \ + " --resize_width={}" \ + " --backend={}" \ + " --shuffle={}" \ + " --check_size={}" \ + " --encode_type={}" \ + " --encoded={}" \ + " --gray={}" \ + " {} {} {}" \ + .format(anno_args.anno_type, anno_args.min_dim, anno_args.max_dim, anno_args.resize_height, + anno_args.resize_width, anno_args.backend, anno_args.shuffle, anno_args.check_size, anno_args.encode_type, anno_args.encoded, + anno_args.gray, anno_args.root_dir, anno_args.list_file, anno_args.out_dir) + print cmd + os.system(cmd) + +def detection_list(Img_dir, Ano_dir, Data_dir, test_num): + # 造成目标检测图像数据库 + # Img_dir表示图像文件夹 + # Ano_dir表示图像标记文件夹,用labelImg生成 + # Data_dir生成的数据库文件地址 + # test_num测试图像的数目 + # 列出图像 + listfile=os.listdir(Img_dir) # 提取图像名称列表 + + # 列出图像,并将图像改为序号名称 + total_num = 0 + for line in listfile: #把目录下的文件都赋值给line这个参数 + if line[-4:] == '.jpg': + total_num+=1 #统计所有图像 + + trainval_num = total_num-test_num # 训练图像数目 + + # 生成训练图像及测试图像列表 + test_list_file=open(Data_dir+'/test.txt','w') + train_list_file=open(Data_dir+'/trainval.txt','w') + + test_list = np.random.randint(0,total_num-1, size=test_num) + + train_list = range(total_num) + for n in range(test_num): + train_list.remove(test_list[n]) + random.shuffle(train_list) + + # 测试图像排序,而训练图像不用排序 + test_list = np.sort(test_list) + # train_list = np.sort(train_list) + + for n in range(trainval_num): + train_list_file.write(Img_dir + '{:0>6}'.format(train_list[n]) +'.jpg '+ Ano_dir + '{:0>6}'.format(train_list[n]) +'.xml\n') + + for n in range(test_num): + test_list_file.write(Img_dir + '{:0>6}'.format(test_list[n]) +'.jpg '+ Ano_dir + '{:0>6}'.format(test_list[n]) +'.xml\n') + + +caffe_root = 'E:/Code/Github/windows_caffe/' +data_root = caffe_root + 'data/mnist/' +Img_dir = data_root + 'JPEGImages/' +Ano_dir = data_root + 'Annotations/' +anno_type = "detection" +test_num = 100 + +# 第一步,预处理图像,重命名图像名,生成各图像标记信息 +# rename_img(Img_dir) +# 然后通过labelImg(可以通过pip install labelImg安装,出现错误可以删除PyQt4的描述)来生成图像的标记 + +# 第二步,生成分类标签文件 +# 编辑label信息 +label_info = [ + dict(name='none', label=0, display_name='background'), # 背景 + dict(name="cat",label=1, display_name='cat'), # 背景 + dict(name="dog",label=2, display_name='dog'), # 背景 +] +labelmap(data_root+'labelmap_voc.prototxt', label_info) + +# 第三步,生成图像及标记的列表文件 +if anno_type == "detection": + detection_list(Img_dir, Ano_dir, data_root, test_num) +else: + # 分类,生成 + pass + +# 第四步,生成lmdb文件 +# 初始化信息 +anno_args = {} +anno_args['anno_type'] = anno_type +# 仅用于目标检测,lable文件的类型:{xml, json, txt} +anno_args['label_type'] = "xml" +# 仅用于目标检测,label文件地址 +anno_args['label_map_file'] = data_root+"labelmap_voc.prototxt" +# 是否检测所有数据有相同的大小.默认False +anno_args['check_size'] = False +# 检测label是否相同的名称,默认False +anno_args['check_label'] = False +# 为0表示图像不用重新调整尺寸 +anno_args['min_dim'] = 0 +anno_args['max_dim'] = 0 +anno_args['resize_height'] = 0 +anno_args['resize_width'] = 0 +anno_args['backend'] = "lmdb" # 数据集格式(lmdb, leveldb) +anno_args['shuffle'] = False # 是否随机打乱图像及对应标签 +anno_args['encode_type'] = "" # 图像编码格式('png','jpg',...) +anno_args['encoded'] = False # 是否编码,默认False +anno_args['gray'] = False # 是否视为灰度图,默认False +anno_args['root_dir'] = data_root # 存放图像文件夹及标签文件夹的根目录 +anno_args['list_file'] = data_root + '' # listfile文件地址 +anno_args['out_dir'] = data_root # 最终lmdb的存在地址 + +# 生成训练数据集train_lmdb +anno_args['list_file'] = data_root + 'trainval.txt' +create_annoset(anno_args) + +# 生成测试数据集train_lmdb +anno_args['list_file'] = data_root + 'test.txt' +create_annoset(anno_args) + +``` +## 训练 +train_val.py +```py +# -*- coding:utf-8 -*- +# 训练及测试文件 +# 训练网络 +import caffe +import numpy as np +import matplotlib.pyplot as plt +import math + +def crop_network(prune_proto, caffemodel, prune_caffemodel): + # 截取已知网络的部分层 + # caffemodel网络权重值并不要求其结构与proto相对应 + # 网络只会取train_proto中定义的结构中权重作为网络的初始权重值 + # 因此,当我们需要截取某些已训练网络的特定层作为新网络的某些层的权重初始值,只需要在其train_proto定义同名的层 + # 之后caffe将在caffemodel中找到与train_proto定义的同名结构,并将其权重作为应用权重初始值。 + # prune_deploy: 选择保留的网络结构层:prototxt + # caffemodel: 已知网络的权重连接 + # prune_caffemodel:截断网络的权重连接文件 + net = caffe.Net(prune_proto, caffemodel, caffe.TEST) + net.save(prune_caffemodel) + +def train(solver_proto, caffemodel='', is_step=True, savefig=''): + # 训练模型函数 + # solver_proto: 训练配置文件 + # caffemodel:预设权重值或者快照等,并不要求其结构与网络结构相对应,但只会取与训练网络结构相对应的权重值 + # is_step: True表示按步训练,False表示直接完成训练 + # savefig: 表示要保存的图像训练时损失变化图 + # 设置训练器:随机梯度下降算法 + solver = caffe.SGDSolver(solver_proto) + if caffemodel!='': + solver.net.copy_from(caffemodel) + + if is_step==False: + # 直接完成训练 + solver.solve() + else: + # 迭代次数 + max_iter = 10000 + # 每隔100次收集一次数据 + display = 100 + + # 每次测试进行100次解算,10000/100 + test_iter = 100 + # 每500次训练进行一次测试(100次解算),60000/64 + test_interval = 500 + + # 初始化 + train_loss = np.zeros(int(math.ceil(max_iter * 1.0 / display))) + test_loss = np.zeros(int(math.ceil(max_iter * 1.0 / test_interval))) + test_acc = np.zeros(int(math.ceil(max_iter * 1.0 / test_interval))) + + # iteration 0,不计入 + solver.step(1) + + # 辅助变量 + _train_loss = 0 + _test_loss = 0 + _accuracy = 0 + + # 分步训练 + for it in range(max_iter): + # 进行一次解算 + solver.step(1) + # 每迭代一次,训练batch_size张图片 + _train_loss += solver.net.blobs['loss'].data # 最后一层的损失值 + if it % display == 0: + # 计算平均train loss + train_loss[int(it / display)] = _train_loss / display + _train_loss = 0 + + # 测试 + if it % test_interval == 0: + for test_it in range(test_iter): + # 进行一次测试 + solver.test_nets[0].forward() + # 计算test loss + _test_loss += solver.test_nets[0].blobs['loss'].data + # 计算test accuracy + _accuracy += solver.test_nets[0].blobs['accuracy'].data + # 计算平均test loss + test_loss[it / test_interval] = _test_loss / test_iter + # 计算平均test accuracy + test_acc[it / test_interval] = _accuracy / test_iter + _test_loss = 0 + _accuracy = 0 + + # 绘制train loss、test loss和accuracy曲线 + print '\nplot the train loss and test accuracy\n' + _, ax1 = plt.subplots() + ax2 = ax1.twinx() + + # train loss -> 绿色 + ax1.plot(display * np.arange(len(train_loss)), train_loss, 'g') + # test loss -> 黄色 + ax1.plot(test_interval * np.arange(len(test_loss)), test_loss, 'y') + # test accuracy -> 红色 + ax2.plot(test_interval * np.arange(len(test_acc)), test_acc, 'r') + + ax1.set_xlabel('iteration') + ax1.set_ylabel('loss') + ax2.set_ylabel('accuracy') + + if savefig!='': + plt.savefig(savefig) + plt.show() + +#CPU或GPU模型转换 +#caffe.set_mode_cpu() +caffe.set_device(0) +caffe.set_mode_gpu() + +caffe_root = '../../' +# caffe_root = 'E:/Code/Github/windows_caffe/' +model_root = caffe_root + 'models/mnist/' +solver_proto = model_root + 'solver.prototxt' + +``` + +solver.py +```py +# -*- coding:utf-8 -*- +# 生成solver文件 +from caffe.proto import caffe_pb2 + +def solver_file(model_root, model_name): + s = caffe_pb2.SolverParameter() # 声明solver结构 + s.train_net = model_root+'train.prototxt' # 训练网络结构配置文件 + s.test_net.append(model_root+'test.prototxt') # 测试时网络结构配置文件,测试网络可有多个 + # 每训练迭代test_interval次进行一次测试。 + s.test_interval = 500 + # 每次测试时的批量数,测试里网络可有多个 + s.test_iter.append(100) + # 最大训练迭代次数 + s.max_iter = 10000 + # 基础学习率 + s.base_lr = 0.01 + # 动量,记忆因子 + s.momentum = 0.9 + # 权重衰减值,遗忘因子 + s.weight_decay = 5e-4 + # 学习率变化策略。可选参数:fixed、step、exp、inv、multistep + # fixed: 保持base_lr不变; + # step: 学习率变化规律base_lr * gamma ^ (floor(iter / stepsize)),其中iter表示当前的迭代次数; + # exp: 学习率变化规律base_lr * gamma ^ iter; + # inv: 还需要设置一个power,学习率变化规律base_lr * (1 + gamma * iter) ^ (- power); + # multistep: 还需要设置一个stepvalue,这个参数和step相似,step是均匀等间隔变化,而multistep则是根据stepvalue值变化; + # stepvalue参数说明: + # poly: 学习率进行多项式误差,返回base_lr (1 - iter/max_iter) ^ (power); + # sigmoid: 学习率进行sigmod衰减,返回base_lr ( 1/(1 + exp(-gamma * (iter - stepsize))))。 + s.lr_policy = 'inv' + s.gamma = 0.0001 + s.power = 0.75 + + s.display = 100 # 每迭代display次显示结果 + s.snapshot = 5000 # 保存临时模型的迭代数 + s.snapshot_prefix = model_root+model_name+'shapshot' # 模型前缀,就是训练好生成model的名字 + s.type = 'SGD' # 训练方法(各类梯度下降法),可选参数:SGD,AdaDelta,AdaGrad,Adam,Nesterov,RMSProp + s.solver_mode = caffe_pb2.SolverParameter.GPU # 训练及测试模型,GPU或CPU + + solver_file=model_root+'solver.prototxt' # 要保存的solver文件名 + + with open(solver_file, 'w') as f: + f.write(str(s)) + +caffe_root = '../../' +model_name = 'LeNet5_Mnist_' +# caffe_root = 'E:/Code/Github/windows_caffe/' +model_root = caffe_root + 'models/mnist/' +solver_file(model_root, model_name) + +``` + +## 分类 +classification.py +```py +# -*- coding:utf-8 -*- +# 用于模型的单张图像分类操作 +import os +os.environ['GLOG_minloglevel'] = '2' # 将caffe的输出log信息不显示,必须放到import caffe前 +import caffe # caffe 模块 +from caffe.proto import caffe_pb2 +from google.protobuf import text_format +import numpy as np +import cv2 +import matplotlib.pyplot as plt +import time + +# 分类单张图像img +def classification(img, net, transformer, synset_words): + im = caffe.io.load_image(img) + # 导入输入图像 + net.blobs['data'].data[...] = transformer.preprocess('data', im) + + start = time.clock() + # 执行测试 + net.forward() + end = time.clock() + print('classification time: %f s' % (end - start)) + + # 查看目标检测结果 + labels = np.loadtxt(synset_words, str, delimiter='\t') + + category = net.blobs['prob'].data[0].argmax() + + class_str = labels[int(category)].split(',') + class_name = class_str[0] + # text_font = cv2.cv.InitFont(cv2.cv.CV_FONT_HERSHEY_SCRIPT_SIMPLEX, 1, 1, 0, 3, 8) + cv2.putText(im, class_name, (0, im.shape[0]), cv2.cv.CV_FONT_HERSHEY_SIMPLEX, 1, (55, 255, 155), 2) + + # 显示结果 + plt.imshow(im, 'brg') + plt.show() + +#CPU或GPU模型转换 +caffe.set_mode_cpu() +#caffe.set_device(0) +#caffe.set_mode_gpu() + +caffe_root = '../../' +# 网络参数(权重)文件 +caffemodel = caffe_root + 'models/bvlc_alexnet/bvlc_alexnet.caffemodel' +# 网络实施结构配置文件 +deploy = caffe_root + 'models/bvlc_alexnet/deploy.prototxt' + + +img_root = caffe_root + 'data/VOCdevkit/VOC2007/JPEGImages/' +synset_words = caffe_root + 'data/ilsvrc12/synset_words.txt' + +# 网络实施分类 +net = caffe.Net(deploy, # 定义模型结构 + caffemodel, # 包含了模型的训练权值 + caffe.TEST) # 使用测试模式(不执行dropout) + +# 加载ImageNet图像均值 (随着Caffe一起发布的) +mu = np.load(caffe_root + 'python/caffe/imagenet/ilsvrc_2012_mean.npy') +mu = mu.mean(1).mean(1) # 对所有像素值取平均以此获取BGR的均值像素值 + +# 图像预处理 +transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape}) +transformer.set_transpose('data', (2,0,1)) +transformer.set_mean('data', mu) +transformer.set_raw_scale('data', 255) +transformer.set_channel_swap('data', (2,1,0)) + +# 处理图像 +while 1: + img_num = raw_input("Enter Img Number: ") + if img_num == '': break + img = img_root + '{:0>6}'.format(img_num) + '.jpg' + classification(img,net,transformer,synset_words) + +``` +## 检测 +detection.py +```py + # -*- coding:utf-8 -*- +# 用于模型的单张图像分类操作 +import os +os.environ['GLOG_minloglevel'] = '2' # 将caffe的输出log信息不显示,必须放到import caffe前 +import caffe # caffe 模块 +from caffe.proto import caffe_pb2 +from google.protobuf import text_format +import numpy as np +import cv2 +import matplotlib.pyplot as plt +import time + +# 分类单张图像img +def detection(img, net, transformer, labels_file): + im = caffe.io.load_image(img) + net.blobs['data'].data[...] = transformer.preprocess('data', im) + + start = time.clock() + # 执行测试 + net.forward() + end = time.clock() + print('detection time: %f s' % (end - start)) + + # 查看目标检测结果 + file = open(labels_file, 'r') + labelmap = caffe_pb2.LabelMap() + text_format.Merge(str(file.read()), labelmap) + + loc = net.blobs['detection_out'].data[0][0] + confidence_threshold = 0.5 + for l in range(len(loc)): + if loc[l][2] >= confidence_threshold: + xmin = int(loc[l][3] * im.shape[1]) + ymin = int(loc[l][4] * im.shape[0]) + xmax = int(loc[l][5] * im.shape[1]) + ymax = int(loc[l][6] * im.shape[0]) + img = np.zeros((512, 512, 3), np.uint8) # 生成一个空彩色图像 + cv2.rectangle(im, (xmin, ymin), (xmax, ymax), (55 / 255.0, 255 / 255.0, 155 / 255.0), 2) + + # 确定分类类别 + class_name = labelmap.item[int(loc[l][1])].display_name + # text_font = cv2.cv.InitFont(cv2.cv.CV_FONT_HERSHEY_SCRIPT_SIMPLEX, 1, 1, 0, 3, 8) + cv2.putText(im, class_name, (xmin, ymax), cv2.cv.CV_FONT_HERSHEY_SIMPLEX, 1, (55, 255, 155), 2) + + # 显示结果 + plt.imshow(im, 'brg') + plt.show() + +#CPU或GPU模型转换 +caffe.set_mode_cpu() +#caffe.set_device(0) +#caffe.set_mode_gpu() + +caffe_root = '../../' +# 网络参数(权重)文件 +caffemodel = caffe_root + 'models/SSD_300x300/VGG_VOC0712_SSD_300x300_iter_60000.caffemodel' +# 网络实施结构配置文件 +deploy = caffe_root + 'models/SSD_300x300/deploy.prototxt' + + +img_root = caffe_root + 'data/VOCdevkit/VOC2007/JPEGImages/' +labels_file = caffe_root + 'data/VOC0712/labelmap_voc.prototxt' + +# 网络实施分类 +net = caffe.Net(deploy, # 定义模型结构 + caffemodel, # 包含了模型的训练权值 + caffe.TEST) # 使用测试模式(不执行dropout) + +# 加载ImageNet图像均值 (随着Caffe一起发布的) +mu = np.load(caffe_root + 'python/caffe/imagenet/ilsvrc_2012_mean.npy') +mu = mu.mean(1).mean(1) # 对所有像素值取平均以此获取BGR的均值像素值 + +# 图像预处理 +transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape}) +transformer.set_transpose('data', (2,0,1)) +transformer.set_mean('data', mu) +transformer.set_raw_scale('data', 255) +transformer.set_channel_swap('data', (2,1,0)) + +# 处理图像 +while 1: + img_num = raw_input("Enter Img Number: ") + if img_num == '': break + img = img_root + '{:0>6}'.format(img_num) + '.jpg' + detection(img,net,transformer,labels_file) + +``` +## 剪枝 +prune.py +```py + # -*- coding:utf-8 -*- +# 用于修剪网络模型 +import numpy as np +import matplotlib.pyplot as plt +import os +os.environ['GLOG_minloglevel'] = '2' +import caffe + +# 由稠密变成CSC稀疏矩阵 +def dense_to_sparse_csc(W_flatten, num_level): + # W_flatten: 扁平化的权重矩阵 + # num_level: 量化级别 + csc_W = [] # 存储稀疏矩阵 + csc_indx = [] + indx = 0 + for n in range(len(W_flatten)): + if W_flatten[n]!=0 or indx == 2**num_level: + csc_W.append(W_flatten[n]) + csc_indx.append(indx) + indx = 0 + else: + indx += 1 + if indx!=0: + csc_W.append(0.0) + csc_indx.append(indx-1) + return np.array(csc_W, dtype=np.float32),np.array(csc_indx, dtype=np.int8) + +# 由稠密变成CSC稀疏矩阵 +def sparse_to_dense_csc(csc_W, csc_W_indx): + # W_flatten: 扁平化的权重矩阵 + # num_level: 量化级别 + W_flatten = [] # 存储稠密矩阵 + indx = 0 + for n in range(len(csc_W)): + if csc_W_indx[n]!=0: + W_flatten.extend([0]*(csc_W_indx[n])) + W_flatten.append(csc_W[n]) + return np.array(W_flatten, dtype=np.float32) + + +def read_sparse_net(filename, net, layers): + pass + +def write_sparse_net(filename, net): + pass + +# 画出各层参数的直方图 +def draw_hist_weight(net, layers): + plt.figure() # 画图 + layer_num = len(layers) + for i, layer in enumerate(layers): + i += 1 + W = net.params[layer][0].data + + plt.subplot(layer_num/2, 2, i) + numBins = 2 ^ 5 + plt.hist(W.flatten(), numBins, color='blue', alpha=0.8) + plt.title(layer) + plt.show() + +# 网络模型的参数 +def analyze_param(net, layers): + + print '\n=============analyze_param start===============' + total_nonzero = 0 + total_allparam = 0 + percentage_list = [] + for i, layer in enumerate(layers): + i += 1 + W = net.params[layer][0].data + b = net.params[layer][1].data + + print 'W(%s) range = [%f, %f]' % (layer, min(W.flatten()), max(W.flatten())) + print 'W(%s) mean = %f, std = %f' % (layer, np.mean(W.flatten()), np.std(W.flatten())) + non_zero = (np.count_nonzero(W.flatten()) + np.count_nonzero(b.flatten())) # 参数非零值 + all_param = (np.prod(W.shape) + np.prod(b.shape)) # 所有参数的数目 + this_layer_percentage = non_zero / float(all_param) # 参数比例 + total_nonzero += non_zero + total_allparam += all_param + print 'non-zero W and b cnt = %d' % non_zero + print 'total W and b cnt = %d' % all_param + print 'percentage = %f\n' % (this_layer_percentage) + percentage_list.append(this_layer_percentage) + + print '=====> summary:' + print 'non-zero W and b cnt = %d' % total_nonzero + print 'total W and b cnt = %d' % total_allparam + print 'percentage = %f' % (total_nonzero / float(total_allparam)) + print '=============analyze_param ends ===============' + return (total_nonzero / float(total_allparam), percentage_list) + +def prune(threshold, test_net, layers): + sqarse_net = {} + + for i, layer in enumerate(layers): + + print '\n============ Pruning %s : threshold=%0.2f ============' % (layer,threshold[i]) + W = test_net.params[layer][0].data + b = test_net.params[layer][1].data + hi = np.max(np.abs(W.flatten())) + hi = np.sort(-np.abs(W.flatten()))[int((len(W.flatten())-1)* threshold[i])] + + # abs(val) = 0 ==> 0 + # abs(val) >= threshold ==> 1 + interpolated = np.interp(np.abs(W), [0, hi * threshold[i], 999999999.0], [0.0, 1.0, 1.0]) + + # 小于阈值的权重被随机修剪 + random_samps = np.random.rand(len(W.flatten())) + random_samps.shape = W.shape + + # 修剪阈值 + # mask = (random_samps < interpolated) + mask = (np.abs(W) > (np.abs(hi))) + mask = np.bool_(mask) + W = W * mask + + print 'non-zero W percentage = %0.5f ' % (np.count_nonzero(W.flatten()) / float(np.prod(W.shape))) + # 保存修剪后的阈值 + test_net.params[layer][0].data[...] = W + # net.params[layer][0].mask[...] = mask + csc_W, csc_W_indx = dense_to_sparse_csc(W.flatten(), 8) + dense_W = sparse_to_dense_csc(csc_W, csc_W_indx) + sqarse_net[layer + '_W'] = csc_W + sqarse_net[layer + '_W_indx'] = csc_W_indx + + # 计算修剪后的权重稀疏度 + # np.savez(model_dir + model_name +"_crc.npz",sqarse_net) # 保存存储成CRC格式的稀疏网络 + (total_percentage, percentage_list) = analyze_param(test_net, layers) + test_loss, accuracy = test_net_accuracy(test_net) + return (threshold, total_percentage, percentage_list, test_loss, accuracy) + +def test_net_accuracy(test_net): + test_iter = 100 + test_loss = 0 + accuracy = 0 + for test_it in range(test_iter): + # 进行一次测试 + test_net.forward() + # 计算test loss + test_loss += test_net.blobs['loss'].data + # 计算test accuracy + accuracy += test_net.blobs['accuracy'].data + + return (test_loss / test_iter), (accuracy / test_iter) + + +def eval_prune_threshold(threshold_list, test_prototxt, caffemodel, prune_layers): + def net_prune(threshold, test_prototx, caffemodel, prune_layers): + test_net = caffe.Net(test_prototx, caffemodel, caffe.TEST) + return prune(threshold, test_net, prune_layers) + + accuracy = [] + for threshold in threshold_list: + results = net_prune(threshold, test_prototxt, caffemodel, prune_layers) + print 'threshold: ', results[0] + print '\ntotal_percentage: ', results[1] + print '\npercentage_list: ', results[2] + print '\ntest_loss: ', results[3] + print '\naccuracy: ', results[4] + accuracy.append(results[4]) + plt.plot(accuracy,'r.') + plt.show() + +# 迭代训练修剪后网络 +def retrain_pruned(solver, pruned_caffemodel, threshold, prune_layers): + #solver = caffe.SGDSolver(solver_proto) + retrain_iter = 20 + + accuracys = [] + for i in range(retrain_iter): + solver.net.copy_from(pruned_caffemodel) + # solver.solve() + solver.step(500) + _,_,_,_,accuracy=prune(threshold, solver.test_nets[0], prune_layers) + solver.test_nets[0].save(pruned_caffemodel) + accuracys.append(accuracy) + + plt.plot(accuracys, 'r.-') + plt.show() + + +#CPU或GPU模型转换 +#caffe.set_mode_cpu() +caffe.set_device(0) +caffe.set_mode_gpu() + +caffe_root = '../../' +#model_dir = caffe_root + 'models/SSD_300x300/' +#deploy = model_dir + 'deploy.prototxt' +#model_name = 'VGG_VOC0712_SSD_300x300_iter_60000' +#caffemodel = model_dir + model_name + '.caffemodel' + +model_dir = caffe_root + 'models/mnist/' +deploy = model_dir + 'deploy.prototxt' +model_name = 'LeNet5_Mnist_shapshot_iter_10000' +caffemodel = model_dir + model_name + '.caffemodel' +test_prototxt = model_dir + 'test.prototxt' +solver_proto = model_dir + 'solver.prototxt' + +solver = caffe.SGDSolver(solver_proto) + +# 要修剪的层 +prune_layers = ['conv1','conv2','ip1','ip2'] +# 测试修剪率 +test_threshold_list = [[0.3, 1 ,1 ,1], [0.4, 1 ,1 ,1], [0.5, 1 ,1 ,1], [0.6, 1 ,1 ,1], [0.7, 1 ,1 ,1], + [1, 0.05, 1, 1], [1, 0.1, 1, 1], [1, 0.15, 1, 1], [1, 0.2, 1, 1], [1, 0.3, 1, 1], + [1, 1, 0.05, 1], [1, 1, 0.1, 1], [1, 1, 0.15, 1], [1, 1, 0.2, 1], [1, 1, 0.3, 1], + [1, 1, 1, 0.05], [1, 1, 1, 0.1], [1, 1, 1, 0.15], [1, 1, 1, 0.2], [1, 1, 1, 0.3]] + +# 验证修剪率 +#eval_prune_threshold(test_threshold_list, test_prototxt, caffemodel, prune_layers) + +threshold = [0.3, 0.1, 0.01, 0.2] +prune(threshold, solver.test_nets[0], prune_layers) +pruned_model = model_dir + model_name +'_pruned' + '.caffemodel' +solver.test_nets[0].save(pruned_model) + +retrain_pruned(solver, pruned_model, threshold, prune_layers) + + + +""" +# 各层对应的修剪率 +threshold = [0.3, 0.1, 0.01, 0.2] +net = caffe.Net(deploy, caffemodel, caffe.TEST) +# 修剪 +prune(threshold, net, prune_layers, test_prototxt) +# 保存修剪后的稀疏网络模型 +output_model = model_name +'_pruned' + '.caffemodel' +net.save(output_model) +""" + +``` +## 量化 等 +quantize.py +```py +# -*- coding:utf-8 -*- +""" +聚类量化仅仅减少内存消耗,并不能减少计算量 +在实际运行中,也必须通过聚类中心表将量化后权重值转换为32位的浮点数, +因此并不能在减少网络的实际运行内存,只是减少网络的内存消耗。 +要真正减少网络内存消耗,从而达到网络实际运行速度的提高,目前有两类主流方法: + 1、网络剪裁 + 2、量化 +网络权重共享量化也是一类重要的网络压缩方法, +其本质在于先通过聚类方法得到该层权重的聚类中心, +然后通过聚类中心值来表示原权重值。 +因此权重值并不是由32位的浮点数来表示,而是由其对应的聚类中心的序号表示, +如果聚类级别为8位,此时权重值只需要用8位就能表示。 +对于网络权重量化也有三个问题: +量化级别的确定,同修剪率一样,可以通过试错的试验的方法来确定 +量化后网络重新训练问题 +量化中心的初始选择问题:聚类中心采用线性方法初始化,将初始点均匀分散, +这种初始化方法不仅操作简单, +而且能够将对网络影响较大但实际分布较少的较大权重值也包含到初始中心点中, +因此不容易造成较大权重的丢失。 +""" + +# 通过Kmeans聚类的方法来量化权重 +import numpy as np +import matplotlib.pyplot as plt +import scipy.cluster.vq as scv +import pickle +import os +os.environ['GLOG_minloglevel'] = '2' +import caffe +import time + +# 获得各层的量化码表 +# Kmean聚类得到每层的聚类中心 +# 对于Kmean聚类方法,这里调用的是scipy库的聚类函数 +def kmeans_net(net, layers, num_c=16, initials=None): + # net: 网络 + # layers: 需要量化的层 + # num_c: 各层的量化级别 + # initials: 初始聚类中心 + codebook = {} # 量化码表 + if type(num_c) == type(1): + num_c = [num_c] * len(layers) + else: + assert len(num_c) == len(layers) + + # 对各层进行聚类分析 + print "==============Perform K-means=============" + for idx, layer in enumerate(layers): + print "Eval layer:", layer + W = net.params[layer][0].data.flatten() + W = W[np.where(W != 0)] # 筛选不为0的权重 + # 默认情况下,聚类中心为线性分布中心 + if initials is None: # Default: uniform sample + min_W = np.min(W) + max_W = np.max(W) + initial_uni = np.linspace(min_W, max_W, num_c[idx] - 1) + codebook[layer], _ = scv.kmeans(W, initial_uni) + elif type(initials) == type(np.array([])): + codebook[layer], _ = scv.kmeans(W, initials) + elif initials == 'random': + codebook[layer], _ = scv.kmeans(W, num_c[idx] - 1) + else: + raise Exception + + # 将0权重值附上 + codebook[layer] = np.append(0.0, codebook[layer]) + print "codebook size:", len(codebook[layer]) + + return codebook + +# 随机量化权重值 +def stochasitc_quantize2(W, codebook): + # mask插入新维度:(W.shape,1) + mask = W[:, np.newaxis] - codebook + + mask_neg = mask + mask_neg[mask_neg > 0.0] -= 99999.0 + max_neg = np.max(mask_neg, axis=1) + max_code = np.argmax(mask_neg, axis=1) + + mask_pos = mask + mask_pos += 99999.0 + min_code = np.argmin(mask_pos, axis=1) + min_pos = np.min(mask_pos, axis=1) + + rd = np.random.uniform(low=0.0, high=1.0, size=(len(W))) + thresh = min_pos.astype(np.float32) / (min_pos - max_neg) + + max_idx = thresh < rd + min_idx = thresh >= rd + + codes = np.zeros(W.shape) + codes[max_idx] += min_code[max_idx] + codes[min_idx] += max_code[min_idx] + + return codes.astype(np.int) + +# 得到网络的量化权重值 +def quantize_net(net, codebook): + layers = codebook.keys() + codes_W = {} + print "================Perform quantization==============" + for layer in layers: + print "Quantize layer:", layer + W = net.params[layer][0].data + codes, _ = scv.vq(W.flatten(), codebook[layer]) # 根据码表得到量化权重值 + # codes = stochasitc_quantize2(W.flatten(), codebook[layer]) # 采用随机量化的方式 + codes = np.reshape(codes, W.shape) + codes_W[layer] = np.array(codes, dtype=np.uint32) + # 将量化后的权重保存到网络中 + W_q = np.reshape(codebook[layer][codes], W.shape) + np.copyto(net.params[layer][0].data, W_q) + + return codes_W + +# 使用聚类得到的字典进行量化各层 +# 通过各层聚类来进行各层权重的量化 +def quantize_net_with_dict(net, layers, codebook, use_stochastic=False, timing=False): + start_time = time.time() + codeDict = {} # 记录各个量化中心所处的位置 + maskCode = {} # 各层量化结果 + for layer in layers: + print "Quantize layer:", layer + W = net.params[layer][0].data + if use_stochastic: + codes = stochasitc_quantize2(W.flatten(), codebook[layer]) + else: + codes, _ = scv.vq(W.flatten(), codebook[layer]) + W_q = np.reshape(codebook[layer][codes], W.shape) + net.params[layer][0].data[...] = W_q + + maskCode[layer] = np.reshape(codes, W.shape) + codeBookSize = len(codebook[layer]) + a = maskCode[layer].flatten() + b = xrange(len(a)) + + codeDict[layer] = {} + for i in xrange(len(a)): + codeDict[layer].setdefault(a[i], []).append(b[i]) + + if timing: + print "Update codebook time:%f" % (time.time() - start_time) + + return codeDict, maskCode + +def static_vars(**kwargs): + def decorate(func): + for k in kwargs: + setattr(func, k, kwargs[k]) + return func + return decorate + +# 重新训练及聚类中心的更新 +# 重新训练时,其精度的变化图,可以看到随着迭代次数增加,其精度也逐渐提升 +@static_vars(step_cache={}, step_cache2={}, count=0) +def update_codebook_net(net, codebook, codeDict, maskCode, args, update_layers=None, snapshot=None): + + start_time = time.time() + extra_lr = args['lr'] # 基础学习速率 + decay_rate = args['decay_rate'] # 衰减速率 + momentum = args['momentum'] # 遗忘因子 + update_method = args['update'] # 更新方法 + smooth_eps = 0 + + normalize_flag = args['normalize_flag'] # 是否进行归一化 + + + if update_method == 'rmsprop': + extra_lr /= 100 + + # 对码表与量化结果的初始化 + if update_codebook_net.count == 0: + step_cache2 = update_codebook_net.step_cache2 + step_cache = update_codebook_net.step_cache + if update_method == 'adadelta': + for layer in update_layers: + step_cache2[layer] = {} + for code in xrange(1, len(codebook[layer])): + step_cache2[layer][code] = 0.0 + smooth_eps = 1e-8 + + for layer in update_layers: + step_cache[layer] = {} + for code in xrange(1, len(codebook[layer])): + step_cache[layer][code] = 0.0 + + update_codebook_net.count = 1 + + else: + # 读入上次运算的结果 + step_cache2 = update_codebook_net.step_cache2 + step_cache = update_codebook_net.step_cache + update_codebook_net.count += 1 + + # 所有层名 + total_layers = net.params.keys() + if update_layers is None: # 所有层都需要进行更新 + update_layers = total_layers + + # 权重码表的更新 + for layer in total_layers: + if layer in update_layers: + diff = net.params[layer][0].diff.flatten() # 误差梯度 + codeBookSize = len(codebook[layer]) + dx = np.zeros((codeBookSize)) # 编码表的误差更新 + for code in xrange(1, codeBookSize): + indexes = codeDict[layer][code] # codeDict保存属于某编码的权重的序号 + #diff_ave = np.sum(diff[indexes]) / len(indexes) + diff_ave = np.sum(diff[indexes]) # 统计该编码所有的误差更新和 + + # 针对于不同方法进行更新 + if update_method == 'sgd': + dx[code] = -extra_lr * diff_ave + elif update_method == 'momentum': + if code in step_cache[layer]: + dx[code] = momentum * step_cache[layer][code] - (1 - momentum) * extra_lr * diff_ave + step_cache[layer][code] = dx + elif update_method == 'rmsprop': + if code in step_cache[layer]: + step_cache[layer][code] = decay_rate * step_cache[layer][code] + (1.0 - decay_rate) * diff_ave ** 2 + dx[code] = -(extra_lr * diff_ave) / np.sqrt(step_cache[layer][code] + 1e-6) + elif update_method == 'adadelta': + if code in step_cache[layer]: + step_cache[layer][code] = step_cache[layer][code] * decay_rate + (1.0 - decay_rate) * diff_ave ** 2 + dx[code] = -np.sqrt((step_cache2[layer][code] + smooth_eps) / (step_cache[layer][code] + smooth_eps)) * diff_ave + step_cache2[layer][code] = step_cache2[layer][code] * decay_rate + (1.0 - decay_rate) * (dx[code] ** 2) + + # 是否需要进行归一化更新参数 + if normalize_flag: + codebook[layer] += extra_lr * np.sqrt(np.mean(codebook[layer] ** 2)) / np.sqrt(np.mean(dx ** 2)) * dx + else: + codebook[layer] += dx + else: + pass + + # maskCode保存编码结果 + W2 = codebook[layer][maskCode[layer]] + net.params[layer][0].data[...] = W2 # 量化后权重值 + + print "Update codebook time:%f" % (time.time() - start_time) + +# 保存量化结果 +def store_all(net, codebook, dir_t, idx=0): + net.save(dir_t + 'caffemodel%d' % idx) + # 量化网络及码表 + pickle.dump(codebook, open(dir_t + 'codebook%d' % idx, 'w')) + +# 恢复权重值 +def recover_all(net, dir_t, idx=0): + layers = net.params.keys() + net.copy_from(dir_t + 'caffemodel%d' % idx) + codebook = pickle.load(open(dir_t + 'codebook%d' % idx)) + maskCode = {} + codeDict = {} + for layer in layers: + W = net.params[layer][0].data + # 码表结果 + codes, _ = scv.vq(W.flatten(), codebook[layer]) + # 编码结果重新排列 + maskCode[layer] = np.reshape(codes, W.shape) + codeBookSize = len(codebook[layer]) + a = maskCode[layer].flatten() + b = xrange(len(a)) + + codeDict[layer] = {} + for i in xrange(len(a)): + # codeDict保存每个码有哪些位置,而maskCode保存每个位置属于哪个码 + codeDict[layer].setdefault(a[i], []).append(b[i]) + + return codebook, maskCode, codeDict + + +def analyze_log(fileName): + data = open(fileName, "r") + y = [] + for line in data: + y.append(float(line.split()[0])) + return y + +# 读入测试数据 +def parse_caffe_log(log): + lines = open(log).readlines() + try: + res = map(lambda x: float(x.split()[-1]), lines[-3:-1]) + except Exception as e: + print e + res = [0.0, 0.0] + return res + +# 检测量化后网络的精度 +def test_quantize_accu(test_net): + test_iter = 100 + test_loss = 0 + accuracy = 0 + for test_it in range(test_iter): + # 进行一次测试 + test_net.forward() + # 计算test loss + test_loss += test_net.blobs['loss'].data + # 计算test accuracy + accuracy += test_net.blobs['accuracy'].data + + return (test_loss / test_iter), (accuracy / test_iter) + + +def save_quantize_net(codebook, maskcode, net_filename, total_layers): + # 编码 + quantizeNet = {} + for layer in total_layers: + quantizeNet[layer+'_codebook'] = np.float32(codebook[layer]) + quantizeNet[layer + '_maskcode'] = np.int8(maskcode[layer]) + + np.savez(net_filename,quantizeNet) + +# 保存修剪量化的网络参数 +def save_pruned_quantize_net(codebook, maskcode, net_filename, total_layers): + # W_flatten: 扁平化的权重矩阵 + # num_level: 量化级别 + quantizeNet = {} + for layer in total_layers: + W_flatten = maskCode[layer].flatten() + indx = 0 + num_level = 8 + csc_W = [] + csc_indx = [] + for n in range(len(W_flatten)): + if W_flatten[n]!=0 or indx == 2**num_level: + csc_W.append(W_flatten[n]) + csc_indx.append(indx) + indx = 0 + else: + indx += 1 + if indx!=0: + csc_W.append(0) + csc_indx.append(indx-1) + print max(csc_indx) + quantizeNet[layer + '_codebook'] = np.float32(codebook[layer]) + quantizeNet[layer + '_maskcode_W'] = np.array(csc_W, dtype=np.int8) + print max(csc_indx) + quantizeNet[layer + '_maskcode_indx'] = np.array(csc_indx, dtype=np.int8) + + np.savez(net_filename, quantizeNet) + +# caffe接口 + +caffe.set_mode_gpu() +caffe.set_device(0) + +caffe_root = '../../' +model_dir = caffe_root + 'models/mnist/' +deploy = model_dir + 'deploy.prototxt' +solver_file = model_dir + 'solver.prototxt' +# model_name = 'LeNet5_Mnist_shapshot_iter_10000' +model_name = 'LeNet5_Mnist_shapshot_iter_10000_pruned' +caffemodel = model_dir + model_name + '.caffemodel' + +dir_t = '/weight_quantize/' + +# 运行测试命令 +args = dict(lr=0.01, decay_rate = 0.0009, momentum = 0.9, update = 'adadelta', normalize_flag = False) + +start_time = time.time() + +solver = caffe.SGDSolver(solver_file) +solver.net.copy_from(caffemodel) +# 需要量化的权重 +total_layers = ['conv1','conv2','ip1','ip2'] + +num_c = 2 ** 8 # 量化级别,由8位整数表示 +codebook = kmeans_net(solver.test_nets[0], total_layers, num_c) + +codeDict, maskCode = quantize_net_with_dict(solver.test_nets[0], total_layers, codebook) +quantize_net_caffemodel = model_dir + model_name + '_quantize.caffemodel' +solver.test_nets[0].save(quantize_net_caffemodel) + +quantize_net_npz = model_dir + model_name + '_quantize_net' +save_pruned_quantize_net(codebook, maskCode, quantize_net_npz , total_layers) + +# 迭代训练编码表 +accuracys = [] +co_iters = 40 +ac_iters = 10 +for i in xrange(2500): + if (i % (co_iters + ac_iters) == 0 and i > 0): + # 重新量化 + # 导入训练后的 + codebook = kmeans_net(solver.net, total_layers, num_c) + codeDict, maskCode = quantize_net_with_dict(solver.net, total_layers, codebook) + solver.net.save(quantize_net_caffemodel) + solver.test_nets[0].copy_from(quantize_net_caffemodel) + _, accu = test_quantize_accu(solver.test_nets[0]) + accuracys.append(accu) + + solver.step(1) + if (i % (co_iters + ac_iters) < co_iters): + # 码表更新 + update_codebook_net(solver.net, codebook, codeDict, maskCode, args=args, update_layers=total_layers) + + print "Iter:%d, Time cost:%f" % (i, time.time() - start_time) + +plt.plot(accuracys, 'r.-') +plt.show() + +``` diff --git a/darknect/caffe/caffe_tool/compute_flops_params_mac_1_3_conv_percent.py b/darknect/caffe/caffe_tool/compute_flops_params_mac_1_3_conv_percent.py index 5727c9d6..473b5ca3 100644 --- a/darknect/caffe/caffe_tool/compute_flops_params_mac_1_3_conv_percent.py +++ b/darknect/caffe/caffe_tool/compute_flops_params_mac_1_3_conv_percent.py @@ -1,4 +1,4 @@ -#-*- coding:utf-8 -*- + #-*- coding:utf-8 -*- import sys # add your caffe/python path sys.path.insert(0, "/home/wanyouwen/ewenwan/software/caffe-ssd/python") @@ -55,39 +55,56 @@ def print_net_parameters_flops (deploy_file): # 卷积核维度 output_channel * input_channel * kernel_height * kernel_width # ['Convolution'] if net.layer_dict[layer_name].type == typenames[0]: - # flops = h*w*c1*c2*w_h*w_w + # 计算量 乘加次数 macc = h_out*w_ou*c_in*c_out* k_h * k_w + # 如果是 flops 近似为 2倍的 macc cur_flops = (np.product(net.params[layer_name][0].data.shape) * \ - h_out*w_out)# 是否需要乘以2 + h_out*w_out)# + # 输出图面积 * 卷积核面积 * 输入通道数量 * 输出通道数量 + # 卷积核参数 net.params[layer_name][0].data + # shape[0] shape[1] shape[2] shape[3] 输出数量Cout 输入数量Cin k_h k_w - - # mac访存 h*w*c_in + h2*w2*c_out + c_in*c_out*w_h*w_w - cur_mac = (h_in*w_in*net.params[layer_name][0].data.shape[1] + \ + # mem acc cost 访存 h*w*c_in + h2*w2*c_out + c_in*c_out* k_h*k_w + cur_mac = (h_out*w_out*np.product(net.params[layer_name][0].data.shape) + \ h_out*w_out*net.params[layer_name][0].data.shape[0] + \ np.product(net.params[layer_name][0].data.shape)) + # 输入访问 + 输出内存大小 + 卷积核内存大小 + # 1. 输入(K × K × Cin) x (Hout x Wout x Cout) 一次访问输入数据大小(单个卷积核参数量) * 总共多少次(输出像素数量) + # 2. 输出 output = Hout × Wout × Cout 计算一次,输出赋值一次 + # 3. 参数 weights = K × K × Cin × Cout + Cout 读取一次在缓存,Cout 个 维度为 K × K × Cin 的卷积核 + # 特征图H*W * Weight_h * Weight_w*c_in*c_out*2 / 1 + # 乘法和加法 # ['DepthwiseConvolution'] elif net.layer_dict[layer_name].type == typenames[1]: + # 逐通道卷积 一个卷积核的厚度 从c_in 变为 1 相当于组卷积数量 为 输入c_in数量 + # 是普通卷积 的 macc / c_in cur_flops = (np.product(net.params[layer_name][0].data.shape) * \ h_out*w_out/net.params[layer_name][0].data.shape[1]) - # 特征图H*W * Weight_h * Weight_w*c_in*c_out*2 / group + # K × K × C_out × Hout × Wout # mac访存 h*w*c_in + h2*w2*c_out + c_in*c_out*w_h*w_w/group - cur_mac = (h_in*w_in*net.params[layer_name][0].data.shape[1] + \ + cur_mac = (h_out*w_out*np.product(net.params[layer_name][0].data.shape)/net.params[layer_name][0].data.shape[1] + \ h_out*w_out*net.params[layer_name][0].data.shape[0] + \ np.product(net.params[layer_name][0].data.shape)/net.params[layer_name][0].data.shape[1]) + # 输入 输入(K × K × 1) x (Hout x Wout x Cout) + # 输出 h_out*w_out*C_out + # 权重 C_out * c_in *k_h * k_w / c_in 厚度从 c_in 变为1 + # InnerProduct c_in*c_out*1*1 else: cur_flops = np.product(net.params[layer_name][0].data.shape) - # 特征图H*W = 1*1 - # Weight_h * Weight_w * c_in*c_out*2 + # kernel特征图H*W = 1*1 + # flops = Weight_h * Weight_w * c_in*c_out*2 # mac访存 h*w*c_in + 1*1*c_out + c_in*c_out*w_h*w_w/group cur_mac = (h_in*w_in*net.params[layer_name][0].data.shape[1] + \ 1*1*net.params[layer_name][0].data.shape[0] + \ np.product(net.params[layer_name][0].data.shape)) + + #''' # 3*3卷积 diff --git a/darknect/caffe/caffe_tool/convert_no_bn_2.py b/darknect/caffe/caffe_tool/convert_no_bn_2.py new file mode 100644 index 00000000..773eb429 --- /dev/null +++ b/darknect/caffe/caffe_tool/convert_no_bn_2.py @@ -0,0 +1,514 @@ +# coding:utf-8 +''' +# demo usage: +# modify_prototxt.py +--src_prototxt src_net.prototxt \ +--dst_prototxt dest_net.prototxt \ +--dst_width 1280 --dst_height 720 \ +--caffe_path /data/caffe/python +''' +import sys +import argparse +import copy +import os.path as osp + +''' +本脚本功能: +1.变换 prototxt 模型分辨率 以及 预设区域尺寸 anchors box 参数排布形式 +2.吸收BN层 和 Concat_ls层 +''' + +### 解析命令行参数 #### +def parse_args(): + """ + Parse input arguments + """ + parser = argparse.ArgumentParser(description='Convert conv+bn+scale to conv') + parser.add_argument('--src_prototxt', dest='src_prototxt', + help='prototxt file defining the source network', + default=None, type=str) + parser.add_argument('--dst_prototxt', dest='dst_prototxt', + help='prototxt file defining the destination network', + default=None, type=str) + parser.add_argument('--dst_width', dest='dst_width', + help='width of input image', + default=None, type=str) + parser.add_argument('--dst_height', dest='dst_height', + help='height of input image', + default=None, type=str) + parser.add_argument('--caffe_path', dest='caffe_path', + help='absolute path of caffe', + default=None, type=str) + if len(sys.argv) == 1: + parser.print_help() + sys.exit(1) + + args = parser.parse_args() + + if args.src_prototxt is None or args.dst_prototxt is None or args.dst_width is None or args.dst_height is None: + parser.print_help() + sys.exit(1) + + return args + +def add_path(path): + """ + purpose: add path in sys path + args: + path: path to be added + """ + if path not in sys.path: + sys.path.insert(0,path) + +### 加入python环境路径 ##### +args = parse_args() +# add darwin-caffe to PYTHONPATH +#caffe_path = osp.join(args.caffe_path,'python') +add_path(args.caffe_path) + +#caffe_root = '/data/caffe/python' +#sys.path.insert(0, caffe_root) +import caffe +from caffe.proto import caffe_pb2 +from caffe import layers as L +import google.protobuf as pb +import google.protobuf.text_format + +#''' +def extend_square_brackets(lines, idx, key_str, out_lines): + if lines[idx].find(key_str) != -1 and \ + (lines[idx].find('#') == -1 or \ + lines[idx].find('#') > lines[idx].find(key_str)) and \ + (lines[idx].find('[') != -1 or lines[idx+1].find('[') != -1):# 且本行出现 [ 或者下一行出现 [ (是否要加 [在关键字符串之后的条件?) + #lines[idx].find('_') == -1 and \ + + # 找到了关键字符串 + # 且该行 不包括 # + # 或者该行 的# 在 关键字符串后面出现 + # 且 无 _ 针对 anchors 有待确认 TODO 可以除去这个条件 + + #anchors_str = "" + key_str_str = "" + + temp_idx = idx + # 加入从 key_str:[ xxx,xxx, 开始的行 到有 ']' 无# 的行之前 + #while temp_idx < len(lines) and (not (lines[temp_idx].find(']') != -1 and lines[temp_idx].find('#') == -1)): + while temp_idx < len(lines) and \ + (not (lines[temp_idx].find(']') != -1 \ + and (lines[idx].find('#') == -1 or \ + lines[temp_idx].find('#') > lines[temp_idx].find(']')))): + # 在总字符区域查找 + # 没找到 ] + # 且 没找大 # 或者 # 出现在 ] 后面 + + key_str_str += lines[temp_idx].lstrip().strip() # 去左边空格 去左右两边空格 + temp_idx += 1 + + # 有可能是已经修改过后的文件(就找不到 anchors:[ xxx,xxx,...,xxx], temp_idx 会越界) + if temp_idx < len(lines): + idx = temp_idx + key_str_str += lines[idx] # 加入有 ]行 + key_str_str = ','.join(key_str_str.split()) # Delete redundatn blank + print key_str_str + front_idx = key_str_str.find('[') # [ 开始 + tail_idx = key_str_str.find(']') # ] 结束 + # key_str_str:[ xxx,xxx,...,xxx] + # 取出 数字部分 + key_str_str = key_str_str[front_idx + 1:tail_idx] + # 按逗号分隔 出每个数据 生成 列表 + key_str_list = [x for x in key_str_str.split(',') if x != ''] + print key_str_list + for key in key_str_list: + out_lines.append(" {}: {}\n".format(key_str,key)) + idx += 1 + #continue # Skip appending current line to the out_lines + #这个怎么解决 + + return idx, out_lines +#''' + +# 需要从list 展开的 关键字符串 +square_key_str_list = ['anchors', 'clses', 'forward_roi_num_per_cls', 'anchor_scales'] + +### 变换 prototxt 模型分辨率 以及 预设区域尺寸 anchors box 参数排布形式 +def preprocess(src_prototxt, dst_width, dst_height): + # 只读方式打开 + with open(src_prototxt, 'r') as fin: + lines = fin.readlines() + #resolu_dict = {'720': (720, 1280), '1080': (1080, 1920)} + #if resolution not in resolu_dict: + # print("Only support resolution '1080' or '720' ") + # exit() + idx = 0 + out_lines = [] + first_input_layer=True + while idx < len(lines): + # 遍历prototxt每一行 + # 1. 修改输入层 input layer 分辨率 参数 ### + if lines[idx].find('input_shape') != -1 : + in_cnt = 0 + out_lines.append(lines[idx]) + idx += 1 + while idx < len(lines) and lines[idx].find('dim') == -1: # Skip lines until find first dim + idx += 1 + continue + while idx < len(lines) and lines[idx].find('dim') != -1: # 保存所有有dim的行 + in_cnt += 1 + out_lines.append(lines[idx]) + idx += 1 + if in_cnt == 4 and first_input_layer: # 只修改第一个 dim=4 的输入层) + # 修改 输入层分辨率参数 + out_lines[-2] = " dim: {}\n".format(dst_height) + out_lines[-1] = " dim: {}\n".format(dst_width) + first_input_layer=False + ''' + # Find lines with not commented "anchor" + ### 2. 修改 检测网络 的 预设区域尺寸 anchors box 参数排布形式 ### + # 找到 含有anchors的行 并且无#号(未被注释) 也无'_'(排出掉num_anchors:行) + #if lines[idx].find('anchors') != -1 and lines[idx].find('#') == -1 and lines[idx].find('_') == -1 and (lines[idx].find('[') != -1 or lines[idx+1].find('[') != -1): + if lines[idx].find('anchors') != -1 and (lines[idx].find('#') == -1 or lines[idx].find('#') > lines[idx].find('anchors')) and lines[idx].find('_') == -1 and (lines[idx].find('[') != -1 or lines[idx+1].find('[') != -1): + anchors_str = "" + + temp_idx = idx + # 加入从 anchors:[ xxx,xxx, 开始的行 到有 ']' 无# 的行之前 + #while temp_idx < len(lines) and (not (lines[temp_idx].find(']') != -1 and lines[temp_idx].find('#') == -1)): + while temp_idx < len(lines) and (not (lines[temp_idx].find(']') != -1 and (lines[idx].find('#') == -1 or lines[temp_idx].find('#') > lines[temp_idx].find(']')))): + anchors_str += lines[temp_idx].lstrip().strip() # 去左边空格 去左右两边空格 + temp_idx += 1 + #while temp_idx < len(lines): + # if(lines[temp_idx].find(']') != -1 and lines[temp_idx].find('#') == -1): + # break + # anchors_str += lines[temp_idx].lstrip().strip() # 去左边空格 去左右两边空格 + # temp_idx += 1 + # + #if temp_idx < len(lines): + # print lines[temp_idx] + #print temp_idx + #print len(lines) + # 有可能是已经修改过后的文件(就找不到 anchors:[ xxx,xxx,...,xxx]) + if temp_idx < len(lines): + idx = temp_idx + anchors_str += lines[idx] # 加入有 ]行 + anchors_str = ','.join(anchors_str.split()) # Delete redundatn blank + print anchors_str + front_idx = anchors_str.find('[') + tail_idx = anchors_str.find(']') + # anchors:[ xxx,xxx,...,xxx] + # 取出 数字部分 + anchors_str = anchors_str[front_idx + 1:tail_idx] + # 按逗号分隔 出每个数据 生成 列表 + anchors_list = [x for x in anchors_str.split(',') if x != ''] + print anchors_list + for anchor in anchors_list: + out_lines.append(" anchors: {}\n".format(anchor)) + idx += 1 + continue # Skip appending current line to the out_lines + ''' + + #idx, out_lines = extend_square_brackets(lines, idx, 'anchors', out_lines) + ''' + ### 3. 修改 检测网络 的 kpn_proposal_parameter/kpn_output_parameter clses: [xx,xx,xx] 参数排布形式 ### + # 找到 含有clses的行 并且无#号(未被注释) 也无'_'(排出掉num_clses:行) + if lines[idx].find('clses') != -1 and (lines[idx].find('#') == -1 or lines[idx].find('#') > lines[idx].find('clses')) and lines[idx].find('_') == -1 and (lines[idx].find('[') != -1 or lines[idx+1].find('[') != -1): + clses_str = "" + + temp_idx = idx + # 加入从 anchors:[ xxx,xxx, 开始的行 到有 ']' 无# 的行之前 + while temp_idx < len(lines) and (not (lines[temp_idx].find(']') != -1 and (lines[idx].find('#') == -1 or lines[temp_idx].find('#') > lines[temp_idx].find(']')) )): + clses_str += lines[temp_idx].lstrip().strip() # 去左边空格 去左右两边空格 + temp_idx += 1 + + # 有可能是已经修改过后的文件(就找不到 anchors:[ xxx,xxx,...,xxx]) + if temp_idx < len(lines): + idx = temp_idx + clses_str += lines[idx] # 加入有 ]行 + clses_str = ','.join(clses_str.split()) # Delete redundatn blank + print clses_str + front_idx = clses_str.find('[') + tail_idx = clses_str.find(']') + # clses:[ xxx,xxx,...,xxx] + # 取出 数字部分 + clses_str = clses_str[front_idx + 1:tail_idx] + # 按逗号分隔 出每个数据 生成 列表 + clses_list = [x for x in clses_str.split(',') if x != ''] + print clses_list + for clses in clses_list: + out_lines.append(" clses: {}\n".format(clses)) + idx += 1 + continue # Skip appending current line to the out_lines + ''' + #idx, out_lines = extend_square_brackets(lines, idx, 'clses', out_lines) + + ''' + # 找到 含有forward_roi_num_per_cls的行 并且无#号(未被注释) 也无'_'(排出掉num_clses:行) + if lines[idx].find('forward_roi_num_per_cls') != -1 and (lines[idx].find('#') == -1 or lines[idx].find('#') > lines[idx].find('forward_roi_num_per_cls')) and (lines[idx].find('[') != -1 or lines[idx+1].find('[') != -1): + clses_str = "" + + temp_idx = idx + # 加入从 anchors:[ xxx,xxx, 开始的行 到有 ']' 无# 的行之前 + while temp_idx < len(lines) and (not (lines[temp_idx].find(']') != -1 and (lines[idx].find('#') == -1 or lines[temp_idx].find('#') > lines[temp_idx].find(']')))): + clses_str += lines[temp_idx].lstrip().strip() # 去左边空格 去左右两边空格 + temp_idx += 1 + + # 有可能是已经修改过后的文件(就找不到 anchors:[ xxx,xxx,...,xxx]) + if temp_idx < len(lines): + idx = temp_idx + clses_str += lines[idx] # 加入有 ]行 + clses_str = ','.join(clses_str.split()) # Delete redundatn blank + print clses_str + front_idx = clses_str.find('[') + tail_idx = clses_str.find(']') + # clses:[ xxx,xxx,...,xxx] + # 取出 数字部分 + clses_str = clses_str[front_idx + 1:tail_idx] + # 按逗号分隔 出每个数据 生成 列表 + clses_list = [x for x in clses_str.split(',') if x != ''] + print clses_list + for clses in clses_list: + out_lines.append(" forward_roi_num_per_cls: {}\n".format(clses)) + idx += 1 + continue # Skip appending current line to the out_lines + ''' + #idx, out_lines = extend_square_brackets(lines, idx, 'forward_roi_num_per_cls', out_lines) + ''' + # 找到 含有anchor_scales的行 并且无#号(未被注释) 也无'_'(排出掉num_clses:行) + if lines[idx].find('anchor_scales') != -1 and (lines[idx].find('#') == -1 or lines[idx].find('#') > lines[idx].find('anchor_scales')) and (lines[idx].find('[') != -1 or lines[idx+1].find('[') != -1): + clses_str = "" + + temp_idx = idx + # 加入从 anchors:[ xxx,xxx, 开始的行 到有 ']' 无# 的行之前 + while temp_idx < len(lines) and (not (lines[temp_idx].find(']') != -1 and (lines[idx].find('#') == -1 or lines[temp_idx].find('#') > lines[temp_idx].find(']')))): + clses_str += lines[temp_idx].lstrip().strip() # 去左边空格 去左右两边空格 + temp_idx += 1 + + # 有可能是已经修改过后的文件(就找不到 anchors:[ xxx,xxx,...,xxx]) + if temp_idx < len(lines): + idx = temp_idx + clses_str += lines[idx] # 加入有 ]行 + clses_str = ','.join(clses_str.split()) # Delete redundatn blank + print clses_str + front_idx = clses_str.find('[') + tail_idx = clses_str.find(']') + # clses:[ xxx,xxx,...,xxx] + # 取出 数字部分 + clses_str = clses_str[front_idx + 1:tail_idx] + # 按逗号分隔 出每个数据 生成 列表 + clses_list = [x for x in clses_str.split(',') if x != ''] + print clses_list + for clses in clses_list: + out_lines.append(" anchor_scales: {}\n".format(clses)) + idx += 1 + continue # Skip appending current line to the out_lines + ''' + #idx, out_lines = extend_square_brackets(lines, idx, 'anchor_scales', out_lines) + + for square_key_str in square_key_str_list: + idx, out_lines = extend_square_brackets(lines, idx, square_key_str, out_lines) + + + ### 4. 加入其它行 + out_lines.append(lines[idx]) + idx += 1 + + # 5. 可写方式打开 写入修改后的文件 + with open(src_prototxt, 'w')as fout: + for line in out_lines: + fout.write(line) + +### 转换 prototxt 去除bn层 并 变换到指定分辨率 +def process_prototxt(src_prototxt, dst_prototxt, dst_width, dst_height): + """ + @function: Process original test prototxt for converting bin + :param src_prototxt: + :param dst_prototxt: + :param resolution: Specify image resolution. "720P" [720*1080], "1080P" [1080*1920] + :return: + """ + ### 变换 prototxt 模型分辨率 以及 预设区域尺寸 anchors box 参数排布形式 ### + preprocess(src_prototxt, dst_width, dst_height) + src_net = caffe_pb2.NetParameter() + # 吸收BN层 Scale 被改名为 "findBatchNorm" + layer_type_set = set([u"BatchNorm", u"BN", u"Scale", u"LBN"]) + + # conv+BN / conv+LBN / conv+BatchNorm+Scale / conv+Scale + + # 只读方式打开 + with open(src_prototxt, 'r') as fin: + # 解析prototxt文件 保存每一层信息到 src_net + pb.text_format.Merge(fin.read(), src_net) + + ### 吸收 Concat_ls/concat_res层 ### + concat_loss_name_list=["Concat_ls","concat_res"] # 最后特有的 收集 loss_Px 层的concat层 + + Concat_ls_layer_exist=False + # 遍历 网络的每一层 + remove_layer=[] + # 前向时需要删除的层 Dropout层等 + forward_remove_layer = [] + # 记录非in-place的信息用于修改 + dict_cbn={} # 记录 BN类层输出 : 卷积层的输出 bottom名字 字典 + dict_activate={} # 激活层 in-place 修改 前后 名字字典 + + + # enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。 + for i, layer in enumerate(src_net.layer): + '''############ 1. BN 结构处理 ###################''' + # BN层 + if layer.type in layer_type_set: + #print(layer.type) + # BN层的前一层 + pre_layer = src_net.layer[i - 1] + if pre_layer.type == "Convolution": + remove_layer.append(layer) + # 合并BN层到前一层convolution_param参数里面 Set bias of convolution before current layer True + pre_layer.convolution_param.bias_term = True + + # 可能该层在网络最后 有问题 + if ((i + 1) < (len(src_net.layer) - 1)) and (src_net.layer[i + 1].type not in layer_type_set): + #### 确保是 卷积+BN / 卷积+LBN / 卷积+Scale / 卷积+BatchNorm 的结构 + dict_cbn[layer.top[0]]=pre_layer.top[0] + + #### 确保是 卷积+BatchNorm+Scale + if i >= 2 and layer.type == "Scale" and pre_layer.type == "BatchNorm" and src_net.layer[i - 2].type == "Convolution": + remove_layer.append(layer) + # scale输出的blob名 和 卷积层的输出blob名关联 + dict_cbn[layer.top[0]]=src_net.layer[i - 2].top[0] + + '''############ 2. concat+nms 结构处理 ###########''' + #Concat_ls_layer_exist=False + # 记录 Concat_ls 层 + if layer.name in concat_loss_name_list: # Delete concat_res layer + # 拷贝 名为 Concat_ls 层 的 输入 层列表 + bottom_list = copy.deepcopy(layer.bottom) + # 拷贝 名为 Concat_ls 层 + tmp_layer = copy.deepcopy(layer) + Concat_ls_layer_exist=True + if Concat_ls_layer_exist: + # 将concat_loss层的输入直接合并到 输入为loss或combine_loss的nms层中 + if layer.name == "nms": + print layer.bottom + if 'loss' == layer.bottom[0]: + layer.bottom.remove('loss') + elif 'combine_loss' == layer.bottom[0]: + layer.bottom.remove('combine_loss') + else: + print "error!! only support loss and combine_loss" + # 将 concat_loss 层的输入直接合并到 输入为 loss 或 combine_loss的 nms 层中 + layer.bottom.extend(bottom_list) + + '''############ 3. Dropout层处理 ##################''' + if layer.type in ['Dropout']: + forward_remove_layer.append(layer) + + '''# 除去bn 层''' + for layer in remove_layer: + print "remove "+layer.name + src_net.layer.remove(layer) + '''# 去除 Concat_ls 层''' + if Concat_ls_layer_exist: + try: + #if(tmp_layer): + src_net.layer.remove(tmp_layer) + except NameError: + print("Concat_ls layer not exist") + '''# 除去 Dropout 层''' + for layer in forward_remove_layer: + print "remove "+layer.name + src_net.layer.remove(layer) + # 处理 Dropout 层 非 in-place + for layer in forward_remove_layer: + # 非 in-place 情况:输入botom != 输出 + if layer.bottom[0] != layer.top[0]: + print "Dropout layer not in-place " + for src_layer in src_net.layer: + for id in range(len(src_layer.bottom)): + # 在网络中找到以 Dropout层的输出bottom 为输入的层,也就是该层的后继层 + if src_layer.bottom[id] == layer.top[0]: + #改名字 + src_layer.bottom[id] = layer.bottom[0] + + + #### 如果 卷积+BatchNorm+Scale的输入输出blob名字不一样, + #### 那么其后面的层如激活层 Relu的输入blob就需要改名为前面卷积层的输出blob的名字 + #activatre_layer_type=["ReLU","Sigmoid","TanH","Power","PReLU","AbsVal","BNLL","ELU","LeakyReLU"] #### 处理方式有bug + #convolution_layer=["Convolution","Deconvolution"] + #last_layer=None + #for i, layer in enumerate(src_net.layer): + # if layer.type in activatre_layer_type and last_layer.type in convolution_layer: + # if len(layer.bottom) != 1 or len(last_layer.top) != 1: + # print layer.type + " / " + last_layer.type + " top/bottom numn not 1" + # else: + # layer.bottom.remove(layer.bottom[0]) + # layer.bottom.append(last_layer.top[0]) + # + # last_layer=layer + + # 修改激活层的 输入名 同时修改激活层为 in-place情况 + activate_layer = ["ReLU","Sigmoid","TanH","Power","PReLU","AbsVal","BNLL","ELU","LeakyReLU"] + for i, layer in enumerate(src_net.layer): + if layer.type in activate_layer: + #print "layername :"+layer.name + #for id in range(len(layer.bottom)): + #print layer.bottom[id] + # dict_cbn: 激活层输出:前层卷积层输出 + # 查找 有已 被删除的 激活层的输出为 输入的 激活层 + if layer.bottom[0] in dict_cbn: + layer.bottom[0] = dict_cbn[layer.bottom[0]] # 替换为 对应卷积层的输出 + # 记录 激活层 输出:输入 字典 为处理 激活层的后继层做处理 + dict_activate[layer.top[0]] = layer.bottom[0] + layer.top[0] = layer.bottom[0] # 改成 inplace + ''' + follow_bn_layer = ["Pooling","Convolution"] + for i, layer in enumerate(src_net.layer): + if layer.type in follow_bn_layer: + #print "layername :"+layer.name + #for id in range(len(layer.bottom)): + #print layer.bottom[id] + if layer.bottom[0] in dict_cbn: + layer.bottom[0] = dict_cbn[layer.bottom[0]] + + elif layer.bottom[0] in dict_activate: + layer.bottom[0] = dict_activate[layer.bottom[0]] + + # 处理岔路口合并的情况 + 激活 非 inplace的case + #merge_layer=["Eltwise","Concat","Crop"] + merge_layer=["Eltwise","Concat","Crop"] + for i, layer in enumerate(src_net.layer): + if layer.type in merge_layer: + #print "layername :"+layer.name + for id in range(len(layer.bottom)): + #print layer.bottom[id] + if layer.bottom[id] in dict_cbn: + layer.bottom[id] = dict_cbn[layer.bottom[id]] + + elif layer.bottom[id] in dict_activate: + layer.bottom[id] = dict_activate[layer.bottom[id]] + ''' + for i, layer in enumerate(src_net.layer): + for id in range(len(layer.bottom)): + # BN层 in-place 后,其后继层的调整 + if layer.bottom[id] in dict_cbn: + layer.bottom[id] = dict_cbn[layer.bottom[id]] + # 激活层 in-place 后,其后继层的调整 + elif layer.bottom[id] in dict_activate: + layer.bottom[id] = dict_activate[layer.bottom[id]] + + + + # 这种处理有bug + #for dict_cbn_key in dict_cbn: + # for layer in src_net.layer: + # if layer.type not in activatre_layer_type: + # for id in range(len(layer.bottom)): + # if layer.bottom[id] == dict_cbn_key: + # layer.bottom[id] = dict_cbn[dict_cbn_key] + + + # 写入修改后的文件 + with open(dst_prototxt, 'w') as fout: + fout.write(pb.text_format.MessageToString(src_net)) + + +if __name__ == "__main__": + args = parse_args() + process_prototxt(args.src_prototxt, args.dst_prototxt, args.dst_width,args.dst_height) diff --git a/darknect/caffe/caffe_tool/convert_no_bn_3.py b/darknect/caffe/caffe_tool/convert_no_bn_3.py new file mode 100644 index 00000000..6b93ca51 --- /dev/null +++ b/darknect/caffe/caffe_tool/convert_no_bn_3.py @@ -0,0 +1,232 @@ +#coding: utf-8 +#!/usr/bin/env python +''' +# usage: +# convbn2conv.py + --src_proto src_debn_net.prototxt \ + --src_model src_bn.caffemodel \ + --dst_proto dest_debn_net.prototxt \ + --dst_model dest_debn.caffemodel \ + --caffe_path /data/caffe/python +''' +''' +吸收模型文件caffemodel中的BN层参数 + +''' +# -------------------------------------------------------- +# Fast R-CNN +# Copyright (c) 2015 Microsoft +# Licensed under The MIT License [see LICENSE for details] +# Written by Ross Girshick +# -------------------------------------------------------- + +"""Test a Fast R-CNN network on an image database.""" +import sys +import argparse +import os.path as osp + +def parse_args(): + """ + Parse input arguments + """ + parser = argparse.ArgumentParser(description='Convert conv+bn+scale to conv') + # 原去除bn层的prototxt + parser.add_argument('--src_proto', dest='src_prototxt', + help='prototxt file defining the source network', + default=None, type=str) + # 原caffemodel + parser.add_argument('--src_model', dest='src_caffemodel', + help='model to convert', + default=None, type=str) + parser.add_argument('--dst_proto', dest='dst_prototxt', + help='prototxt file defining the destination network', + default=None, type=str) + parser.add_argument('--dst_model', dest='dst_caffemodel', + help='dest caffemodel', + default='result.caffemodel', type=str) + # caffe主目录路径 + parser.add_argument('--caffe_path',dest='caffe_path', + help='absolute path of caffe', + default='None',type=str) + + if len(sys.argv) == 1: + parser.print_help() + sys.exit(1) + + args = parser.parse_args() + + if args.src_prototxt is None or args.src_caffemodel is None or args.dst_prototxt is None: + parser.print_help() + sys.exit(1) + + return args + +def add_path(path): + """ + purpose: add path in sys path + args: + path: path to be added + """ + if path not in sys.path: + sys.path.insert(0,path) + + +args = parse_args() +#caffe_path = osp.join(args.caffe_path,'python') +add_path(args.caffe_path) + +import caffe +import pprint +import time, os + +os.environ["CUDA_VISIBLE_DEVICES"] = "0" +import numpy as np +import pdb + + +### 按名字查找某一层 +def find_layer(name, net): + for idx, n in enumerate(net._layer_names): + if n == name: + return net.layers[idx] + return None + +### 合并bn层 bn_layer 到前一层的 卷积层 conv_layer 中 +def merge_bn(bn_layer, conv_layer): + scale_factor = bn_layer.blobs[2].data[0] + # 尺度参数 + if scale_factor != 0: + scale_factor = 1.0 / scale_factor + # 均值参数 + mean = bn_layer.blobs[0].data + # 方差参数 + var = bn_layer.blobs[1].data + + mean *= scale_factor + #### TODO + eps = 1e-5 # how to get the parameter 'eps' of BatchNorm lyaer + var = np.sqrt(var * scale_factor + eps) + # 卷积层参数维度 和 BN层参数维度一致 + assert conv_layer.blobs[0].data.shape[0] == mean.shape[0] + # 卷积 weight + blob0 = conv_layer.blobs[0].data + # 卷积偏置 bias + blob1 = conv_layer.blobs[1].data + for fi in range(mean.shape[0]): + blob0[fi] /= var[fi] + blob1[fi] = (blob1[fi] - mean[fi]) / var[fi] + +### 合并lbn层(bn+scale) 到前一层的 卷及参数中 +def merge_lbn(lbn_layer, conv_layer): + scale = lbn_layer.blobs[0].data + shift = lbn_layer.blobs[1].data + mean = lbn_layer.blobs[2].data + var = lbn_layer.blobs[3].data + # pdb.set_trace() + scale = scale.reshape(scale.size) + shift = shift.reshape(shift.size) + mean = mean.reshape(mean.size) + var = var.reshape(var.size) + + eps = 1e-5 # how to get the parameter 'eps' of BatchNorm lyaer + + W = conv_layer.blobs[0].data + bias = conv_layer.blobs[1].data + + assert W.shape[0] == mean.size + assert bias.size == mean.size + + alpha = scale / np.sqrt(var + eps); + # 变化 bias + conv_layer.blobs[1].data[...] = alpha * (bias - mean) + shift; + # 变换 weight + for fi in range(mean.shape[0]): + W[fi] *= alpha[fi] + +### 合并 缩放层 到前一层的 卷及参数中 +def merge_scale(scale_layer, conv_layer): + scale = scale_layer.blobs[0].data + shift = None + if len(scale_layer.blobs) == 2: + shift = scale_layer.blobs[1].data + + assert conv_layer.blobs[0].data.shape[0] == scale.shape[0] + + blob0 = conv_layer.blobs[0].data + #if shift is not None: + # 有bug + # 卷积层 的 bias_term为true 这里 blob1 肯定会存在 + blob1 = conv_layer.blobs[1].data + for fi in range(scale.shape[0]): + # weight 执行 缩放系数 + blob0[fi] *= scale[fi] + # bias 执行 缩放+平移 + if shift is not None: + blob1[fi] = blob1[fi] * scale[fi] + shift[fi] + else: + blob1[fi] = blob1[fi] * scale[fi] + + +if __name__ == '__main__': + + print('Called with args:') + print(args) + # cpu模式 + caffe.set_mode_cpu() + # 原网络 + src_net = caffe.Net(args.src_prototxt, args.src_caffemodel, caffe.TEST) + # 目标网络 无权重参数 + dst_net = caffe.Net(args.dst_prototxt, caffe.TEST) + # 目标网络数据清零 + for layer in dst_net.layers: + for b in layer.blobs: + b.data[...] = 0 + + prev_conv_layer = None + for name, layer in zip(src_net._layer_names, src_net.layers): + print(name) + + # 在目标网络中找到 name命名的层 + dst_layer = find_layer(name, dst_net) + if dst_layer is not None: + # 该层blob的数量 + blob_n = min(len(layer.blobs), len(dst_layer.blobs)) + # 设置 目标网络该层的数据 + for i in range(blob_n): + dst_layer.blobs[i].data[...] = layer.blobs[i].data[...] + + #记录原网络前一层卷积层参数 + if dst_layer.type == "Convolution": + prev_conv_layer = dst_layer + + # 目标网络中这一层已经删除,需要将其参数合并到该层的前继卷积层 + if dst_layer is None: + if layer.type == "BatchNorm": + if len(prev_conv_layer.blobs) != 2: + print("layer %s must have bias term" % name) + sys.exit(0) + # 吸收BatchNorm层 layer 到前一层 卷积层 prev_conv_layer 中 + merge_bn(layer, prev_conv_layer) + + elif layer.type == 'Scale': + if len(layer.blobs) == 2 and len(prev_conv_layer.blobs) != 2: + print("layer %s must have bias term" % name) + sys.exit(0) + # 吸收 Scale 层 到前一层 卷积层 prev_conv_layer 中 + merge_scale(layer, prev_conv_layer) + + elif layer.type == "LBN": + if len(prev_conv_layer.blobs) != 2: + print("layer %s must have bias term" % name) + sys.exit(0) + # 吸收LBN(BatchNorm+Scale)层 到前一层 卷积层 prev_conv_layer 中 + merge_lbn(layer, prev_conv_layer) + + elif layer.type == "BN": + if len(prev_conv_layer.blobs) != 2: + print("layer %s must have bias term" % name) + sys.exit(0) + # 吸收LBN(BatchNorm+Scale)层 到前一层 卷积层 prev_conv_layer 中 + merge_lbn(layer, prev_conv_layer) + + dst_net.save(args.dst_caffemodel) diff --git a/darknect/caffe/caffe_tool/readme.md b/darknect/caffe/caffe_tool/readme.md index 7eb9fea3..42b97756 100644 --- a/darknect/caffe/caffe_tool/readme.md +++ b/darknect/caffe/caffe_tool/readme.md @@ -10,7 +10,7 @@ bn层即batch-norm层,一般是深度学习中用于加速训练速度和一种方法, 一般放置在卷积层(conv层)或者全连接层之后, 将数据归一化并加速了训练拟合速度。 - 但是bn层虽然在深度学习模型训练时起到了一定的积极作用, + 但是 bn 层虽然在深度学习模型训练时起到了一定的积极作用, 但是在预测时因为凭空多了一些层,影响了整体的计算速度并占用了更多内存或者显存空间。 所以我们设想如果能将bn层合并到相邻的卷积层或者全连接层之后就好了. @@ -32,3 +32,245 @@ ## caffe coco模型 转 voc模型 coco2voc.py + +## 模型修改 +```py +import numpy as np +import caffe +from caffe.proto import caffe_pb2 +from google.protobuf import text_format + +# //修改后的prototxt +src_prototxt = "xxx.prototxt" + +# //原始的prototxt +old_prototxt = "s.prototxt" +old_caffemodel = "s.caffemodel" + +# 创建网络模型对象 +caffe.set_mode_cpu() +net = caffe.Net(src_prototxt, caffe.TEST) +net_old = caffe.Net(old_prototxt, old_caffemodel, caffe.TEST) + +src_net_params = caffe_pb2.NetParameter() +text_format.Merge(open(src_prototxt).read(), src_net_params) + +#拷贝相同名字层的参数 +for k,v in net_old.params.items(): + # print (k,v[0].data.shape) + # print (np.size(net_old.params[k])) + if(k in net.layer_dict.keys()): + print(k, v[0].data.shape) + print(np.size(net_old.params[k])) + for i in range(np.size(net_old.params[k])): + net.params[k][i].data[:] = np.copy(net_old.params[k][i].data[:]) +net.save("eur_single.caffemodel") +``` + + +## 模型计算量 +[参考](https://github.com/Captain1986/CaptainBlackboard/blob/master/D%230023-CNN%E6%A8%A1%E5%9E%8B%E8%AE%A1%E7%AE%97%E9%87%8F%E4%BC%B0%E8%AE%A1/D%230023.md) + +在我们训练的深度学习模型在资源受限的嵌入式设备上落地时,**精度不是我们唯一的考量因素**,我们还需要考虑 + +1. **安装包的大小**,如果你的模型文件打包进app一起让客户下载安装,那么动辄数百MB的模型会伤害用户的积极性; + +2. 模型速度,或者说**计算量的大小**。现在手机设备上的图片和视频的分辨率越来越大,数据量越来越多;对于视频或者游戏,FPS也越来越高,这都要求我们的模型在计算时,速度越快越好,计算量越小越好; + +3. 运行时**内存占用大小**,内存一直都是嵌入式设备上的珍贵资源,占用内存小的模型对硬件的要求低,可以部署在更广泛的设备上,降低我们**算法落地的成本**;况且,一些手机操作系统也不会分配过多的内存给单一一个app,当app占用内存过多,系统会kill掉它; + +4. **耗电量大小**,智能手机发展到今天,最大的痛点一直是电池续航能力和发热量,如果模型计算量小,内存耗用小的话,自然会降低电量的消耗速度。 + +### 计算量评价指标 + +一个朴素的评估模型速度的想法是评估它的计算量。一般我们用FLOPS,即每秒浮点操作次数FLoating point OPerations per Second这个指标来衡量GPU的运算能力。这里我们用MACC,即乘加数Multiply-ACCumulate operation,或者叫MADD,来衡量模型的计算量。 + +不过这里要说明一下,用MACC来估算模型的计算量只能**大致地**估算一下模型的速度。模型最终的的速度,不仅仅是和计算量多少有 +关系,还和诸如**内存带宽**、优化程度、CPU流水线、Cache之类的因素也有很大关系。 + +为什么要用乘加数来评估计算量呢?因为CNN中很多的计算都是类似于y = w[0]*x[0] + w[1]*x[1] + w[2]*x[2] + ... + w[n-1]*x[n-1]这样的点乘然后累加的形式,其中w和x是向量,结果y是标量。 + +在CNN中最常见的卷积层和全连接层中,w是学习到的权重值,而x是该层的输入特征图,y是该层的输出特征图。一般来说,每层输出不止一张特征图,所以我们上面的乘加计算也要做多次。这里我们约定w[0]*x[0] + ...算一次乘加运算。这样来算,像上面两个长度为n的向量w和x相乘,就有n次乘法操作和n-1次加法操作,大约可等于n次乘加操作。 + + +### CNN常用层计算量分析 + +#### 全连接层 + +全连接层执行的计算就是y = matmul(x, W) + b,这里x是I个输入值的向量,W是包含层权重的IxJ矩阵,b是包含J个元素的偏置值向量。结果y包含由层计算的输出值,也是大小为J的向量。 + +为了计算MACC的数量,我们看点乘发生的位置matmul(x, W)。矩阵乘法matmul只包含一大堆的点积运算。每个点积都在输入x和矩阵W的一列间发生。两者都有个I元素,因此这算作I个MACC。我们必须计算J个这样的点积,因此MACC的总数IxJ与权重矩阵的大小相同。 + +加偏置b并不会太影响MACC的数量,毕竟加偏置的操作次数远少于矩阵乘法里面的乘加次数。 + +总之,一个长度为I的向量与一个I x J维度的矩阵相乘(这就是全连接呀)得到一个长度为J的输出向量,需要I x J次MACC或者(2xI - 1) x J和FLOPS。 + +如果全连接层直接跟随卷积层,则其输入大小可能不会被指定为单个矢量长度I,但是可能被指定为具有诸如形状(512, 7, 7)的特征图。例如Keras要求你先将这个输入“压扁flatten”成一个向量,这样就可以得到I = 512×7×7个输入。 + +### 激活函数 + +通常深度学习模型层的后面会串联一个非线性激活函数,例如ReLU或者Sigmoid函数。这些激活函数自然也会消耗时间。但是我们不用MACC来计算它们的计算量,而是使用FLOPS,因为它们不完全是乘加运算。 + +有些激活函数的计算比其他激活函数更难,例如,ReLU:y = max(x, 0),这只是GPU上的一次单次操作。对于一个有J个输出神经元的全连接层来说,ReLU只做J次这样的运算,所以算J次FLOPS。对于Sigmoid函数y = 1 / (1 + exp(-x))来说,因为它涉及到指数运算和倒数,所以它有更多的计算量。当我们计算FLOPS时,我们通常把加、减、乘、除、取幂、求根等看做一次FLOPS。因为Sigmoid函数有四种(减、取幂、加、除),所以它每个输出对应四个FLOPS,对于J个输出单元的全连接层后的Sigmoid激活层,有J x 4次FLPOS。 + +通常我们不计算激活函数的计算量,因为他们只占整个网络计算量中的很小一部分,我们主要关心大矩阵乘法和点乘运算,直接认为激活函数的运算是免费的。 + +总结:不需要担忧激活函数。 + +### 卷积层 + +卷积层的输入和输出不是矢量,而是三维特征图H × W × C,其中H是特征图的高度,W宽度和C是通道数。 + +今天使用的大多数卷积层都是方形核。对于具有核大小K的卷积层,MACC的数量为:K × K × Cin × Hout × Wout × Cout。这个公式可以这么理解: + + 首先,输出特征图中有Hout × Wout × Cout个像素; + + 其次,每个像素对应一个立体卷积核K x K x Cin在输入特征图上做立体卷积卷积出来的; + + 最后,而这个立体卷积操作,卷积核上每个点都对应一次MACC操作 + + 同样,我们在这里为了方便忽略了偏置和激活。 +我们不应该忽略的是层的stride,以及任何dilation因子,padding等。这就是为什么我们需要参看层的输出特征图的尺寸Hout × Wout,因它考虑到了stride等因素。 + +### 深度可分离卷积层 + +这里对于MobileNet V1中的深度可分离卷积只列个结论,更详细的讨论可见本黑板报我前面写的depthwise separable convolutions in mobilenet一文。MobileNet V1深度可分层的总MACC是:MACC_v1 = (K × K × Cin × Hout × Wout) + (Cin × Hout × Wout × Cout),其中K是卷积核大小,Cin是输入特征图通道数,Hout, Wout是DW卷积核输出尺寸(PW卷积只改变输出通道数,不改变输入输出尺寸)。深度可分离卷积的计算量和传统卷积计算量的比为(K × K + Cout) / K × K × Cout,约等于 1 / (K x K)。 + +下面我们详细讨论下MobileNet V2中的MACC。 + +MobileNet V2相比与V1,主要是由DW+PW两层变成了下面的三层PW+DW+PW: + +一个1×1卷积,为特征图添加更多通道(称为expansion layer) + +3×3深度卷积,用于过滤数据(depthwise convolution) + +1×1卷积,再次减少通道数(projection layer,bottleneck convolution) + +这种扩展块中MACC数量的公式: + +Cexp = (Cin × expansion_factor),(expansion_factor用于创建深度层要处理的额外通道,使得Cexp在此块内使用的通道数量) + +MACC_expansion_layer = Cin × Hin × Win × Cexp,(参照上面传统卷积,把卷积核设置为1x1即得) + +MACC_depthwise_layer = K × K × Cexp × Hout × Wout(参照MoblieNet V1分析) + +MACC_projection_layer = Cexp × Hout × Wout × Cout(参照MoblieNet V1分析,或者传统卷积把卷积核设置为1x1即得) + +把所有这些放在一起: + +MACC_v2 = Cin × Hin × Win × Cexp + (K × K + Cout) × Cexp × Hout × Wout + +如果stride = 1,则简化为: + +(K × K + Cout + Cin) × Cexp × Hout × Wout + + +## 模型 内存访问估计 mem acc cost 内存带宽(bandwidth) +我们对常见层的计算量(MACC,FLOPS)做了分析和估算,但这只是模型性能估计这整个故事的一部分。内存带宽(bandwidth)是另一部分,大部分情况下,它比计算次数更重要! + +### 内存访问 +在当前的计算机架构中,内存的访问比CPU中执行单个计算要慢得多(需要更多的时钟周期)—— 大约100或更多倍! + +对于网络中的每个层,CPU需要: + + 1. 首先,从主存储器读取输入向量或特征图; + + 2. 然后,计算点积——这也涉及从主存中读取层的权重; + + 3. 最后,将计算出的结果作为新的矢量或特征图写回主存储器。 + +这涉及大量的内存访问。由于内存非常慢(相对于CPU计算速度而言),因此该层执行的内存读/写操作量也会对其速度产生很大影响——可能比计算次数更大。 + + +#### 卷积层和全连接层:读取权重带来的内存访问 + +网络每层学习的参数或权重存储在主存储器中。通常,模型的权重越少,运行的速度就越快。 + +> **将权重读入** + +**全连接层** 将其权重保持在大小I × J矩阵中,其中I是输入神经元的数量和J是输出的数量。它还有一个大小J的偏置量。所以这一层的权重总共有 **(I + 1) × J**。 + +**大多数卷积层**都有正方形内核,因此对于具有内核大小K和Cin输入通道的卷积层,每个滤波器都有权重K × K × Cin。该层将具有Cout滤波器/输出通道,因此权重总数 **K × K × Cin × Cout**加上额外的Cout个偏置值。 + +通常,**卷积层的权重数量小于全连接层。** + +很明显,**全连接层是内存权重访问的负担**! + +有用的结论:由于权值共享,卷积层一般占网络更少的权重参数数量,但是更多的计算量。 + +我们可以使用**全连接层实现卷积层**,反之亦然。卷积可以看成是一个全连接层,绝大多数连接设置为0——每个输出仅连接到K × K输入 +而不是所有输出,并且所有输出对这些连接使用相同的值。这就是卷积层对内存更有效的原因,因为它们不存储未使用的连接的权重。 + +[CNN中使用卷积代替全连接](https://github.com/Captain1986/CaptainBlackboard/blob/master/D%230025-CNN%E4%B8%AD%E4%BD%BF%E7%94%A8%E5%8D%B7%E7%A7%AF%E4%BB%A3%E6%9B%BF%E5%85%A8%E8%BF%9E%E6%8E%A5/D%230025.md) + +#### 卷积层:读取特征图、权重参数和写回中间结果带来的内存访问 + +在文献中,经常会看到模型的复杂性,其中列出了MACC(或FLOPS)的数量和训练参数的数量。但是,这忽略了一个重要的指标:层的输入读取的内存量,以及写入该层输出执行的内存访问次数。 + +假设卷积层的输入形状是Hin x Win x Cin图像,输出特征图形状Hout x Wout x Cout那么,对于每个输出特征图的像素来说,需要访问输入特征图次数为每个卷积核的参数的个数:K x K x Cin。所以,此卷积层需要访问内存(读取输入特征)的次数为(K × K × Cin) x (Hout x Wout x Cout)。(当然,一个聪明的GPU内核程序员将有办法优化这一点。每个GPU线程可以计算多个输出像素而不是一个,允许它多次重复使用一些输入值,总体上需要更少的内存读取,所有这些优化都将平等地应用于所有模型。因此,即使我的公式不是100%正确,它们的误差是常数级的,因此仍然可用于比较模型。) + +对于计算得到的特征图的输出,如果此特定卷积层的步幅为2,滤波器为32个,则它会写入具有112×112×32个值的输出特征图。那么需要112 x 112 x 32 = 401,408次内存访问。 + +对于本层卷积的参数从内存中读取,因为参数数量很少,可以直接认为只读取一次,存储在缓存中。这里读取次数为K x K x Cin x Cout + Cout。 + +总结:每个层将进行以下总内存访问: + + 1. input = (K × K × Cin) x (Hout x Wout x Cout) + 一次访问输入数据大小(单个卷积核参数量) * 总共多少次(输出像素数量) + 2. output = Hout × Wout × Cout + 计算一次,输出赋值一次 + 3. weights = K × K × Cin × Cout + Cout + 读取一次在缓存,Cout 个 维度为 K × K × Cin 的卷积核 + +具体举例来说,如果是一副输入224 x 224 x 3的图片,经过stride = 2,K = 3的卷积,输出112 x 112 x 32的特征图,那么有: + + input = 3 × 3 × 3 × 112 × 112 × 32 = 10,838,016(96.42%) + output = 112 × 112 × 32 = 401,408(3.57%) + weights = 3 × 3 × 3 × 32 + 32 = 896(0.01%) + total = 11,240,320 + +有这个例子我们可以看到,卷积层主要的内存访问发生在把输入特征图反复搬运到CPU参与计算(因此有得会重排参数和输入来达到更好的缓存访问效果),把计算得到的输出特征图写入内存和权重的读取带来的内存访问,可以忽略不计。顺便说一句,我们这里假设了权重只被读取一次并缓存在本地CPU/GPU内存中,因此它们可以在CPU/GPU线程之间共享,并将重新用于每个输出像素。 + +对于网络中较深的层,具有28 x 28 x 256个输入和28 x 28 x 512个输出,K = 3,stride = 1,那么: + + input = 3 × 3 × 256 × 28 × 28 × 512 = 924,844,032(99.83%) + output = 28 × 28 × 512 = 401,408(0.04%) + weights = 3 × 3 × 256 × 512 + 512 = 1,180,160(0.13%) + total = 926,425,600 + +即使特征图的宽度和高度现在较小,它们也会有更多的通道。这就是为什么权重的计算更多,因为由于通道数量的增加,权重会越来越多。但是主要的内存访问依然是把输入特征图反复搬运到CPU参与计算。 + +#### 深度可分离卷积分析 + +如果使用深度可分离卷积呢?使用跟前面相同的输入和输出大小,计算3×3深度卷积层和1×1逐点层的内存访问次数: + + DepthWise layer + input = 3 × 3 × 1 x 28 × 28 × 256 = 1,806,336 + output = 28 × 28 × 256 = 200,704 + weights = 3 × 3 × 1 x 256 + 256 = 2,560 + total = 2,009,600(1.91%) + PointWise layer + input = 1 × 1 × 256 × 28 × 28 × 512 = 102,760,448 + output = 28 × 28 × 512 = 401,408 + weights = 1 × 1 × 256 × 512 + 512 = 131,584 + total = 103,293,440(98.09%) + total of both layers = 105,303,040 + +可以看到深度可分离卷积它的内存访问量减少到大约原来的926425600 / 105303040 = 8.80倍(几乎是K × K倍),这就是使用深度可分层的好处。还可以看到Depth-Wise层的内存访问成本非常便宜,几乎可以忽略不计。 + +#### 激活层和BN层:融合 + +在PyTorch和大多数训练框架中,经常会看到Conv2D层后面跟着一个应用ReLU的激活层。这对训练框架来说很好,提供了灵活性,但是让ReLU成为一个单独的层是浪费的,特别是因为这个函数非常简单。 + +示例:对28 × 28 × 512卷积层的输出应用ReLU : + + input = 28 × 28 × 512 = 401,408 + output = 28 × 28 × 512 = 401,408 + weights = 0 + total = 802,816 + +首先,它需要从卷积层读取特征图每个像素,然后对其应用ReLU,最后将结果写回内存。当然,这非常快,因为它几乎与将数据从一个内存位置复制到另一个内存位置相同,但这样的操作有些浪费。 + +因此,激活函数通常与卷积层融合。这意味着卷积层在计算出点积之后直接应用ReLU,然后才能写出最终结果。这节省了一次读取和一次写入存储器的昂贵时钟开销。 + +同理,对于BN层来说,将BN层融合进卷积层也是一种在实践中经常用到的策略。 diff --git "a/darknect/caffe/caffe_\345\256\211\350\243\205.md" "b/darknect/caffe/caffe_\345\256\211\350\243\205.md" index 81de3c25..0db96833 100644 --- "a/darknect/caffe/caffe_\345\256\211\350\243\205.md" +++ "b/darknect/caffe/caffe_\345\256\211\350\243\205.md" @@ -53,8 +53,7 @@ sudo apt-get install python-numpy 7.2 测试 - python - import caffe + python import caffe 错误1: ImportError: No module named caffe 导入路径 @@ -91,5 +90,37 @@ +# 11. protobuf 源码安装 +下载 https://github.com/protocolbuffers/protobuf/archive/v3.8.0.tar.gz +解压 tar -xvf protobuf-3.8.0.tar.gz +编译安装 + +./autogen.sh + +可以修改安装目录通过 + + ./configure --prefix=/usr/local/protobuf + + make + + make check + + make install + +ldconfig + + +安装python支持: + + $ cd protobuf/python + $ python3 setup.py build + $ python3 setup.py test + $ python setup.py install + + 可能会提示差一些其他包 + + + + diff --git "a/darknect/caffe/pycaffe_\346\265\213\350\257\225.md" "b/darknect/caffe/pycaffe_\346\265\213\350\257\225.md" new file mode 100644 index 00000000..3f818b65 --- /dev/null +++ "b/darknect/caffe/pycaffe_\346\265\213\350\257\225.md" @@ -0,0 +1,461 @@ + +# 测试单层 +``` +# test_east +input: "_tadd_blob137" +input_shape { + dim: 1 + dim: 8 + dim: 128 + dim: 128 +} +input: "sigmoid_blob138" +input_shape { + dim: 1 + dim: 1 + dim: 128 + dim: 128 +} +layer { + name: "east_out" + type: "EastOutput" + bottom: "_tadd_blob137" + bottom: "sigmoid_blob138" + top: "output" + east_out_param { + stride: 4 + score_thre: 0.8 + nms_thre: 0.01 + nms_method: 2 + } +} + + +``` +```py + +#!/usr/bin/env python +# coding: utf-8 + +import os.path as osp +import sys,os + +def add_path(path): + if path not in sys.path: + sys.path.insert(0, path) + +### caffe路径 加入python环境路径 ##### +add_path("/data3/plat/wanyouwen/wanyouwen/cvt_bin_demo/tool/transfer_bin") + +os.system("export LD_LIBRARY_PATH=/data3/plat/wanyouwen/wanyouwen/cvt_bin_demo/tool/transfer_bin:$LD_LIBRARY_PATH") + + +import numpy as np +import caffe , cv2 +from caffe.proto import caffe_pb2 +from caffe import layers as L +import google.protobuf as pb +import google.protobuf.text_format + + +if __name__ == '__main__': + # 解析命令行参数 + #if args.cpu_mode: + caffe.set_mode_cpu() + # 创建网络 + test_net="test_east_out.prototxt" + unit_net = caffe.Net(test_net, caffe.TEST) + print '\nLoaded network {:s}\n'.format(test_net) + + # 读入数据 每行一个数据 + # input1 + #float_data_power = np.loadtxt("layer_id_98_transed_power136_128x128x8x1_out_0_whcn") + float_data_power = np.loadtxt("wk_transed_power136.txt") + float_data_power.shape=[1,8,128,128] + float_data_power = float_data_power.astype(np.float32) + # input2 + #float_data_sigmoid = np.loadtxt("layer_id_99_transed_sigmoid137_128x128x1x1_out_0_whcn") + float_data_sigmoid = np.loadtxt("wk_transed_sigmoid137.txt") + float_data_sigmoid.shape=[1,1,128,128] + float_data_sigmoid = float_data_sigmoid.astype(np.float32) + #需要知道 输入blob的名字 + + forward_kwargs = {"_tadd_blob137" : float_data_power} + forward_kwargs["sigmoid_blob138"] = float_data_sigmoid + unit_net.blobs["_tadd_blob137"].reshape(*(float_data_power.shape)) + unit_net.blobs["sigmoid_blob138"].reshape(*(float_data_sigmoid.shape)) + + print "unit_net.forward " + blobs_out = unit_net.forward(**forward_kwargs) + print "unit_net.forward down" + + + # 需要知道输出blob的名字 + # 提取输出 + print "extract output " + netopt = unit_net.blobs["output"] + print " ot shape " + for oi in range(len(netopt.shape)): + print netopt.shape[oi] + + with open("./output.txt",'ab')as fout: + # txt文本文件 reshape成 n行 1列 + np.savetxt(fout, netopt.data.reshape(-1, 1), fmt='%f', newline='\n') + + +``` + + +# 单模型测试 +```py +#!/usr/bin/env python +# coding: utf-8 +''' +# usage: +#python test_caffemodel_demo.py \ + --prototxt m.prototxt \ + --caffemodel m.caffemodel \ + --bgr_data bgr_data \ + --chanhel_mean_file 127.5, 127.5, 127.5 +eg: +python test_caffemodel_demo.py \ + --prototxt model_squeezenet_east_0.61G_fire11_bn_reduceV5-interp.prototxt \ + --caffemodel Squeezenet_EAST_CNR_toushi_kuozeng_190000_mvave.caffemodel \ + --bgr_data east_out_384_640_bgr + +python test_caffemodel_demo.py + --prototxt VDPR_mbv1_11_512_pool_e30_0427.prototxt \ + --caffemodel VDPR_mbv1_11_512_pool_e30_0427.caffemodel \ + --bgr_data vdpr_cls_bgr_256x32.raw + + +python test_caffemodel_demo.py \ + --prototxt merge_bn_kpnv7_yolov3-tep.prototxt \ + --caffemodel merge_bn_kpn_v6_yolov3_day_crop.caffemodel \ + --bgr_data adas_rec_960_256_bgr +''' +''' +生成指定层的输出数据 +''' +import os.path as osp +import sys,os +import argparse + +#### 解析命令行参数 +def parse_args(): + """Parse input arguments.""" + parser = argparse.ArgumentParser(description='generate YOLO V3 layer data demo') + parser.add_argument('--gpu', dest='gpu_id', + help='GPU device id to use [0]', default=0, type=int) + parser.add_argument('--cpu', dest='cpu_mode', + help='Use CPU mode (overrides --gpu)', action='store_true') + parser.add_argument('--prototxt', dest='prototxt', + help='caffe prototxt path', type=str) + parser.add_argument('--caffemodel', dest='caffemodel', + help='caffe model path', type=str) + parser.add_argument('--bgr_data', dest='bgr_data', + help='bgr_data', type=str) + parser.add_argument('--chanhel_mean_file', dest='chanhel_mean_file', + help='net chanhel mean file', type=str) + + + if len(sys.argv) == 1: + parser.print_help() + sys.exit(1) + + args = parser.parse_args() + + if args.prototxt is None or args.caffemodel is None or args.bgr_data is None: + parser.print_help() + sys.exit(1) + + return args + +def add_path(path): + if path not in sys.path: + sys.path.insert(0, path) + +### caffe路径 加入python环境路径 ##### +add_path("/data3/plat/wanyouwen/wanyouwen/cvt_bin_demo/tool/transfer_bin") + +os.system("export LD_LIBRARY_PATH=/data3/plat/wanyouwen/wanyouwen/cvt_bin_demo/tool/transfer_bin:$LD_LIBRARY_PATH") + + +import numpy as np +import caffe , cv2 +from caffe.proto import caffe_pb2 +from caffe import layers as L +import google.protobuf as pb +import google.protobuf.text_format + + +""" +参数配置 这里是不是要从外部传递过来 从文件载入通道均值数据 +""" +# yolov3通道均值 +#PIXEL_MEANS = 127.5 #np.array([[[127.5, 127.5, 127.5]]], dtype=np.float32) +#PIXEL_SCALE = 0.007843 +#PIXEL_MEANS = 123 +#PIXEL_MEANS = np.array([127.5, 127.5, 127.5]) +#PIXEL_SCALE = 0.007843 + +#PIXEL_MEANS = np.array([123.680000, 116.779999, 103.940002]) +#PIXEL_SCALE = 1 + +PIXEL_MEANS = np.array([128, 128, 128]) +#PIXEL_SCALE = 0.017 +PIXEL_SCALE = 0.017241379310344827 + +import matplotlib + +matplotlib.use('Agg') + +import matplotlib.pyplot as plt + +def save_feature_picture(data, name, image_name=None, padsize = 1, padval = 1): + data = data[0] + #print "data.shape1: ", data.shape + n = int(np.ceil(np.sqrt(data.shape[0]))) + padding = ((0, n ** 2 - data.shape[0]), (0, 0), (0, padsize)) + ((0, 0),) * (data.ndim - 3) + #print "padding: ", padding + data = np.pad(data, padding, mode='constant', constant_values=(padval, padval)) + #print "data.shape2: ", data.shape + data = data.reshape((n, n) + data.shape[1:]).transpose((0, 2, 1, 3) + tuple(range(4, data.ndim + 1))) + #print "data.shape3: ", data.shape, n + data = data.reshape((n * data.shape[1], n * data.shape[3]) + data.shape[4:]) + #print "data.shape4: ", data.shape + # 这里 plt 有问题 + #plt.figure() + plt.imshow(data, cmap='gray') + plt.axis('off') + #plt.show() + if image_name == None: + img_path = './data/feature_picture/' + else: + img_path = './data/feature_picture/' + image_name + "/" + check_file(img_path) + plt.savefig(img_path + name + ".jpg", dpi = 400, bbox_inches = "tight") + +def check_file(path): + if not os.path.exists(path): + os.mkdir(path) + +if __name__ == '__main__': + # 解析命令行参数 + args = parse_args() + prototxt = args.prototxt + caffemodel = args.caffemodel + bgr_data = args.bgr_data + + if not os.path.isfile(caffemodel): + raise IOError(('{:s} not exist!!!').format(caffemodel)) + if not os.path.isfile(bgr_data): + raise IOError(('{:s} not exist!!!').format(bgr_data)) + + #if args.cpu_mode: + caffe.set_mode_cpu() + + + src_net = caffe_pb2.NetParameter() # 网络prototxt对象 + # 只读方式打开 + with open(prototxt, 'r') as fin: + # 解析prototxt文件 保存每一层信息到 src_net + pb.text_format.Merge(fin.read(), src_net) + # + + input_name = src_net.input + input_size = len(input_name) + input_name_0 = input_name[0] + print "input_size " + str(input_size) + " input0_name: " + input_name_0 + # 针对这种形式的输入 + ''' + input_shape{ + dim: 1 + dim: 3 + dim: 384 #416 #540 + dim: 640 #864 + } + ''' + try: + if len( src_net.input_shape[0].dim) != 4 : + print "input shape error input dim not equal to 4" + + n = int(src_net.input_shape[0].dim[0]) + c = int(src_net.input_shape[0].dim[1]) + h = int(src_net.input_shape[0].dim[2]) + w = int(src_net.input_shape[0].dim[3]) + except: + # 这种形式 + ''' + input: "blob0" + input_dim: 1 + input_dim: 3 + input_dim: 32 + input_dim: 256 + ''' + if len( src_net.input_dim) != 4 : + print "input shape error input dim not equal to 4" + + n = int(src_net.input_dim[0]) + c = int(src_net.input_dim[1]) + h = int(src_net.input_dim[2]) + w = int(src_net.input_dim[3]) + + print "input shape: " + str(n) + " " + str(c) + " " + str(h) + " " + str(w) + + + im_info_input = False + if input_name[-1] == "im_info": + im_info_input = True + + + # 默认网络输出 blob 为 最后一层的top + out_layer = src_net.layer[len(src_net.layer)-1] + out_blob_name = out_layer.top[0] + + # 创建网络 + net = caffe.Net(prototxt, caffemodel, caffe.TEST) + print '\nLoaded network {:s}\n'.format(caffemodel) + + # 读入数据 + # fromfile()函数读回数据时需要用户指定元素类型,并对数组的形状进行适当的修改 + # tofile()将数组中的数据以二进制格式写进文件 + # tofile()输出的数据不保存数组形状和元素类型等信息 + data = np.fromfile(bgr_data, dtype=np.uint8) + # 形状外面传进来 + #data.shape = [1,3,384,640] + data.shape = [n,c,h,w] + + float_data = data.astype(np.float32) + # 去均值和归一化操作 + # 去均值 + float_data -= PIXEL_MEANS.reshape(1,3,1,1) + # 缩放尺度 + float_data *= PIXEL_SCALE + + #需要知道 输入blob的名字 + + forward_kwargs = {input_name_0: float_data} + net.blobs[input_name_0].reshape(*(float_data.shape)) + + if im_info_input: + im_info = np.array([[h, w, 1.0]], dtype=np.float32) + forward_kwargs[input_name[-1]] = im_info + + + print "net.forward " + blobs_out = net.forward(**forward_kwargs) + print "net.forward down" + + + # 需要知道输出blob的名字 + # 提取输出 + print "extract output " + netopt = net.blobs[out_blob_name] + print " ot shape " + for oi in range(len(netopt.shape)): + print netopt.shape[oi] + + # blob 保存标记 + blob_save_flag = {} + for bn in net.blobs: + #print type(bn) + #print bn + blob_save_flag[bn] = 0 + + # 打印网络每个blob的形状 + #net_blobs = [(k,v.data) for k,v in net.blobs.items()] + #print net_blobs[0][0] # 名字 + #print net_blobs[0][1] # 形状 (n,c,h,w) + #for k,v in net.blobs.items(): + # #save_feature_picture(v.data, k.replace("/", "")) + + #for ib in range(len(net_blobs)): + # blob = net_blobs[ib] + # print "name: " + str(blob[0]) + " shape: " + str(blob[1].shape) + # print type(blob[1]) + ''' + # 寻找 在网络中的那一层 的输入或是输出 + save_dir = './dump_bin/' + check_file(save_dir) + for i, layer in enumerate(src_net.layer): + if layer.type == "BatchNorm" or layer.type == "Scale": + continue + file_name_base = "layer_id_"+str(i) + bottom = layer.bottom + top = layer.top + for ib in range(len(bottom)): + b_blob = net.blobs[bottom[ib]] + b_shape = b_blob.shape + print len(b_shape) + while len(b_shape) < 4: + b_shape.append(1) + file_name = file_name_base + "_" + layer.name.replace("/", "_") + "_" + str(b_shape[3]) + "x" + str(b_shape[2]) + "x" + str(b_shape[1]) + "x" + str(b_shape[0]) + "_in_" + str(ib) + "_whcn" + b_blob.data.tofile(save_dir + file_name) + for ob in range(len(top)): + o_blob = net.blobs[top[ob]] + o_shape = o_blob.shape + while len(o_shape) < 4: + o_shape.append(1) + file_name = file_name_base + "_" + layer.name.replace("/", "_") + "_" + str(o_shape[3]) + "x" + str(o_shape[2]) + "x" + str(o_shape[1]) + "x" + str(o_shape[0]) + "_out_" + str(ib) + "_whcn" + o_blob.data.tofile(save_dir + file_name) + ''' + save_dir = './dump_txt/' + check_file(save_dir) + layer_num = len(src_net.layer) + for i, layer in enumerate(src_net.layer): + #if layer.type == "BatchNorm" or layer.type == "Scale": + # continue + print "save: " + str(i) + " layer, res: " + str(layer_num-i-1) + file_name_base = "layer_id_"+str(i) + bottom = layer.bottom + top = layer.top + for ib in range(len(bottom)): + if not blob_save_flag[bottom[ib]]: + blob_save_flag[bottom[ib]] = 1 + b_blob = net.blobs[bottom[ib]] + b_shape = b_blob.shape + while len(b_shape) < 4: + b_shape.append(1) + file_name = file_name_base + "_" + layer.name.replace("/", "_") + "_" + str(b_shape[3]) + "x" + str(b_shape[2]) + "x" + str(b_shape[1]) + "x" + str(b_shape[0]) + "_in_" + str(ib) + "_whcn" + #b_blob.data.tofile(save_dir + file_name) + with open(save_dir + file_name, 'ab')as fout: + # txt文本文件 reshape成 n行 1列 + np.savetxt(fout, b_blob.data.reshape(-1, 1), fmt='%f', newline='\n') + for ob in range(len(top)): + if not blob_save_flag[top[ob]]: + blob_save_flag[top[ob]] = 1 + o_blob = net.blobs[top[ob]] + o_shape = o_blob.shape + while len(o_shape) < 4: + o_shape.append(1) + file_name = file_name_base + "_" + layer.name.replace("/", "_") + "_" + str(o_shape[3]) + "x" + str(o_shape[2]) + "x" + str(o_shape[1]) + "x" + str(o_shape[0]) + "_out_" + str(ib) + "_whcn" + #o_blob.data.tofile(save_dir + file_name) + with open(save_dir + file_name, 'ab')as fout: + # txt文本文件 reshape成 n行 1列 + np.savetxt(fout, o_blob.data.reshape(-1, 1), fmt='%f', newline='\n') + + #打印网络参数形状 + #print [(k,v[0].data.shape) for k,v in net.params.items()] + + + ''' ocr 解析 + opdata = netopt.data.reshape(1, -1) + + opdata = netopt.data.tolist() + max_value = [] + max_id = [] + for ni in range(netopt.shape[0]): + max_value.append(0) + max_id.append(0) + for ci in range(netopt.shape[2]): + if opdata[ni][0][ci] > max_value[ni]: + max_value[ni] = opdata[ni][0][ci] + max_id[ni] = ci + + for ii in range(netopt.shape[0]): + if max_id[ii] != 96 and ( ii > 0 and max_id[ii] != max_id[ii-1] ): + print "id : " + str(max_id[ii]) + " conf: " + str(max_value[ii]) + ''' + +``` diff --git a/darknect/caffe/readme.md b/darknect/caffe/readme.md index a7b0374d..d6fd7fca 100644 --- a/darknect/caffe/readme.md +++ b/darknect/caffe/readme.md @@ -1,5 +1,8 @@ + [yolo_darknet 转 caffe](https://github.com/Ewenwan/MVision/blob/master/darknect/caffe/yolo_darknet_to_caffe.md) +[详细教程:window下安装Caffe深度学习框架!(同时安装pycaffe)](https://blog.csdn.net/weixin_37621229/article/details/80547934) + # caffe使用 [caffe 安装](https://github.com/Ewenwan/MVision/blob/master/darknect/caffe/caffe_%E5%AE%89%E8%A3%85.md) @@ -21,6 +24,10 @@ [Caffe使用教程_c++接口](https://github.com/Ewenwan/MVision/blob/master/darknect/caffe/Caffe%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B_c%2B%2B%E6%8E%A5%E5%8F%A3.md) +[caffe MobileNet-SSD Focal-loss ](https://github.com/Ewenwan/MobileNet-SSD-Focal-loss) + +[caffe 实现 MobileNet-YOLOv3 ](https://github.com/Ewenwan/MobileNet-YOLO) + [caffe 模型搜集](https://github.com/SnailTyan/caffe-model-zoo) ![screenshot](https://user-images.githubusercontent.com/21311442/33640664-cbcbeff2-da6c-11e7-97c8-1ad8d7fdf4c0.png) diff --git "a/darknect/caffe/\350\247\243\346\236\220\346\250\241\345\236\213.md" "b/darknect/caffe/\350\247\243\346\236\220\346\250\241\345\236\213.md" new file mode 100644 index 00000000..e11bcddb --- /dev/null +++ "b/darknect/caffe/\350\247\243\346\236\220\346\250\241\345\236\213.md" @@ -0,0 +1,29 @@ +# 解析模型 + +在网上看到了不少使用caffe python接口来编写生成prototxt文件的帖子,也找到了用protobuf的python接口读取caffemodel的方法,不过一直没看到用protobuf读prototxt的方法(我想要用caffe.proto解析,而不是用字符串直接读入)。由于我对protobuf不是很熟悉,想了半天,突然想起caffe提供了用prototxt绘制网络结构图的draw_net.py,既然根据prototxt绘制结构图,那么肯定要解析它,果然,实现步骤很简单,和读取caffemodel差不多。 + +```c + +from google.protobuf import text_format +import caffe.proto.caffe_pb2 as caffe_pb2 # 载入caffe.proto编译生成的caffe_pb2文件 +caffeprototxt_path = "yourpath/deploy.prototxt" +net = caffe_pb2.NetParameter() +text_format.Merge(open(caffeprototxt_path).read(), net) +print(net) +print(net.layer[0]) +print(net.layer[0].name) + +``` + + + +方法2 + +```c + +s_net=caffe.Net(xxx.prototxt, caffe.TEST) +for ly in s_net.layers: + print ly.type + + +``` diff --git a/darknect/keras/readme.md b/darknect/keras/readme.md new file mode 100644 index 00000000..b263392e --- /dev/null +++ b/darknect/keras/readme.md @@ -0,0 +1,64 @@ +# Keras 基于Python的深度学习库 + +[ Keras中文文档](https://keras-cn.readthedocs.io/en/latest/) + +[ Keras教程](https://github.com/cdlwhm1217096231/keras_tutorials) + + Keras是一个高层神经网络API,Keras由纯Python编写而成并基Tensorflow、Theano以及CNTK后端 + +[快速开始序贯(Sequential)模型](https://keras-cn.readthedocs.io/en/latest/getting_started/sequential_model/) + +[快速开始函数式(Functional)模型](https://keras-cn.readthedocs.io/en/latest/getting_started/functional_API/) + + +# 安装 + pip3 install tensorflow-gpu==1.8.0 + # Python语言用于数字图像处理 + # scikit-image 是基于scipy的一款图像处理包,它将图片作为numpy数组进行处理,正好与matlab一样 + pip3 install scikit-image + # Keras:基于Python的深度学习库 + # Keras是一个高层神经网络API,Keras由纯Python编写而成并基Tensorflow、Theano以及CNTK后端 + pip3 install keras +# 快速开始:30s上手Keras + + Keras的核心数据结构是“模型”,模型是一种组织网络层的方式。 + Keras中主要的模型是Sequential模型, + Sequential是一系列网络层按顺序构成的栈。 + 你也可以查看函数式模型来学习建立更复杂的模型 + + Sequential模型如下 + + from keras.models import Sequential + + model = Sequential() + + 将一些网络层通过.add()堆叠起来,就构成了一个模型: + from keras.layers import Dense, Activation + + model.add(Dense(units=64, input_dim=100)) + model.add(Activation("relu")) + model.add(Dense(units=10)) + model.add(Activation("softmax")) + + 完成模型的搭建后,我们需要使用.compile()方法来编译模型: + model.compile(loss='categorical_crossentropy', optimizer='sgd', metrics=['accuracy']) + + 编译模型时必须指明损失函数和优化器,如果你需要的话,也可以自己定制损失函数。 + Keras的一个核心理念就是简明易用,同时保证用户对Keras的绝对控制力度, + 用户可以根据自己的需要定制自己的模型、网络层,甚至修改源代码。 + + from keras.optimizers import SGD + model.compile(loss='categorical_crossentropy', optimizer=SGD(lr=0.01, momentum=0.9, nesterov=True)) + + 完成模型编译后,我们在训练数据上按batch进行一定次数的迭代来训练网络 + model.fit(x_train, y_train, epochs=5, batch_size=32) + 当然,我们也可以手动将一个个batch的数据送入网络中训练,这时候需要使用: + model.train_on_batch(x_batch, y_batch) + 随后,我们可以使用一行代码对我们的模型进行评估,看看模型的指标是否满足我们的要求: + loss_and_metrics = model.evaluate(x_test, y_test, batch_size=128) + 或者,我们可以使用我们的模型,对新的数据进行预测: + classes = model.predict(x_test, batch_size=128) + + + + diff --git a/darknect/readme.md b/darknect/readme.md index 3214922c..b0e7d567 100644 --- a/darknect/readme.md +++ b/darknect/readme.md @@ -1,10 +1,382 @@ -# yolo darknet +# 深度学习框架 人工智能操作系统 训练&前向推理 + +[AI嵌入式框架](https://github.com/Ewenwan/nortrom-notes/blob/master/system/ai_framework.md) + +OneFlow & 清华计图Jittor & 华为深度学习框架MindSpore & 旷视深度学习框架MegEngine(天元) & caffe & Google的TFBOYS & Facebook的Pytorch & XLA + +严格意义来说TVM和Jittor都不算深度学习框架,TVM和Jittor更多的是一套独立的深度学习编译器。我们可以将导出的模型文件通过TVM或者Jittor离线编译成一个Serving的模块,从而可以在云上或者端上部署模型的预测服务。 + +[华为 mindspore](https://github.com/Ewenwan/mindspore) + +[清华计图Jittor gt](https://github.com/Jittor/jittor/blob/master/README.cn.md) + +依赖: sudo apt install python3.7-dev libomp-dev pip3 install pybind11 numpy tqdm pillow astunparse six wheel + +pybind11使用问题 https://zhuanlan.zhihu.com/p/52619334 + +[旷视深度学习框架MegEngine gt](https://github.com/MegEngine/MegEngine) + +[模型可视化超好用的工具](https://github.com/lutzroeder/Netron) + +[使用自动代码生成技术TVM优化深度学习算子的一些思考](https://zhuanlan.zhihu.com/p/101026192) + +[基于ARM-v8的Tengine GEMM教程](https://github.com/Ewenwan/Tengine_gemm_tutorial) + + +## 深度学习编译器 + +[谈谈对深度学习编译技术的一些思考](https://zhuanlan.zhihu.com/p/87458316) + +深度学习编译器,一般是分两阶段优化,一个是high level optimization, 譬如在XLA里叫HLO, 这部分做硬件无关优化; 还有一个阶段是代码生成阶段,即codegen,和硬件体系结构相关。不同的编译器在这俩阶段的处理上各有所长。第一阶段的问题基本上被解决了,难的是第二阶段。 + +深度学习编译器的价值取决于AI芯片的前途。AI芯片上开发编译器的难度不高,基本上和在GPU上调用cublas, cudnn写程序差不多,因为基本的张量运算都用专用电路固化了,没啥可优化的(当然访存和计算做流水还是要做的),为某款AI芯片研发深度学习编译器,可能只需要关注第一阶段的问题(HLO),不需要解决第二阶段的问题(codegen)。如果对专用芯片上代码怎么写感兴趣,**可参照Glow, 它提供了一个为Habana 后端,这可能是唯一一个开源的AI芯片代码示例。** + +深度学习编译器的命运与AI芯片竞争格局息息相关,但我们并没有讨论AI芯片未来如何,这是另一个问题了,真正投入搞AI芯片的玩家对这个问题想的更清楚。 + +1、前端用DSL还是限定一个算子集合。XLA没有DSL,而是限定了一些基本算子,element-wise, map, reduce, broadcast, matmul 等等,蛮像函数式编程里面那些基本运算,用这些基本算子可以搭建起来tensorflow 里绝大多数更上层的算子,譬如batchnorm, softmax等。这么做当然限制了表示能力,但却给第二阶段codegen 带来极大便利,因为它只需要为这些限定的算子emit LLVM IR, 用固定的套路即可,相当于逃避了第二阶段优化那个难题。Glow实际上采用了和XLA相似的策略,对于第二步取了个巧,对于常见的矩阵运算算子提供了代码生成的模板,用模板并不意味着对不同的参数(譬如矩阵的长宽)都生成一样的代码。模板里面的参数是可调的,这样如果输入代码超参数不同,它也会针对不同的超参数做一些对应的优化。所以对于XLA和Glow可观赏的只有HLO这一层,这也是比较务实的做法,因为第二阶段优化太难了。**TVM,TC, Tiramisu, PlaidML使用了DSL**,这使得它们能表示的运算范围更广,当然也直面了第二阶段优化的挑战,这也是这些编译器出彩的地方,我们在下一个要点里讨论第二阶段优化。对第一阶段优化来说,XLA做的相当全面了,可能是最全面的。 + +2,剑宗还是气宗?在特定体系结构上自动生成最优代码,可以看出有俩套路,一个套路可以称之为剑宗,也好似一种自底向上的办法,即把专家手工优化代码的经验提炼出来,形成一些粗线条的rule(规则), 这是TVM的路线,也就是来自Halide的思路,那些rule称为schedule,Halide的最重要贡献是提出了问题表示方法,但没有解决自动化这个问题,当然自动化问题很困难。还有一个套路可称之为气宗,寻求一种高层次的数学抽象来描述和求解代码生成问题,这个代表就是TC, Tiramisu, MLIR等依赖的Polyhedral method(多面体方法)。 + +**深度学习编译器和传统编译器技术很不相同,它只解决一类特定问题,不去解决控制流问题,基本上是解决多重循环优化,也就是稠密计算问题。** + +Polyhedral method 是一种对多重循环程序的表示方法,问题表示出来之后,并不一定要借助isl求解。isl是什么?对一个比较复杂的cost model, 一个polyhedral 表示的计算,生成什么样的代码最优?这是一个离散解空间上的组合优化问题,有时可描述成整数线性规划,isl (integer set library)就是来求解这个问题的一个开源库。像TC, Tiramisu 用了isl, PlaidML和MLIR仅仅用了多面体表示却没有借助isl, 猜测:问题搜索空间太大时,isl 也不行。多面体方法只解决表示问题,不解决自动化问题。 + +用多面体与否实际上和前端是否用DSL也有关,用Polyhedral 的都用DSL, 表明多面体的表达能力和能求解的问题范围非常广,用DSL但不用Polyhedral 也有,譬如Halide, TVM, Tiramisu 作者对Halide表达能力有所批评,需要注意的是, Halide和Tiramisu 作者们其实是同一位MIT教授的学生,这是自己对自己的批评。 + +polyhedral 是近些年发展出来的最优雅的抽象方法,是并行编译领域的一种数学抽象,利用空间几何的仿射变换来实现循环优化。 + +Pluto是众多Polyhedral编译器中应用范围最广、最成功的编译器之一,以该编译器为平台实现的Pluto调度算法代表了Polyhedral model调度最先进的研究水平。Pluto编译器是一个很好的开发程序并行性和数据局部性的优化工具。 + +Pluto调度算法至今在众多领域包括将机器学习算法部署在特定加速部件等方面都发挥着重要作用。所以,Pluto编译器是一个很好的循环优化工具,也是研究Polyhedral model一个很好的平台。 Pluto编译器是一个从C程序到OpenMP的source-to-source编译器。 + +polyhedral compilation的研究内容分为依赖关系分析、调度变换和代码生成几个部分。当然,在做这些之前,polyhedral需要用一个parser来做解析,现在比较常用的parser是pet(“Polyhedral extraction tool”(IMPACT 2012))还有clan。polyhedral涉及到的工具及其链接大部分可以在polyhedral.info这个网站上找到。 + +现在的polyhedral研究大多被认为是由Feautrier针对数据流分析的工作“Dataflow analysis of array and scalar references”(IJPP 1991)奠基而来的。数据流分析的优势在于把依赖关系分析的粒度从语句细化到语句的实例,所以结果比传统的依赖关系分析结果更精确。但是在polyhedral里面的依赖关系分析,我并不会推荐去读这篇文章,因为这篇文章 比较难懂,我更推荐去看Pugh的“The Omega test: a fast and practical integer programming algorithm for dependence analysis”(ICS 1991)这篇文章,这篇文章对polyhedral的思维构建很有帮助。 + +依赖关系分为value-based和memory-based两种依赖关系,这个为polyhedral里面的scheduling算法在优化和正确性方面提供了很多支持。 + +现在大部分的polyhedral算法是Bondhugula的pluto算法“A practical automatic polyhedral parallelizer and locality optimizer”(PLDI 2008),这个算法是真正让polyhedral前后贯通的一个scheduling算法。如果对scheduling算法感兴趣,我会建议去阅读pluto算法或者Bondhugula的博士论文“Effective Automatic Parallelization and Locality Optimization using the Polyhedral Model”,这个算法也是Pluto编译器的核心。Bondhugula对scheduling算法后续做了许多优化和提升例如Pluto+,这部分可以参考他的个人主页。 + +polyhedral的代码生成工具主要有CodeGen+,“Code generation for multiple mappings”(Frontiers 1995)和CLooG,“Code generation in the polyhedral model is easier than you think”(PACT 2004)两个工具。CodeGen+部分主要是在Omega库里使用,而CLooG和CodeGen+的代码生成方式有一些不同。这两篇文章都值得去看一下,了解一下如何生成代码。不过,“Polyhedral AST generation is more than scanning polyhedra”(TOPLAS 2015)这篇文章我建议对AST生成部分有兴趣的话可以仔细阅读一下,这个长达50页的文章系统地介绍了如何生成循环的边界、控制流条件语句还有避免代码膨胀等问题。 + + + +> **深度学习编译优化技术与手工优化的对比** + +深度学习编译优化与手工优化并不是互斥关系,而是互补关系。在一个完整的系统里,应该既有深度学习编译优化,也有手工优化,让各自解决其适合解的问题。 + +1). 编译优化适合解决给定策略,涉及较多routine性质tedious work的问题。比如我们知道loop unrolling会可能带来性能收益是一个策略问题,但是按什么样的strides来unroll,是一个trial-and error的问题。以及我们都知道对于GEMM进行分tile计算可以提升计算访存比,这是一个策略问题,但是给定一款硬件,按什么尺寸,在什么维度上分tile则是一个trial-and-error的问题。这类问题,适合采取编译优化的手段来解,也往往是编译优化能够在生产效率上显著优于手工优化的地方; + +2). 手工优化适合那种不容易精确形式化描述成一个清晰策略,带有一定非逻辑思维的直觉性质(由我们认识规律的能力水平决定)的问题,往往涉及到全局性质优化的问题具备这种性质。比如最近我们针对TensorCore在进行手工优化,会在访存pattern上进行精细的优化,以期最大可能将计算与访存overlap,就会发现涉及到精细的访存排布,至少基于目前我们对TVM schedule描述的理解,如果只是基于TVM显式提供的schedule,不去手写TVM IR,是不容易表达出来的。实际上TVM在设计上提供了Tensorize/intrinsics的接口,也是在一定程度上需要将手工优化的经验嵌入到优化流程里,但也并不是所有的手工优化都可以基于目前的tensorize/intrinsics机制来完成扩充的。 + +3).手工优化是可能向编译优化迁移的。比如通过扩展编译引擎的内核,来加入对应的支持。比如我们最近在TVM社区里针对NV GPU TensorCore提供了基于graph/IR pass/codegen模块改造的作法,能够做到用户完全无感,自动完成TensorCore kernel优化生成的效果,而社区的另一个相关工作作法则是需要显式提供TensorCore相关intrinsics的描述,将一部分工作offload到用户层。这算是一个手工优化,向编译优化层次迁移的示例。 + +4).总会有些优化在编译优化层面完成会存在事倍功半的效果,这类优化我们就应该考虑either是通过手工优化扩充,或是通过提供pre-defined library,甚至runtime强化的方式来进行协同优化,而不是什么优化都往编译层面压。反过来也一样。手工优化可以在极限场景下找到非常精细的性能优化空间,但是并不是所有的手工优化所探索的性能空间都复杂精细到编译优化不能支持的程度。找到不同技术适合的土壤就好。之前跟NV的同学沟通,他们针对TensorCore kernel的支持,考虑采取设计若干个小的recipe,recipe提供可定制的可能,再进行拼装组合来实现不同尺寸的GEMM kernel,这种作法,包括CUTLASS的设计思想,在我看来,都具备了一定的将手工优化的经验向编译优化层次转移的味道,只是程度不同而已。 + +对于AI芯片来说,已经以后专门的硬件架构来解决ai中常见的计算密集型算子,GPU虽然有一定通用性没有完全硬件化,但TensorCore的出现也使它未来可能有这方面的趋势,这样来说软件编译器在这里能做的事情应该是有限的;可能“主要开销都不是计算密集型算子”,数据搬运非常关键。 + + +## 深度学习框架简述 + +深度学习框架发展到今天,目前在架构上大体已经基本上成熟并且逐渐趋同。无论是国外的Tensorflow、PyTorch,亦或是国内最近开源的MegEngine、MindSpore,目前基本上都是支持EagerMode和GraphMode两种模式。 + +> Tensorflow + +Google的Tensorflow最早是按照GraphMode来设计的,GraphMode是系统同学比较偏爱的一个架构。用户通过申明式的API来定义好模型,然后后面具体的优化、执行都交给后端的系统。由于系统能够一次能够拿到整个执行的Graph,因此系统同学便有足够的空间对系统做各种优化。比如在Tensorflow里面,我们可以做各种类型的优化,包括Placement的优化、图优化(Grappler)、内存优化、分布式优化等。不过GraphMode有一个弊端,就是模型调试。许多使用Tensorflow的算法同学对于运行过程中遇到的各种千奇百怪的问题都感到束手无策。不过需要说的是,从Tensorflow上来看的话Google在整个AI系统领域的布局是最完善的,从底层的芯片(推理、训练、端)、到深度学习框架(Tensorflow、、XLA),再到模型部署(TF Serving、TFLite),最后再到TF的训练链路(TFX、TF.js、Tensorboard、federated)。从这些布局来看,整个Tensorflow的设计完全体现出了Google的系统深度,并完全引领了整个AI系统。 + +> PyTorch + +PyTorch从一开始就是按照EagerMode来进行架构实现。和Tensorflow v1.0对比,PyTorch非常灵活,对于开发者极其友好。因此,在开发者社区上PyTorch很快就逼近了Tensorflow,从最近两年的论文应用上我们也能看到PyTorch的引用数和Tensorflow越来越接近。从这个角度来看会给人一个感觉就是Tensorflow起了个大早赶了个晚集。我们也能看到Tensorflow也在2.0里面也开始支持EagerMode并将EagerMode设置为默认的运行模式,希望能够补齐易用性这个短板。不过其实对于Tensorflow而言转型支持EagerMode其实不容易。就像前面说道的,Tensorflow自身的架构是完全按照GraphMode来设计的,因此为了支持EagerMode,Tensorflow自身的改动也是很痛苦,从Tensorflow的代码来看许多地方都加入了if(eager_mode)这样的判断条件。不过PyTorch也不是完美无缺。对于PyTorch的开发者而言,PyTorch模型的Deployment过程是一个痛苦的过程。这也是在工业界Tensorflow相比较PyTorch更受欢迎的一个重要原因。 + +> 华为MindSpore + +华为在国内是一个很值得尊敬的企业。可以这么说,华为在IT这个领域是整体上部署最完善的公司。这些领域包括了云计算最底层的网络、存储、服务器、芯片,也包括了上层的编译器、高斯数据库。在深度学习这个领域,华为可以说布局也比较完整,比如Asend芯片(训练、推理)、最近刚开源的深度学习框架MindSpore。对于一家企业而言,布局这些领域都是需要极大的决心。不过企业布局这些领域也不是为了开发而开发,为了自研而自研。对于企业而言,布局这些领域最终肯定是希望能够在商业上带来相应的回报。(开源社区与华为共成长) + +从MindSpore这个框架的架构来看,MindSpore的架构和目前已有引擎的架构比较相似,整体执行也都是基于自动微分进行的设计。这个也比较合理。另外,整个框架从上往下依次是Python的DSL层、中间的Graph优化层以及底下的执行层。这个架构也是目前主流的引擎的相似的架构。此外,由于有了后发的优势,MindSpore应该是在设计之初就考虑了如何兼具EagerMode和GraphMode两种执行方式,这样就可以同时兼具易用性和高性能。在底层不同设备的支持上,我们也能够看到MindSpore支持了包括CPU,GPU加速器,当然最重要的还是自家的Ascend芯片。 + +> 自动并行 Auto Parallel + +MindSpore里面我觉得一个比较大的亮点也是他们在文档里面强调的一个就是自动并行的训练能力。自动并行是一个在其他领域研究的比较多的方向,比如在大数据领域对于用户写的一条SQL语句我们能够在优化器内部自动生成一个相对较优的执行计划,从而生成一个自动并行的Mapper-Reduce任务。在深度学习这个领域也存在这个问题,那就是如何将用户的模型最大高效的并行执行。 + +在深度学习这个领域存在多种并行的范式,比如数据并行(Data Paralle),模型并行(Model Parallel),混合并行(Hybrid Parallel)等。目前在深度学习分布式执行这个领域应用最多的还是数据并行,也就是Data Parallel。业内多个框架,比如Horovod,Tensorflow的DistributeStrategy,PyTorch的DDP,这些都是数据并行的分布式框架。数据并行就是将模型在多个设备上进行复制并行训练,同时基于NCCL进行梯度同步,从而达到分布式执行的效果。数据并行这个架构比较简洁,模型构建也比较清晰,因此目前绝大部分任务都是采用数据并行的训练方式。 + +MindSpore里面也支持基本的数据并行能力。不过从MindSpore里面他着重强调的是自动并行。这里的自动并行是指从众多的并行可能性里面搜寻出一种最优的并行执行方式,比如将部分算子进行自动拆分从而达到一个比较好的并行效果。从下面的图里面我们能够看到MindSpore的自动并行是基于一个Cost Model来进行并行策略的评估。通过Cost Model,我们可以对不同的并行策略进行评估,从而可以选择一个cost最小的并行策略。在Cost Model里面,我们通常会对通信的cost、计算的cost、算子拆分的cost等进行评估。并行策略的搜寻算法在MindSpore里面我们看到使用了动态规划(dynamic programming)和递归算法(recursive programming)。 + +> 自动并行的挑战 + +对于自动并行而言,最大的挑战是如何寻优到最佳的并行策略。对于常见的数据并行而言,我们只需要将模型副本分布到不同的设备上,选择合适的时间对梯度进行AllReduce即可。对于自动并行,我们需要考虑不同的通信拓扑(比如以太网、NVLink、多网卡设备)、算子拆分(Layer间拆分、Layer内拆分)、设备算力、流水并行、算子计算依赖、显存大小、通信成本(Weight,Activation等)等众多维度。Google有一个项目,Mesh-Tensorflow,目前是提供了相应算子的拆分机制。算法同学可以自由的在不同的维度(Batch维度、NCHW四个维度、Matmul维度等)进行拆分。在MindSpore里面我们也看到也提供了类似的拆分能力,在MindSpore源代码里面我们看到了支持算子的定义,不过相应拆分的能力目前没有看到可以让用户来指定。 + +# AI通用框架 + +## caffe + +* concept + * top & bottom + * forward: bottom -> top + * backward: top -> bottom +* usage + * check caffe proto + * [Netscope Editor](http://ethereon.github.io/netscope/#/editor) + * set weight init method + * see include/caffe/filler.hpp + * iter_size + * You can change the iter_size in the solver parameters. Caffe accumulates gradients over **iter_size x batch_size** instances in each stochastic gradient descent step. So increasing iter_size can also get more stable gradient when you cannot use large batch_size due to the limited memory. + * test_iter + * how many iterations to be executed for a test loop(each iteration calculate a batch of test image) + * test_interval + * how often a test is executed, test_interval iterations(each iteration calculate a batch of train image) + * epoch + * iteration number needs to iterate all train image number = train image num / batch size + * lr_policy + * learning rate policy, usually set to "step" + * fixed:   保持base_lr不变. + * step:    如果设置为step,则还需要设置一个stepsize, 返回base_lr \* gamma ^ (floor(iter / stepsize)),其中iter表示当前的迭代次数 + * exp:   返回base_lr \* gamma ^ iter, iter为当前迭代次数 + * inv:   如果设置为inv,还需要设置一个power, 返回base_lr \* (1 + gamma \* iter) ^ (- power)- multistep: 如果设置为multistep,则还需要设置一个stepvalue。这个参数和step很相似,step是均匀等间隔变化,而multistep则是根据 stepvalue值变化 + * poly:    学习率进行多项式误差, 返回 base_lr (1 - iter/max_iter) ^ (power)- sigmoid: 学习率进行sigmod衰减,返回 base_lr ( 1/(1 + exp(-gamma \* (iter - stepsize)))) + * display + * show loss/lr in console in each 'display' iterations +* layer + * power + * 输入1 featuremap,输出1 featuremap + * eltwise级操作 + * 计算:$(shift + scale * x)^{power}$ + * scale + * 输入2 featuremap,输出1 featuremap + * 输入1:$n*c*h*w$,输入2:$n*c*1*1$ + * 计算:输入2h&w维度平铺展开,与输入1 eltwise prod + * permute + * 输入1 featuremap,输出1 featuremap + * 交换caffe_blob中数据的维度,下面参数将$n*c*h*w$-->$c*n*h*w$ + + ``` + permute_param { + order: 1 + order: 0 + order: 2 + order: 3 + } + ``` + + * reshape + * 输入1 featuremap,输出1 featuremap + * 只改变输入数据的维度表示,内容不变 + * dim的参数0:表示维度不变,x:表示将原来维度变化为x,-1:表示自动推算剩下维度 + * 比如下面的参数将32x3x28x28变换为32x3x14x56 + + ``` + shape { + dim: 0 # 32 --> 32 + dim: 0 # 3 --> 3 + dim: 14 # 28 --> 14 + dim: -1 # deduce 28 --> 56 + } + ``` + + * flatten + * 输入1 featuremap,输出1 featuremap + * 只改变输入数据的维度表示,内容不变,将数据拉成一维向量 + * $n*c*h*w$-->$n*1*1*(chw)$ +* proto + * 简介 + * protobuf是一种轻便高效的结构化数据存储格式。 + * 包含proto文件,prototxt,protoc编译器。 + * prototxt文件是结构化数据按照proto文件定义的格式序列化后的文本文件。 + * caffe.proto + * 在caffe编译过程中,protoc编译器编译caffe.proto得到caffe.pb.cc和caffe.pb.h,包含了所有消息类型的序列化和反序列化接口。 + +## tensorflow + +* 简介 + * 2015.11 +* 机制 + * 计算图(静态图) + * 声明式编程(declarative programming),不兼容python自身语法体系,无法实时调试和打印,甚至无法使用python自带的if-else和while控制语句。 + * 基于静态图进行了深入的优化,但牺牲了灵活性。 +* 静态图优化范畴 + * 算子融合、内存复用、计算划分、即时编译 +* 基本概念 + * Graph: 计算图 + * Node: 包含计算节点和数据节点,类似于caffe中的layer概念 + * Tensor: 实际数据的表示形式,在计算图中为节点和节点的连接 + * Session: 会话,为整个计算图的计算提供上下文,包括GPU配置信息等 + * meta:计算图结构文件 + * ckpt:模型参数文件 +* 常见问题 + * 为什么tensorflow必须使用特定域语言描述计算图? + * 对计算性能的极致要求,需要完善的数值库,非常低的编译开销,很高的硬件支持,这是python无法提供的。 + * 为什么tensorflow的静态图有这么大的局限性? + * 因为静态图对计算类型有预设,目前的计算图中仅对有向无环图支持友好,一旦出现条件分支、循环、递归、以及模型大小取决于输入规模等(word2vec),就会给框架带来巨大挑战 + * 为什么tensorflow的特定域语言图灵完备? + * 因为其包含tf.cond和tf.while_loop + + +## pytorch + +* 简介 + * 2016.10 +* 机制 + * 计算图(动态图) + * 命令式编程(imperative programming),数据实时计算,支持实时调试,和python语法完全兼容 + * 保证灵活性但部分程度上牺牲运行时性能 + +## mindspore + +* 机制 + * 张量加速引擎(TBE) + * 介绍:用张量加速引擎语言编写TBE算子,构建各种神经网络模型 + * 模块:特定域语言(DSL)模块;调度模块;中间表达模块;编译器传递模块;代码生成模块(本人预测仅该部分为昇腾实现,前4个模块均复用TVM框架) + * 应用场景 + * TBE标准算子库 + * TBE自定义算子(自定义计算) + * TBE算子融合 + * TVM&引擎关联 + * 昇腾构建TVM lowerIR与芯片代码间的关联,用户根据场景搜索出合适的代码实现。(参见昇腾AI处理器架构与实现P178) + * DSL--> Deep Learning IR --> LLVM IR --> Target(参见昇腾AI处理器架构与实现P163) + * 离线模型生成器 + * 需预先确定模型输入维度和对应的内存大小 + * 独立于硬件的算子融合优化及内存复用优化 + +## 比较 + +||图类型|序列化方式|模型| +|---|---|---|---| +|caffe|静态|prototxt(protobuf)|.caffemodel| +|tensorflow|静态(eager动态)|meta|.ckpt| +|pytorch|动态(jit静态)||.pth| +|mindspore|静态+动态||.ms| + +* 深度学习编译栈比较 + * TensorRT + * 只关注模型在GPU架构上的推理性能 + * tensorflow XLA + * 使用LLVM中间表示来描述各个算子,能复用LLVM的一系列前端优化手段 + * Tensor Comprehensions + * 使用Halide中间表示来描述底层计算,通过各种编译器理论中的优化方法,针对特定硬件架构对底层的计算循环进行变换和优化 + * TVM + * 图级别中间表示NNVM和Relay,Halide中间表示作为下层的计算支撑,AutoTVM提供搜索算法针对特定硬件架构找到最优方案。 + +## 推理优化 + +* 基本优化方法 + * 优化内存 + * 多次推理复用同一片存储区域 + * 共享输出层的内存合并,共享输入层的内存复用 + * 优化计算效率 + * 多batch(补零,启动时间,调度时间开销较大) +* 融合 + * 算子融合 + * 常量运算预计算(batchnorm) + * 公共子表达式消除(fused-conv-bn-relu,又称CBR) + * 子图融合(多个共享相同输入和参数规模的CBR融合) +* 计算优化 + * 计算模型优化 + * FFT + * winograd + * 计算效率优化 + * 循环展开,矩阵分块 + * 存储顺序优化(NCkHWK,NC4HW4,NHWC) + * 专用内核 + +## 其他概念 + +* 网络格式转换 + * ONNX(开发网络交换格式) + * MMdnn +* 编译器堆栈(compiler stack) + * 深度学习推理引擎完成了不同深度学习框架下的模型到不同硬件平台的端到端任务,类似于编译器完成不同编译器到不同平台的任务,所以被称作为编译器堆栈。 + +# AI集群框架 +## 涉及的问题 + +* 数据传输带宽 + * 单机内传输 + * PCI-E,NVLINK + * 多机间传输 + * 以太网,Inifiniband,Omini-Patch Architecture +* 文件读写带宽 + * 随机读写-IOPS,大文件读写-带宽 + * 介质:HDA,SSD,3d xpoint + * refer [storage performance](./system.md#performance) +* 并行方案 + * 方案 + * 数据并行:计算节点单独进行前向与反向运算,梯度规约之后进行更新 + * 模型并行:不同的计算节点负责网络的一部分运算 + * 混合并行:数据并行+模型并行 + * 常用策略 + * 由于数据并行虽然加速明显,但需要节点间数据传输;因此计算密集型操作可数据并行,数据密集型操作可模型并行。比如conv适合数据并行,fc适合模型并行 + +# 大数据框架 + +* 分布式计算框架 + * MapReduce:离线批处理框架 + * Tez:DAG计算框架 + * Spark:迭代/内存计算框架 + * Storm:实时流计算框架 +* 技术支撑 + * 一致性算法:Paxos + * 分布式协同:Apache Zookeeper & Google Chubby + * 分布式存储:HDFS & HBase +* 概念 + * yarn:Yet Another Resource Negotiator,一种新的 Hadoop 资源管理器 + * spark工作模式:单机/standalone/yarn + * 流式API: + * 流水线式处理数据,处理类型为函数式编程中常见的map/sort/reduce/filter等操作 + * 举例 + ```java + List threeHighCaloricDishNames = + menu.stream()//从menu获得流 + .filter(d -> d.getCalories() > 300)//筛选热量大于300的 + .map(Dish::getName)//只需要名称 + .limit(3)//限制取3个元素 + .collect(toList());//保存结果到List + System.out.println(threeHighCaloricDishNames); + ``` + + +# 开发深度学习框架的知识架构 + +1,熟悉常见深度学习模型,CNN, GAN, RNN/LSTM, BERT, Transformer; + +2,熟悉后向误差传播算法(BP),完成从标量求导到矩阵求导思维方式的转换,熟悉常见算子的梯度推导(矩阵乘,卷积, 池化,Relu,如果会batch normalization 就一步到位了); + +3,熟悉autograd的基本原理,能自己手撸一个最好; + +4,熟悉cuda编程(举一反三),熟悉cuda高阶用法,event, stream, 异步/同步,会优化常见cuda kernel, element-wise, reduce, broadcast, MatMul, conv, pooling 等; + +5,熟悉c++和python, 对c++高级用法感到舒服,各种模式,惯用法,模板;熟悉vim, gdb 程序调试; + +6,熟悉socket, RDMA编程,熟悉常见collective operation代价分析,譬如ring allreduce, tree allreduce 代价分析; + +7,熟悉多线程编程,熟悉锁,条件变量,内核线程,用户级线程,对actor, CSP(coroutine)各种技术熟悉; + +8,熟悉编译器基本原理,parser什么的不重要,主要是dataflow分析,灵活运用;熟悉多重循环程序优化技巧,譬如polyhedral 模型; + +9,熟悉常见分布式系统原理,mapreduce, spark, flink, tensorflow 等; + +10,熟悉计算机体系机构,量化分析方法,Amdahl' Law, Roofline Model, 流水线分析(譬如David Patterson 那本书); + +11,熟悉操作系统原理及常用系统诊断工具,譬如各种资源利用率分析; + +12,programming language 原理,命令式编程,函数式编程,逻辑编程,入门书《程序的构造与解释》? + +13,熟悉项目构建原理,compiler, assembler, linker, loader之类,有一本书《程序员的自我修养》有比较全面覆盖。 + +[编译器书籍 现代体系结构的优化编译器 高级编译器设计与实现](https://github.com/Ewenwan/compilerbook) + +# 目标检测 yolov3相关 darknet框架 + +[YOLO_v3 TF 加强版 GN FC DA ](https://github.com/Stinky-Tofu/YOLO_V3) + +[caffe 实现 MobileNet-YOLOv3 ](https://github.com/Ewenwan/MobileNet-YOLO) + +[Translate darknet to tensorflow darkflow](https://github.com/thtrieu/darkflow) [FOR Raspberry Pi 3 ](https://github.com/digitalbrain79/darknet-nnpack) [基于YOLO的3D目标检测:YOLO-6D bounding box在2D图像上的投影的1个中心点和8个角点 + 置信度 + 类别C](https://zhuanlan.zhihu.com/p/41790888) - +[yolov1 赛灵思(Xilinx) ZCU102 SoC 16bit量化 x86 / ARM NEON优化加速](https://github.com/Ewenwan/YOLO_quantize) * YOLO-v1 论文翻译 [You Only Look Once: Unified, Real-Time Object Detection](https://arxiv.org/abs/1506.02640) @@ -16,8 +388,9 @@ [中文版](http://noahsnail.com/2017/12/26/2017-12-26-YOLO9000,%20Better,%20Faster,%20Stronger%E8%AE%BA%E6%96%87%E7%BF%BB%E8%AF%91%E2%80%94%E2%80%94%E4%B8%AD%E6%96%87%E7%89%88/) [中英文对照](http://noahsnail.com/2017/12/26/2017-12-26-YOLO9000,%20Better,%20Faster,%20Stronger%E8%AE%BA%E6%96%87%E7%BF%BB%E8%AF%91%E2%80%94%E2%80%94%E4%B8%AD%E8%8B%B1%E6%96%87%E5%AF%B9%E7%85%A7/) +[自动标注图片工具 A self automatically labeling tool ](https://github.com/eric612/AutoLabelImg) - ## 0.项目主页 +## 0. darknet 项目主页 [darknet yolov3](https://pjreddie.com/darknet/yolo/) [darknet yolov3 from scratch in PyTorch 详细](https://blog.paperspace.com/how-to-implement-a-yolo-object-detector-in-pytorch/) diff --git "a/darknect/tensorflow/TensorFlow\345\206\205\346\240\270\345\211\226\346\236\220.pdf" "b/darknect/tensorflow/TensorFlow\345\206\205\346\240\270\345\211\226\346\236\220.pdf" new file mode 100644 index 00000000..bdc64fa0 Binary files /dev/null and "b/darknect/tensorflow/TensorFlow\345\206\205\346\240\270\345\211\226\346\236\220.pdf" differ diff --git a/darknect/tensorflow/awesome-tensorflow.md b/darknect/tensorflow/awesome-tensorflow.md new file mode 100644 index 00000000..117938b8 --- /dev/null +++ b/darknect/tensorflow/awesome-tensorflow.md @@ -0,0 +1,251 @@ +# Awesome TensorFlow [![Awesome](https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg)](https://github.com/jtoy/awesome) + +A curated list of awesome TensorFlow experiments, libraries, and projects. Inspired by awesome-machine-learning. + +[参考](https://github.com/Ewenwan/awesome-tensorflow) + +## 简介 + +TensorFlow is an open source software library for numerical computation using data flow graphs. In other words, the best way to build deep learning models. + +More info [here](http://tensorflow.org). + + + +## Table of Contents + + +- [Tutorials](#github-tutorials) +- [Models/Projects](#github-projects) +- [Powered by TensorFlow](#github-powered-by) +- [Libraries](#libraries) +- [Videos](#video) +- [Papers](#papers) +- [Blog posts](#blogs) +- [Community](#community) +- [Books](#books) + + + + + + +## Tutorials + +* [TensorFlow Tutorial 1](https://github.com/pkmital/tensorflow_tutorials) - From the basics to slightly more interesting applications of TensorFlow +* [TensorFlow Tutorial 2](https://github.com/nlintz/TensorFlow-Tutorials) - Introduction to deep learning based on Google's TensorFlow framework. These tutorials are direct ports of Newmu's Theano +* [TensorFlow Tutorial 3](https://github.com/Hvass-Labs/TensorFlow-Tutorials) - These tutorials are intended for beginners in Deep Learning and TensorFlow with well-documented code and YouTube videos. +* [TensorFlow Examples](https://github.com/aymericdamien/TensorFlow-Examples) - TensorFlow tutorials and code examples for beginners +* [Sungjoon's TensorFlow-101](https://github.com/sjchoi86/Tensorflow-101) - TensorFlow tutorials written in Python with Jupyter Notebook +* [Terry Um’s TensorFlow Exercises](https://github.com/terryum/TensorFlow_Exercises) - Re-create the codes from other TensorFlow examples +* [Installing TensorFlow on Raspberry Pi 3](https://github.com/samjabrahams/tensorflow-on-raspberry-pi) - TensorFlow compiled and running properly on the Raspberry Pi +* [Classification on time series](https://github.com/guillaume-chevalier/LSTM-Human-Activity-Recognition) - Recurrent Neural Network classification in TensorFlow with LSTM on cellphone sensor data +* [Getting Started with TensorFlow on Android](https://omid.al/posts/2017-02-20-Tutorial-Build-Your-First-Tensorflow-Android-App.html) - Build your first TensorFlow Android app +* [Predict time series](https://github.com/guillaume-chevalier/seq2seq-signal-prediction) - Learn to use a seq2seq model on simple datasets as an introduction to the vast array of possibilities that this architecture offers +* [Single Image Random Dot Stereograms](https://github.com/Mazecreator/TensorFlow-SIRDS) - SIRDS is a means to present 3D data in a 2D image. It allows for scientific data display of a waterfall type plot with no hidden lines due to perspective. +* [CS20 SI: TensorFlow for DeepLearning Research](http://web.stanford.edu/class/cs20si/syllabus.html) - Stanford Course about Tensorflow from 2017 - [Syllabus](http://web.stanford.edu/class/cs20si/syllabus.html) - [Unofficial Videos](https://youtu.be/g-EvyKpZjmQ?list=PLSPPwKHXGS2110rEaNH7amFGmaD5hsObs) +* [TensorFlow World](https://github.com/astorfi/TensorFlow-World) - Concise and ready-to-use TensorFlow tutorials with detailed documentation are provided. +* [Effective Tensorflow](https://github.com/vahidk/EffectiveTensorflow) - TensorFlow howtos and best practices. Covers the basics as well as advanced topics. +* [TensorLayer](http://tensorlayer.readthedocs.io/en/latest/user/tutorial.html) - Modular implementation for TensorFlow's official tutorials. ([CN](https://tensorlayercn.readthedocs.io/zh/latest/user/tutorial.html)). + + + +## Models/Projects + +* [SenseNet](https://github.com/jtoy/sensenetjey/dtn-tensorflow) - Robotics touch model with TensorFlow DQN example +* [Tensorflow-Project-Template](https://github.com/Mrgemy95/Tensorflow-Project-Template) - A simple and well-designed template for your tensorflow project. +* [Domain Transfer Network](https://github.com/yunjey/dtn-tensorflow) - Implementation of Unsupervised Cross-Domain Image Generation +* [Show, Attend and Tell](https://github.com/yunjey/show_attend_and_tell) - Attention Based Image Caption Generator +* [Neural Style](https://github.com/cysmith/neural-style-tf) Implementation of Neural Style +* [SRGAN](https://github.com/tensorlayer/srgan) - Photo-Realistic Single Image Super-Resolution Using a Generative Adversarial Network +* [Pretty Tensor](https://github.com/google/prettytensor) - Pretty Tensor provides a high level builder API +* [Neural Style](https://github.com/anishathalye/neural-style) - An implementation of neural style +* [AlexNet3D](https://github.com/denti/AlexNet3D) - An implementations of AlexNet3D. Simple AlexNet model but with 3D convolutional layers (conv3d). +* [TensorFlow White Paper Notes](https://github.com/samjabrahams/tensorflow-white-paper-notes) - Annotated notes and summaries of the TensorFlow white paper, along with SVG figures and links to documentation +* [NeuralArt](https://github.com/ckmarkoh/neuralart_tensorflow) - Implementation of A Neural Algorithm of Artistic Style +* [Deep-Q learning Pong with TensorFlow and PyGame](http://www.danielslater.net/2016/03/deep-q-learning-pong-with-tensorflow.html) +* [Generative Handwriting Demo using TensorFlow](https://github.com/hardmaru/write-rnn-tensorflow) - An attempt to implement the random handwriting generation portion of Alex Graves' paper +* [Neural Turing Machine in TensorFlow](https://github.com/carpedm20/NTM-tensorflow) - implementation of Neural Turing Machine +* [GoogleNet Convolutional Neural Network Groups Movie Scenes By Setting](https://github.com/agermanidis/thingscoop) - Search, filter, and describe videos based on objects, places, and other things that appear in them +* [Neural machine translation between the writings of Shakespeare and modern English using TensorFlow](https://github.com/tokestermw/tensorflow-shakespeare) - This performs a monolingual translation, going from modern English to Shakespeare and vice-versa. +* [Chatbot](https://github.com/Conchylicultor/DeepQA) - Implementation of ["A neural conversational model"](http://arxiv.org/abs/1506.05869) +* [Seq2seq-Chatbot](https://github.com/tensorlayer/seq2seq-chatbot) - Chatbot in 200 lines of code +* [DCGAN](https://github.com/tensorlayer/dcgan) - Deep Convolutional Generative Adversarial Networks +* [GAN-CLS](https://github.com/zsdonghao/text-to-image) -Generative Adversarial Text to Image Synthesis +* [im2im](https://github.com/zsdonghao/Unsup-Im2Im) - Unsupervised Image to Image Translation with Generative Adversarial Networks +* [Improved CycleGAN](https://github.com/luoxier/CycleGAN_Tensorlayer) - Unpaired Image to Image Translation +* [DAGAN](https://github.com/nebulaV/DAGAN) - Fast Compressed Sensing MRI Reconstruction +* [Colornet - Neural Network to colorize grayscale images](https://github.com/pavelgonchar/colornet) - Neural Network to colorize grayscale images +* [Neural Caption Generator](https://github.com/jazzsaxmafia/show_attend_and_tell.tensorflow) - Implementation of ["Show and Tell"](http://arxiv.org/abs/1411.4555) +* [Neural Caption Generator with Attention](https://github.com/jazzsaxmafia/show_attend_and_tell.tensorflow) - Implementation of ["Show, Attend and Tell"](http://arxiv.org/abs/1502.03044) +* [Weakly_detector](https://github.com/jazzsaxmafia/Weakly_detector) - Implementation of ["Learning Deep Features for Discriminative Localization"](http://cnnlocalization.csail.mit.edu/) +* [Dynamic Capacity Networks](https://github.com/jazzsaxmafia/dcn.tf) - Implementation of ["Dynamic Capacity Networks"](http://arxiv.org/abs/1511.07838) +* [HMM in TensorFlow](https://github.com/dwiel/tensorflow_hmm) - Implementation of viterbi and forward/backward algorithms for HMM +* [DeepOSM](https://github.com/trailbehind/DeepOSM) - Train TensorFlow neural nets with OpenStreetMap features and satellite imagery. +* [DQN-tensorflow](https://github.com/devsisters/DQN-tensorflow) - TensorFlow implementation of DeepMind's 'Human-Level Control through Deep Reinforcement Learning' with OpenAI Gym by Devsisters.com +* [Policy Gradient](https://github.com/zsdonghao/tensorlayer/blob/master/example/tutorial_atari_pong.py) - For Playing Atari Ping Pong +* [Deep Q-Network](https://github.com/zsdonghao/tensorlayer/blob/master/example/tutorial_frozenlake_dqn.py) - For Playing Frozen Lake Game +* [AC](https://github.com/zsdonghao/tensorlayer/blob/master/example/tutorial_cartpole_ac.py) - Actor Critic for Playing Discrete Action space Game (Cartpole) +* [A3C](https://github.com/zsdonghao/tensorlayer/blob/master/example/tutorial_bipedalwalker_a3c_continuous_action.py) - Asynchronous Advantage Actor Critic (A3C) for Continuous Action Space (Bipedal Walker) +* [DAGGER](https://github.com/zsdonghao/Imitation-Learning-Dagger-Torcs) - For Playing [Gym Torcs](https://github.com/ugo-nama-kun/gym_torcs) +* [TRPO](https://github.com/jjkke88/RL_toolbox) - For Continuous and Discrete Action Space by +* [Highway Network](https://github.com/fomorians/highway-cnn) - TensorFlow implementation of ["Training Very Deep Networks"](http://arxiv.org/abs/1507.06228) with a [blog post](https://medium.com/jim-fleming/highway-networks-with-tensorflow-1e6dfa667daa#.ndicn1i27) +* [Sentence Classification with CNN](https://github.com/dennybritz/cnn-text-classification-tf) - TensorFlow implementation of ["Convolutional Neural Networks for Sentence Classification"](http://arxiv.org/abs/1408.5882) with a [blog post](http://www.wildml.com/2015/12/implementing-a-cnn-for-text-classification-in-tensorflow/) +* [End-To-End Memory Networks](https://github.com/domluna/memn2n) - Implementation of [End-To-End Memory Networks](http://arxiv.org/abs/1503.08895) +* [Character-Aware Neural Language Models](https://github.com/carpedm20/lstm-char-cnn-tensorflow) - TensorFlow implementation of [Character-Aware Neural Language Models](http://arxiv.org/abs/1508.06615) +* [YOLO TensorFlow ++](https://github.com/thtrieu/yolotf) - TensorFlow implementation of 'YOLO: Real-Time Object Detection', with training and an actual support for real-time running on mobile devices. +* [Wavenet](https://github.com/ibab/tensorflow-wavenet) - This is a TensorFlow implementation of the [WaveNet generative neural network architecture](https://deepmind.com/blog/wavenet-generative-model-raw-audio/) for audio generation. +* [Mnemonic Descent Method](https://github.com/trigeorgis/mdm) - Tensorflow implementation of ["Mnemonic Descent Method: A recurrent process applied for end-to-end face alignment"](http://ibug.doc.ic.ac.uk/media/uploads/documents/trigeorgis2016mnemonic.pdf) +* [CNN visualization using Tensorflow](https://github.com/InFoCusp/tf_cnnvis) - Tensorflow implementation of ["Visualizing and Understanding Convolutional Networks"](https://www.cs.nyu.edu/~fergus/papers/zeilerECCV2014.pdf) +* [VGAN Tensorflow](https://github.com/Singularity42/VGAN-Tensorflow) - Tensorflow implementation for MIT ["Generating Videos with Scene Dynamics"](http://carlvondrick.com/tinyvideo/) by Vondrick et al. +* [3D Convolutional Neural Networks in TensorFlow](https://github.com/astorfi/3D-convolutional-speaker-recognition) - Implementation of ["3D Convolutional Neural Networks for Speaker Verification application"](https://arxiv.org/abs/1705.09422) in TensorFlow by Torfi et al. +* [U-Net](https://github.com/zsdonghao/u-net-brain-tumor) - For Brain Tumor Segmentation +* [Spatial Transformer Networks](https://github.com/zsdonghao/Spatial-Transformer-Nets) - Learn the Transformation Function +* [Lip Reading - Cross Audio-Visual Recognition using 3D Architectures in TensorFlow](https://github.com/astorfi/lip-reading-deeplearning) - TensorFlow Implementation of ["Cross Audio-Visual Recognition in the Wild Using Deep Learning"](https://arxiv.org/abs/1706.05739) by Torfi et al. +* [Attentive Object Tracking](https://github.com/akosiorek/hart) - Implementation of ["Hierarchical Attentive Recurrent Tracking"](https://arxiv.org/abs/1706.09262) +* [Holographic Embeddings for Graph Completion and Link Prediction](https://github.com/laxatives/TensorFlow-TransX) - Implementation of [Holographic Embeddings of Knowledge Graphs](http://arxiv.org/abs/1510.04935) +* [Unsupervised Object Counting](https://github.com/akosiorek/attend_infer_repeat) - Implementation of ["Attend, Infer, Repeat"](https://papers.nips.cc/paper/6230-attend-infer-repeat-fast-scene-understanding-with-generative-models) +* [Tensorflow FastText](https://github.com/apcode/tensorflow_fasttext) - A simple embedding based text classifier inspired by Facebook's fastText. +* [MusicGenreClassification](https://github.com/mlachmish/MusicGenreClassification) - Classify music genre from a 10 second sound stream using a Neural Network. +* [Kubeflow](https://github.com/kubeflow/kubeflow) - Framework for easily using Tensorflow with Kubernetes. +* [TensorNets](https://github.com/taehoonlee/tensornets) - 40+ Popular Computer Vision Models With Pre-trained Weights. + + + +## Powered by TensorFlow + +* [YOLO TensorFlow](https://github.com/gliese581gg/YOLO_tensorflow) - Implementation of 'YOLO : Real-Time Object Detection' +* [android-yolo](https://github.com/natanielruiz/android-yolo) - Real-time object detection on Android using the YOLO network, powered by TensorFlow. +* [Magenta](https://github.com/tensorflow/magenta) - Research project to advance the state of the art in machine intelligence for music and art generation + + + + +## Libraries + +* [TensorFlow Estimators](https://www.tensorflow.org/guide/estimators) - high-level TensorFlow API that greatly simplifies machine learning programming (originally [tensorflow/skflow](https://github.com/tensorflow/skflow)) +* [R Interface to TensorFlow](https://tensorflow.rstudio.com/) - R interface to TensorFlow APIs, including Estimators, Keras, Datasets, etc. +* [Lattice](https://github.com/tensorflow/lattice) - Implementation of Monotonic Calibrated Interpolated Look-Up Tables in TensorFlow +* [tensorflow.rb](https://github.com/somaticio/tensorflow.rb) - TensorFlow native interface for ruby using SWIG +* [tflearn](https://github.com/tflearn/tflearn) - Deep learning library featuring a higher-level API +* [TensorLayer](https://github.com/tensorlayer/tensorlayer) - Deep learning and reinforcement learning library for researchers and engineers +* [TensorFlow-Slim](https://github.com/tensorflow/models/tree/master/inception/inception/slim) - High-level library for defining models +* [TensorFrames](https://github.com/tjhunter/tensorframes) - TensorFlow binding for Apache Spark +* [TensorForce](https://github.com/reinforceio/tensorforce) - TensorForce: A TensorFlow library for applied reinforcement learning +* [TensorFlowOnSpark](https://github.com/yahoo/TensorFlowOnSpark) - initiative from Yahoo! to enable distributed TensorFlow with Apache Spark. +* [caffe-tensorflow](https://github.com/ethereon/caffe-tensorflow) - Convert Caffe models to TensorFlow format +* [keras](http://keras.io) - Minimal, modular deep learning library for TensorFlow and Theano +* [SyntaxNet: Neural Models of Syntax](https://github.com/tensorflow/models/tree/master/syntaxnet) - A TensorFlow implementation of the models described in [Globally Normalized Transition-Based Neural Networks, Andor et al. (2016)](http://arxiv.org/pdf/1603.06042.pdf) +* [keras-js](https://github.com/transcranial/keras-js) - Run Keras models (tensorflow backend) in the browser, with GPU support +* [NNFlow](https://github.com/welschma/NNFlow) - Simple framework allowing to read-in ROOT NTuples by converting them to a Numpy array and then use them in Google Tensorflow. +* [Sonnet](https://github.com/deepmind/sonnet) - Sonnet is DeepMind's library built on top of TensorFlow for building complex neural networks. +* [tensorpack](https://github.com/ppwwyyxx/tensorpack) - Neural Network Toolbox on TensorFlow focusing on training speed and on large datasets. +* [tf-encrypted](https://github.com/mortendahl/tf-encrypted) - Layer on top of TensorFlow for doing machine learning on encrypted data + + + +## Videos + +* [TensorFlow Guide 1](http://bit.ly/1OX8s8Y) - A guide to installation and use +* [TensorFlow Guide 2](http://bit.ly/1R27Ki9) - Continuation of first video +* [TensorFlow Basic Usage](http://bit.ly/1TCNmEY) - A guide going over basic usage +* [TensorFlow Deep MNIST for Experts](http://bit.ly/1L9IfJx) - Goes over Deep MNIST +* [TensorFlow Udacity Deep Learning](https://www.youtube.com/watch?v=ReaxoSIM5XQ) - Basic steps to install TensorFlow for free on the Cloud 9 online service with 1Gb of data +* [Why Google wants everyone to have access to TensorFlow](http://video.foxnews.com/v/4611174773001/why-google-wants-everyone-to-have-access-to-tensorflow/?#sp=show-clips) +* [Videos from TensorFlow Silicon Valley Meet Up 1/19/2016](http://blog.altoros.com/videos-from-tensorflow-silicon-valley-meetup-january-19-2016.html) +* [Videos from TensorFlow Silicon Valley Meet Up 1/21/2016](http://blog.altoros.com/videos-from-tensorflow-seattle-meetup-jan-21-2016.html) +* [Stanford CS224d Lecture 7 - Introduction to TensorFlow, 19th Apr 2016](https://www.youtube.com/watch?v=L8Y2_Cq2X5s&index=7&list=PLmImxx8Char9Ig0ZHSyTqGsdhb9weEGam) - CS224d Deep Learning for Natural Language Processing by Richard Socher +* [Diving into Machine Learning through TensorFlow](https://youtu.be/GZBIPwdGtkk?list=PLBkISg6QfSX9HL6us70IBs9slFciFFa4W) - Pycon 2016 Portland Oregon, [Slide](https://storage.googleapis.com/amy-jo/talks/tf-workshop.pdf) & [Code](https://github.com/amygdala/tensorflow-workshop) by Julia Ferraioli, Amy Unruh, Eli Bixby +* [Large Scale Deep Learning with TensorFlow](https://youtu.be/XYwIDn00PAo) - Spark Summit 2016 Keynote by Jeff Dean +* [Tensorflow and deep learning - without at PhD](https://www.youtube.com/watch?v=vq2nnJ4g6N0) - by Martin Görner +* [Tensorflow and deep learning - without at PhD, Part 2 (Google Cloud Next '17)](https://www.youtube.com/watch?v=fTUwdXUFfI8) - by Martin Görner +* [Image recognition in Go using TensorFlow](https://youtu.be/P8MZ1Z2LHrw) - by Alex Pliutau + + + + + +## Papers + +* [TensorFlow: Large-Scale Machine Learning on Heterogeneous Distributed Systems](http://download.tensorflow.org/paper/whitepaper2015.pdf) - This paper describes the TensorFlow interface and an implementation of that interface that we have built at Google +* [TensorFlow Estimators: Managing Simplicity vs. Flexibility in High-Level Machine Learning Frameworks](https://arxiv.org/pdf/1708.02637.pdf) +* [TF.Learn: TensorFlow's High-level Module for Distributed Machine Learning](https://arxiv.org/abs/1612.04251) +* [Comparative Study of Deep Learning Software Frameworks](http://arxiv.org/abs/1511.06435) - The study is performed on several types of deep learning architectures and we evaluate the performance of the above frameworks when employed on a single machine for both (multi-threaded) CPU and GPU (Nvidia Titan X) settings +* [Distributed TensorFlow with MPI](http://arxiv.org/abs/1603.02339) - In this paper, we extend recently proposed Google TensorFlow for execution on large scale clusters using Message Passing Interface (MPI) +* [Globally Normalized Transition-Based Neural Networks](http://arxiv.org/abs/1603.06042) - This paper describes the models behind [SyntaxNet](https://github.com/tensorflow/models/tree/master/syntaxnet). +* [TensorFlow: A system for large-scale machine learning](https://arxiv.org/abs/1605.08695) - This paper describes the TensorFlow dataflow model in contrast to existing systems and demonstrate the compelling performance +* [TensorLayer: A Versatile Library for Efficient Deep Learning Development](https://arxiv.org/abs/1707.08551) - This paper describes a versatile Python library that aims at helping researchers and engineers efficiently develop deep learning systems. (Winner of The Best Open Source Software Award of ACM MM 2017) + + + +## Official announcements + +* [TensorFlow: smarter machine learning, for everyone](https://googleblog.blogspot.com/2015/11/tensorflow-smarter-machine-learning-for.html) - An introduction to TensorFlow +* [Announcing SyntaxNet: The World’s Most Accurate Parser Goes Open Source](http://googleresearch.blogspot.com/2016/05/announcing-syntaxnet-worlds-most.html) - Release of SyntaxNet, "an open-source neural network framework implemented in TensorFlow that provides a foundation for Natural Language Understanding systems. + +## Blog posts +* [Official Tensorflow Blog](http://blog.tensorflow.org/) +* [Why TensorFlow will change the Game for AI](https://archive.fo/o9asj) +* [TensorFlow for Poets](http://petewarden.com/2016/02/28/tensorflow-for-poets) - Goes over the implementation of TensorFlow +* [Introduction to Scikit Flow - Simplified Interface to TensorFlow](http://terrytangyuan.github.io/2016/03/14/scikit-flow-intro/) - Key Features Illustrated +* [Building Machine Learning Estimator in TensorFlow](http://terrytangyuan.github.io/2016/07/08/understand-and-build-tensorflow-estimator/) - Understanding the Internals of TensorFlow Learn Estimators +* [TensorFlow - Not Just For Deep Learning](http://terrytangyuan.github.io/2016/08/06/tensorflow-not-just-deep-learning/) +* [The indico Machine Learning Team's take on TensorFlow](https://indico.io/blog/indico-tensorflow) +* [The Good, Bad, & Ugly of TensorFlow](https://indico.io/blog/the-good-bad-ugly-of-tensorflow/) - A survey of six months rapid evolution (+ tips/hacks and code to fix the ugly stuff), Dan Kuster at Indico, May 9, 2016 +* [Fizz Buzz in TensorFlow](http://joelgrus.com/2016/05/23/fizz-buzz-in-tensorflow/) - A joke by Joel Grus +* [RNNs In TensorFlow, A Practical Guide And Undocumented Features](http://www.wildml.com/2016/08/rnns-in-tensorflow-a-practical-guide-and-undocumented-features/) - Step-by-step guide with full code examples on GitHub. +* [Using TensorBoard to Visualize Image Classification Retraining in TensorFlow](http://maxmelnick.com/2016/07/04/visualizing-tensorflow-retrain.html) +* [TFRecords Guide](http://warmspringwinds.github.io/tensorflow/tf-slim/2016/12/21/tfrecords-guide/) semantic segmentation and handling the TFRecord file format. +* [TensorFlow Android Guide](https://blog.mindorks.com/android-tensorflow-machine-learning-example-ff0e9b2654cc) - Android TensorFlow Machine Learning Example. +* [TensorFlow Optimizations on Modern Intel® Architecture](https://software.intel.com/en-us/articles/tensorflow-optimizations-on-modern-intel-architecture) - Introduces TensorFlow optimizations on Intel® Xeon® and Intel® Xeon Phi™ processor-based platforms based on an Intel/Google collaboration. +* [Coca-Cola's Image Recognition App](https://developers.googleblog.com/2017/09/how-machine-learning-with-tensorflow.html) Coca-Cola's product code image recognizing neural network with user input feedback loop. +* [How Does The TensorFlow Work](https://www.letslearnai.com/2018/02/02/how-does-the-machine-learning-library-tensorflow-work.html) How Does The Machine Learning Library TensorFlow Work? + + + + +## Community + +* [Stack Overflow](http://stackoverflow.com/questions/tagged/tensorflow) +* [@TensorFlow on Twitter](https://twitter.com/tensorflow) +* [Reddit](https://www.reddit.com/r/tensorflow) +* [Mailing List](https://groups.google.com/a/tensorflow.org/forum/#!forum/discuss) + + + + +## Books + +* [Machine Learning with TensorFlow](http://tensorflowbook.com) by Nishant Shukla, computer vision researcher at UCLA and author of Haskell Data Analysis Cookbook. This book makes the math-heavy topic of ML approachable and practicle to a newcomer. +* [First Contact with TensorFlow](http://www.jorditorres.org/first-contact-with-tensorflow/) by Jordi Torres, professor at UPC Barcelona Tech and a research manager and senior advisor at Barcelona Supercomputing Center +* [Deep Learning with Python](https://machinelearningmastery.com/deep-learning-with-python/) - Develop Deep Learning Models on Theano and TensorFlow Using Keras by Jason Brownlee +* [TensorFlow for Machine Intelligence](https://bleedingedgepress.com/tensor-flow-for-machine-intelligence/) - Complete guide to use TensorFlow from the basics of graph computing, to deep learning models to using it in production environments - Bleeding Edge Press +* [Getting Started with TensorFlow](https://www.packtpub.com/big-data-and-business-intelligence/getting-started-tensorflow) - Get up and running with the latest numerical computing library by Google and dive deeper into your data, by Giancarlo Zaccone +* [Hands-On Machine Learning with Scikit-Learn and TensorFlow](http://shop.oreilly.com/product/0636920052289.do) – by Aurélien Geron, former lead of the YouTube video classification team. Covers ML fundamentals, training and deploying deep nets across multiple servers and GPUs using TensorFlow, the latest CNN, RNN and Autoencoder architectures, and Reinforcement Learning (Deep Q). +* [Building Machine Learning Projects with Tensorflow](https://www.packtpub.com/big-data-and-business-intelligence/building-machine-learning-projects-tensorflow) – by Rodolfo Bonnin. This book covers various projects in TensorFlow that expose what can be done with TensorFlow in different scenarios. The book provides projects on training models, machine learning, deep learning, and working with various neural networks. Each project is an engaging and insightful exercise that will teach you how to use TensorFlow and show you how layers of data can be explored by working with Tensors. +* [Deep Learning using TensorLayer](http://www.broadview.com.cn/book/5059) - by Hao Dong et al. This book covers both deep learning and the implmentation by using TensorFlow and TensorLayer. + + + + + +## Contributions + +Your contributions are always welcome! + +If you want to contribute to this list (please do), send me a pull request or contact me [@jtoy](https://twitter.com/jtoy) +Also, if you notice that any of the above listed repositories should be deprecated, due to any of the following reasons: + +* Repository's owner explicitly say that "this library is not maintained". +* Not committed for long time (2~3 years). + +More info on the [guidelines](https://github.com/jtoy/awesome-tensorflow/blob/master/contributing.md) + + + + +## Credits + +* Some of the python libraries were cut-and-pasted from [vinta](https://github.com/vinta/awesome-python) +* The few go reference I found where pulled from [this page](https://code.google.com/p/go-wiki/wiki/Projects#Machine_Learning) + diff --git a/darknect/tensorflow/readme.md b/darknect/tensorflow/readme.md index 4a2f0401..e8d82cfe 100644 --- a/darknect/tensorflow/readme.md +++ b/darknect/tensorflow/readme.md @@ -1,9 +1,87 @@ # tensorflow 使用 +[TensorFlow 教程和实战经验 ](https://github.com/Ewenwan/EffectiveTensorflow) + +[tensorflow_tutorials 教程 待整合](https://github.com/Ewenwan/tensorflow_tutorials) + +[深入浅出Tensorflow 中文教程](https://www.ctolib.com/docs-Tensorflow-c-index.html) [TFLearn: Deep learning library featuring a higher-level API for TensorFlow ](https://github.com/Ewenwan/tflearn) +[我的Learn_TensorFLow](https://github.com/Ewenwan/Learn_TensorFLow) + +[TensorFlow技术内幕(一):导论](https://www.imooc.com/article/265350) + +[参考 刘光聪 著 TensorFlow 内核剖析](https://github.com/Ewenwan/MVision/blob/master/darknect/tensorflow/TensorFlow%E5%86%85%E6%A0%B8%E5%89%96%E6%9E%90.pdf) + +[Simple Tensorflow Cookbook 代码本](https://github.com/Ewenwan/Tensorflow-Cookbook) + +![](https://upload-images.jianshu.io/upload_images/12714329-6928cb6461e05052.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/565/format/webp) + + TensorFlow 是一个使用 数据流图 (Dataflow Graph) 表达数值计算的开源软件库。 + 用 节点 表示抽象的 数学计算,并使用 OP 表达计算的逻辑; + 而 边 表示节点间 传递的数据流, + 并使用 Tensor 表达数据的表示。 + 数据流图是一种有 向无环图 (DAG),当图中的 OP 按照特定的拓扑排序依次被执行时, + Tensor 在图中流动形成数据流, TensorFlow 因此而得名。 + + 分布式运算: 数据流图的被分裂为多个子图, + 在一个机器内,注册的子图被二次分裂为更小的子图, + 它们被部署在本地设备集上并发执行。 + + TensorFlow 最初由 Google Brain (谷歌大脑) 的研究员和工程师们开发出来, + 用于开展机器学习和深度神经网络的研究, + 包括 语言识别、计算机视觉、自然语言理解、机器人、信息检索。 + + Google Brain 构建了第一代分布式深度学习框架 DistBelief。 + 于 2015.11 重磅推出第二代分布式深度学习框架 TensorFlow。 + + Tensorflow前端支持多种开发语言,包括Python,C++,Go,Java等,出于性能的考虑,后端实现采用了C++和CUDA。 + +示例: + +```python +import tensor flow as tf +# 生成一个1维度向量,长度为10,初始化为0 +b = tf.Variable(tf.zeros([10])) + +#生成一个二维数组,大小为784x10,随机初始化 -1~1 +W = tf.Variable(tf.random_uniform([784,10],-1,1)) + +# 生成输入的Placeholder,计算的时候填入输入值 +x = tf.palceholder(name="x") # tf.placeholder 定义了一个占位的 OP +# 当 Session.run 时,将通过 feed_dict 的字典提供一个 mini-batch 的 +# 样本数据集,从而自动推导出 tf.placeholder 的大小。 + + +#计算最终输出 +s = tf.matmul(W,x) + b +out= tf.nn.relu(s) +#开始计算 +with tf.Session() as sess: + r = sess.run(out, feed_dict={x:input}) + print(r) + +# 我们我们算法是输入是 x, 输出是 out = Relu(wx+b) . +# MNIST 拥有 50000 个训练样本,如果 batch_size 为 100, +# 则需要迭代 500 次才能完整地遍历一次训练样本数据集,常称为一个 epoch 周期。 + +``` + +![](https://upload-images.jianshu.io/upload_images/12714329-664b59dc942586c9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/330/format/webp) + +1. 计算图(graph):TensorFlow中的计算都可以表示为一个有向图(directed graph),上图就是一个计算图(Graph)。 + +2. 节点(node):计算图中的每个运算操作,比如Add,Relu,Matmul就将作为节点,b,w,x,out等也是节点 + +3. 运算(operation):例如Add,Relu,Matmul,运算代表一种类型的抽象运算。运算可以有自己的属性,但是所有属性必须被预先设置,或则能在计算的时候被推断出来。 + +4. 运算核:是一个运算在一个具体硬件(GPU,CPU,ARM等)上的实现。 + +5. 张量(Tensor):张量是对Tensorflow中所有数据的抽象,张量有自己的维度和size。有自己是数据类型,比如浮点,整形等。张量沿着计算图的边流动,这也是平台名称tensorflow名字的来源。 + +6. 会话(session):会话包含了计算图运行的所有上线问信息。 + -[Learn_TensorFLow](https://github.com/Ewenwan/Learn_TensorFLow) # tensorflow pip安装 Ubuntu/Linux 64-bit$ @@ -48,7 +126,13 @@    github 源码安装源码安装介绍 http://blog.csdn.net/masa_fish/article/details/54096996 + TensorFlow技术内幕(二):编译与安装 + https://www.imooc.com/article/265349 + # 学习tensorflow 目录 + +[学习tensorflow ](https://github.com/Ewenwan/Learn_TensorFLow) + ```asm * 1. [Simple Multiplication] 两个数相乘 相加 (00_multiply.py) * 2. [Linear Regression] 两维变量 线性回归 (01_linear_regression.py) @@ -74,3 +158,302 @@ * 9. [TensorBoard] tensorboard 显示优化记录专题 (09_tensorboard.py) * 10. [Save and restore net] 保存和载入网络模型 (10_save_restore_net.py) ``` + +# 1. TensorFlow 前身 DistBelief 分析 + DistBelief 的编程模型是基于 层 的 DAG 图。 + 层可以看做是一种组合多个运算操作符的复合运算符,它完成特定的计算任务。 + 例如,全连接层完成 f(W * x + b) 的复合计算,包括 + 输入与权重的矩阵乘法,随后再与偏置相加, + 最后在线性加权值的基础上应用激活函数,实施非线性变换。 + + DistBelief 使用参数服务器 (Parameter Server, 常称为 PS) 的系统架构, + 训练作业包括两个分离的进程: + 1. 无状态的 Worker 进程,用于模型的训练; + 2. 有状态的 PS 进程,用于维护模型的参数。 + + 在分布式训练过程中, + 各个模型副本异步地从 PS 上拉取训练参数 w, + 当完成一步迭代运算后,推送参数的梯度 ∆w 到 PS 上去, + w' = w - Learning_rate * ∆w + 并完成参数的更新。 + +## DistBelief 缺陷: + 但是,对于深度学习领域的高级用户, DistBelief 的编程模型, + 及其基于 PS 的系统架构,缺乏足够的灵活性和可扩展性。 + 1. 优化算法: + 添加新的优化算法,必须修改 PS 的实现; + get(), put() 的抽象方法,对某些优化算法并不高效。 + 2. 训练算法: + 支持非前馈的神经网络面临巨大的挑战性; + 例如,包含循环的 RNN,交替训练的对抗网络; + 及其损失函数由分离的代理完成的增强学习模型。 + 3. 加速设备: + DistBelief 设计之初仅支持多核 CPU,并不支持多卡的 GPU, + 遗留的系统架构对支持新的计算设备缺乏良好的可扩展性。 + +## TensorFlow 设计及改进 + TensorFlow 使用数据流图表达计算过程和共享状态, + 使用节点表示抽象计算,使用边表示数据流。 + + +### 设计原则: + TensorFlow 的系统架构遵循了一些基本的设计原则, + 用于指导 TensorFlow 的系统实现. + + 1. 延迟计算: + 图的构造与执行分离,并推迟计算图的执行过程; + + 2. 原子 OP: + OP 是最小的抽象计算单元,支持构造复杂的网络模型; + + 3. 抽象设备: + 支持 CPU, GPU, ASIC 多种异构计算设备类型; + + 4. 抽象任务: + 基于任务的 PS(参数服务器),对新的优化算法和网络模型具有良好的可扩展性。 + +### 优势: + 相对于其他机器学习框架, TensorFlow 具有如下方面的优势。 + + 1. 高性能: + TensorFlow 升级至 1.0 版本性能提升显著, + 单机多卡 (8 卡 GPU) 环境中, Inception v3 的训练实现了 7.3 倍的加速比; + 在分布式多机多卡 (64 卡 GPU) 环境中, Inception v3 的训练实现了 58 倍的加速比; + + 2. 跨平台: + 支持多 CPU/GPU/ASIC 多种异构设备的运算;支持台式机,服务器,移动设备等多种计算平台; + 支持 Windows, Linux, MacOS 等多种操作系统; + 3. 分布式: + 支持本地和分布式的模型训练和推理; + 4. 多语言: + 支持 Python, C++, Java, Go 等多种程序设计语言; + 5. 通用性: + 支持各种复杂的网络模型的设计和实现,包括非前馈型神经网络; + 6. 可扩展: + 支持 OP 扩展, Kernel 扩展, Device 扩展,通信协议的扩展; + 7. 可视化: + 使用 TensorBoard 可视化整个训练过程,极大地降低了 TensorFlow 的调试过程; + 8. 自动微分: + TensorFlow 自动构造反向的计算子图,完成训练参数的梯度计算; + 9. 工作流: + TensorFlow 与 TensorFlow Serving 无缝集成,支持模型的训练、导入、 + 导出、发布一站式的工作流,并自动实现模型的热更新和版本管理。 + +# 2. TensorFlow 编程环境 + 代码结构,工程构建,理解 TensorFlow 的系统架构 + +## 代码结构 +克隆源代码: +> $ git clone git@github.com:tensorflow/tensorflow.git + +切换到最新的稳定分支上。例如, r1.4 分支. + +> $ cd tensorflow + +> $ git checkout r1.4 + +查看代码结构: +>$ tree -d -L 1 ./tensorflow 目录下 一级目标列表 + +``` +./tensorflow +├── c C API代码 +├── cc C++ API代码 总53 万行+ C/C++ 代码 +├── compiler XLA,JIT等编译优化相关 大约为 12.5 万行,主要使用 C++ 实现 +├── contrib 第三方贡献的代码 +├── core 内核代码, 主要由 C++ 实现,大约拥有 26 万行代码 +├── docs_src 文档相关文件 +├── examples 例子相关代码 +├── g3doc TF文档 +├── go go API相关代码 +├── java java API相关代码 +├── python Python API相关代码 总37 万行+ Python提供的 API 最完善 +├── stream_executor 并行计算框架代码,实现了 CUDA 和 OpenCL 的统一封装。 C++ 实现 2.5 万行代码 +├── tools 辅助工具工程代码 +└── user_ops tf插件代码 +``` + + contrib 是第三方贡献的编程库, + 它也是 TensorFlow 标准化之前的实验性编程接口, + 犹如 Boost 社区与 C++ 标准之间的关系。 + 当 contrib 的接口成熟后,便会被 TensorFlow + 标准化,并从 contrib 中搬迁至 core, python 中, + + +core 内核代码 目录: +> tree -d -L 1 ./tensorflow/core + +``` +./tensorflow/core +├── common_runtime 本地运行时,公共运行库 +├── debug 调试相关 +├── distributed_runtime 分布式运行时,分布式执行模块 +├── example 例子代码 +├── framework 基础框架,基础功能模块 +├── graph 图操作,计算图相关 +├── grappler 模型优化模块 Grappler +├── kernels Kernel 实现,包括CPU和GPU上的实现 +├── lib 公共基础库 +├── ops OP 定义,操作代码 +├── platform 各种平台实现相关 +├── profiler +├── protobuf Protobuf 定义 +├── public +├── user_ops OP 定义 +└── util 实用函数库? +``` + + Python API相关代码 目录: 大约有 18 万行代码 +> tree -d -L 1 ./tensorflow/python + +``` +./tensorflow/python +├── client 客户端? 是前端系统的主要组成部分 +├── debug +├── estimator +├── feature_column +├── framework +├── grappler +├── kernel_tests +├── layers +├── lib +├── ops +├── platform +├── profiler +├── saved_model +├── summary +├── tools +├── training +├── user_ops +└── util +``` + + +# 3. TensorFlow 系统架构 + + + +# 4. C API:分水岭,是衔接前后端系统的桥梁、 + + +# 5. 计算图 + + +# 6. 设备 + + +# 7. 会话 Session + + + +# 8. 变量 Variable + + + +# 9. 队列 QueueRunner 控制异步计算的强大工具 + + +# 10. OP 本质论 + + +# 11. 本地执行 + + +# 12. 分布式 TensorFlow + + +# 13. BP反向传播算法 实现 + +# 14. 数据加载 + + +# 15. 模型保存 Saver + + +# 16. 会话监视器 MonitoredSession + + + +# 学习思考 + + 读书有三到,谓心到,眼到,口到。 - 朱熹《训学斋规》 + + 1. 选择 + 耳到,择其善者而从之,择不善者而改之。 + 取其精华去其糟粕。 + + 2. 抽象 + 眼到,扫除外物,直觅本来也。 + 一眼便能看到的都是假象,看不到,摸不着的往往才是本质。 + 简洁之美 + 万物理论 + 忌 盲目抽象!没有调查就没有发言权 + 犹如大规模的预先设计, + 畅谈客户的各种需求, + 畅谈软件设计中各种变化。 + + 3. 分享 + 三人行必有我师焉。 + 口到,传道,授业,解惑也。 + 分享是一种生活的信念,明白了分享的同时,自然明白了存在的意义。 + 喜欢分享知识,并将其当成一种学习动力,督促自己透彻理解问题的。 + + 4. 领悟 + 心到,学而思之,思则得之,不思则不得也。 + 只有通过自己独立思考,归纳总结的知识,才是真正属于自己的。 + + 可使用图表来总结知识,一方面图的表达力远远大于文字; + 另外,通过画图也逼迫自己能够透彻问题的本质。 + +# 成长 + 1. 消除重复 + 代码需要消除重复,工作的习惯也要消除重复。 + 不要拘于固有的工作状态, + 重复的工作状态往往使人陷入舒服的假象, + 陷入三年效应的危机。 + + 2. 提炼知识 + 首先我们学习的不是信息,而是知识。知识是有价值的,而信息则没有价值。 + 只有通过自己的筛选,提炼,总结才可能将信息转变为知识。 + + 3. 成为习惯 + 知识是容易忘记的,只有将知识付诸于行动,并将其融汇到自己的工作状态中去, + 才能永久性地成为自己的财产。 + + 例如,快捷键的使用,不要刻意地去记忆,而是变成自己的一种工作习惯; + 不要去重复地劳动,使用 Shell 提供自动化程度, + 让 Shell 成为工作效率提升的利器,并将成为一种工作习惯。 + + 4. 更新知识 + 我们需要常常更新既有的知识体系,尤其我们处在一个知识大爆炸的时代。 + 终生学习。 + 持续学习。 + 活到老学到老。 + 开放包容接纳。 + + 在C/Objective-C中,if、while、for之后的判断式并不需要一定传入布尔类型。 + 也可以传入整型、指针等类型,只要非0就为真,并且赋值是有副作用的。比如: + a = 0 + 上面代码返回a的数值,这样就有可能出现将判断: + if ( a == 0 ) + 错写成: + f ( a = 0 ) + 为避免这个问题,有种变通写法: + if ( 0 == a ) + 这种写法被称为Yoda(倒装)表达式, + 因为《星球大战》中的Yoda大师喜欢使用这样奇特的倒装句子。 + + 5. 重构自我 + 学,然后知不足;教,然后知困。 + 不要停留在原点,应该时刻重构自己的知识体系。 + + 6. 专攻术业 + 一专多能。 + 多转多能。 + 人的精力是有限的,一个人不可能掌握住世界上所有的知识。 + 与其在程序设计语言的抉择上犹豫不决,不如透彻理解方法论的内在本质; + 与其在众多框架中悬而未决,不如付出实际,着眼于问题本身。 + 总之,博而不精,不可不防。 + + + diff --git a/darknect/tensorflow/src/readme.md b/darknect/tensorflow/src/readme.md new file mode 100644 index 00000000..cec545cf --- /dev/null +++ b/darknect/tensorflow/src/readme.md @@ -0,0 +1 @@ +# TensorFlow 源代码 记录 diff --git a/deepLearning/readme.md b/deepLearning/readme.md index 0606496e..b10cd9d4 100644 --- a/deepLearning/readme.md +++ b/deepLearning/readme.md @@ -1,4 +1,7 @@ # 深度学习算法 The deeplearning algorithms includes (now): + +[深度学习笔记 ](https://github.com/Ewenwan/deep_learning_notes) + - 逻辑回归 Logistic Regression   [logisticRegression.py](logisticRegression.py) - 多层感知机 Multi-Layer Perceptron (MLP) [mlp.py](mlp.py) - 卷积神经网络 Convolution Neural Network (CNN) [cnn.py](cnn.py) @@ -17,6 +20,10 @@ Note: the project aims at imitating the well-implemented algorithms in [Deep Lea [吴恩达老师的深度学习课程笔记及资源](https://github.com/fengdu78/deeplearning_ai_books) +[Deep Learning with Keras ](https://github.com/PacktPublishing/Deep-Learning-with-Keras/tree/master/Chapter07) + +[动手学深度学习 在线书籍 ](https://github.com/d2l-ai/d2l-zh) + # 博客资源 [深度学习(一)——MP(多层感知器)神经元模型, BP(反向传播)算法, 《机器学习》周志华著; 台湾大学李宏毅副教授的深度学习课程; Deep Learning书籍](http://antkillerfarm.github.io/dl/2017/01/13/Deep_Learning.html) diff --git a/deepLearning/reinforcement_learning/CS294-112/lec-1-basic-know.pdf b/deepLearning/reinforcement_learning/CS294-112/lec-1-basic-know.pdf new file mode 100644 index 00000000..393c6bbe Binary files /dev/null and b/deepLearning/reinforcement_learning/CS294-112/lec-1-basic-know.pdf differ diff --git a/deepLearning/reinforcement_learning/CS294-112/lec-10-OptimalControlandPlanning.pdf b/deepLearning/reinforcement_learning/CS294-112/lec-10-OptimalControlandPlanning.pdf new file mode 100644 index 00000000..ecfeb063 Binary files /dev/null and b/deepLearning/reinforcement_learning/CS294-112/lec-10-OptimalControlandPlanning.pdf differ diff --git a/deepLearning/reinforcement_learning/CS294-112/lec-11-Model-BasedReinforcementLearning.pdf b/deepLearning/reinforcement_learning/CS294-112/lec-11-Model-BasedReinforcementLearning.pdf new file mode 100644 index 00000000..42391deb Binary files /dev/null and b/deepLearning/reinforcement_learning/CS294-112/lec-11-Model-BasedReinforcementLearning.pdf differ diff --git a/deepLearning/reinforcement_learning/CS294-112/lec-12-AdvancedModel-BasedReinforcementLearning.pdf b/deepLearning/reinforcement_learning/CS294-112/lec-12-AdvancedModel-BasedReinforcementLearning.pdf new file mode 100644 index 00000000..de33de3e Binary files /dev/null and b/deepLearning/reinforcement_learning/CS294-112/lec-12-AdvancedModel-BasedReinforcementLearning.pdf differ diff --git a/deepLearning/reinforcement_learning/CS294-112/lec-13-Model-BasedRLandPolicyLearning.pdf b/deepLearning/reinforcement_learning/CS294-112/lec-13-Model-BasedRLandPolicyLearning.pdf new file mode 100644 index 00000000..2e36866c Binary files /dev/null and b/deepLearning/reinforcement_learning/CS294-112/lec-13-Model-BasedRLandPolicyLearning.pdf differ diff --git a/deepLearning/reinforcement_learning/CS294-112/lec-14-VariationalInferenceGenerativeModels.pdf b/deepLearning/reinforcement_learning/CS294-112/lec-14-VariationalInferenceGenerativeModels.pdf new file mode 100644 index 00000000..e0ca99d4 Binary files /dev/null and b/deepLearning/reinforcement_learning/CS294-112/lec-14-VariationalInferenceGenerativeModels.pdf differ diff --git a/deepLearning/reinforcement_learning/CS294-112/lec-15-ReframingControlInferenceProblem.pdf b/deepLearning/reinforcement_learning/CS294-112/lec-15-ReframingControlInferenceProblem.pdf new file mode 100644 index 00000000..65ebec3a Binary files /dev/null and b/deepLearning/reinforcement_learning/CS294-112/lec-15-ReframingControlInferenceProblem.pdf differ diff --git a/deepLearning/reinforcement_learning/CS294-112/lec-16-InverseReinforcementLearning.pdf b/deepLearning/reinforcement_learning/CS294-112/lec-16-InverseReinforcementLearning.pdf new file mode 100644 index 00000000..19e3c64c Binary files /dev/null and b/deepLearning/reinforcement_learning/CS294-112/lec-16-InverseReinforcementLearning.pdf differ diff --git a/deepLearning/reinforcement_learning/CS294-112/lec-17-ExplorationPart1.pdf b/deepLearning/reinforcement_learning/CS294-112/lec-17-ExplorationPart1.pdf new file mode 100644 index 00000000..d262c5cc Binary files /dev/null and b/deepLearning/reinforcement_learning/CS294-112/lec-17-ExplorationPart1.pdf differ diff --git a/deepLearning/reinforcement_learning/CS294-112/lec-18-ExplorationPart2.pdf b/deepLearning/reinforcement_learning/CS294-112/lec-18-ExplorationPart2.pdf new file mode 100644 index 00000000..9a1610b8 Binary files /dev/null and b/deepLearning/reinforcement_learning/CS294-112/lec-18-ExplorationPart2.pdf differ diff --git a/deepLearning/reinforcement_learning/CS294-112/lec-19-TransferMulti-TaskLearning.pdf b/deepLearning/reinforcement_learning/CS294-112/lec-19-TransferMulti-TaskLearning.pdf new file mode 100644 index 00000000..d4bfb92a Binary files /dev/null and b/deepLearning/reinforcement_learning/CS294-112/lec-19-TransferMulti-TaskLearning.pdf differ diff --git a/deepLearning/reinforcement_learning/CS294-112/lec-2-SupervisedLearning.pdf b/deepLearning/reinforcement_learning/CS294-112/lec-2-SupervisedLearning.pdf new file mode 100644 index 00000000..1a2c2c7f Binary files /dev/null and b/deepLearning/reinforcement_learning/CS294-112/lec-2-SupervisedLearning.pdf differ diff --git a/deepLearning/reinforcement_learning/CS294-112/lec-20-MetaReinforcementLearning.pdf b/deepLearning/reinforcement_learning/CS294-112/lec-20-MetaReinforcementLearning.pdf new file mode 100644 index 00000000..542c0933 Binary files /dev/null and b/deepLearning/reinforcement_learning/CS294-112/lec-20-MetaReinforcementLearning.pdf differ diff --git a/deepLearning/reinforcement_learning/CS294-112/lec-21-DistributedRL.pdf b/deepLearning/reinforcement_learning/CS294-112/lec-21-DistributedRL.pdf new file mode 100644 index 00000000..bc083329 Binary files /dev/null and b/deepLearning/reinforcement_learning/CS294-112/lec-21-DistributedRL.pdf differ diff --git a/deepLearning/reinforcement_learning/CS294-112/lec-22-TowardsVirtualStuntman.pdf b/deepLearning/reinforcement_learning/CS294-112/lec-22-TowardsVirtualStuntman.pdf new file mode 100644 index 00000000..e0e1d83c Binary files /dev/null and b/deepLearning/reinforcement_learning/CS294-112/lec-22-TowardsVirtualStuntman.pdf differ diff --git a/deepLearning/reinforcement_learning/CS294-112/lec-24-Classnotes.pdf b/deepLearning/reinforcement_learning/CS294-112/lec-24-Classnotes.pdf new file mode 100644 index 00000000..ee5ec7ec Binary files /dev/null and b/deepLearning/reinforcement_learning/CS294-112/lec-24-Classnotes.pdf differ diff --git a/deepLearning/reinforcement_learning/CS294-112/lec-25-AutoML.pdf b/deepLearning/reinforcement_learning/CS294-112/lec-25-AutoML.pdf new file mode 100644 index 00000000..2d1d16dd Binary files /dev/null and b/deepLearning/reinforcement_learning/CS294-112/lec-25-AutoML.pdf differ diff --git a/deepLearning/reinforcement_learning/CS294-112/lec-4-ReinforcementLearningIntroduction.pdf b/deepLearning/reinforcement_learning/CS294-112/lec-4-ReinforcementLearningIntroduction.pdf new file mode 100644 index 00000000..c0bbc06a Binary files /dev/null and b/deepLearning/reinforcement_learning/CS294-112/lec-4-ReinforcementLearningIntroduction.pdf differ diff --git a/deepLearning/reinforcement_learning/CS294-112/lec-5-PolicyGradients.pdf b/deepLearning/reinforcement_learning/CS294-112/lec-5-PolicyGradients.pdf new file mode 100644 index 00000000..10b2e5b4 Binary files /dev/null and b/deepLearning/reinforcement_learning/CS294-112/lec-5-PolicyGradients.pdf differ diff --git a/deepLearning/reinforcement_learning/CS294-112/lec-6-Actor-Critic-Algorithms.pdf b/deepLearning/reinforcement_learning/CS294-112/lec-6-Actor-Critic-Algorithms.pdf new file mode 100644 index 00000000..6e8dd83c Binary files /dev/null and b/deepLearning/reinforcement_learning/CS294-112/lec-6-Actor-Critic-Algorithms.pdf differ diff --git a/deepLearning/reinforcement_learning/CS294-112/lec-7-ValueFunctionMethods.pdf b/deepLearning/reinforcement_learning/CS294-112/lec-7-ValueFunctionMethods.pdf new file mode 100644 index 00000000..81ca3e6b Binary files /dev/null and b/deepLearning/reinforcement_learning/CS294-112/lec-7-ValueFunctionMethods.pdf differ diff --git a/deepLearning/reinforcement_learning/CS294-112/lec-8-DeepRLwithQ-Functions.pdf b/deepLearning/reinforcement_learning/CS294-112/lec-8-DeepRLwithQ-Functions.pdf new file mode 100644 index 00000000..0ceb964f Binary files /dev/null and b/deepLearning/reinforcement_learning/CS294-112/lec-8-DeepRLwithQ-Functions.pdf differ diff --git a/deepLearning/reinforcement_learning/CS294-112/lec-9-AdvancedPolicyGradients.pdf b/deepLearning/reinforcement_learning/CS294-112/lec-9-AdvancedPolicyGradients.pdf new file mode 100644 index 00000000..9f3d58e9 Binary files /dev/null and b/deepLearning/reinforcement_learning/CS294-112/lec-9-AdvancedPolicyGradients.pdf differ diff --git a/deepLearning/reinforcement_learning/CS294-112/readme.md b/deepLearning/reinforcement_learning/CS294-112/readme.md new file mode 100644 index 00000000..6213b405 --- /dev/null +++ b/deepLearning/reinforcement_learning/CS294-112/readme.md @@ -0,0 +1 @@ +# CS294-112 深度增强学习课程(加州大学伯克利分校 2017) diff --git a/deepLearning/reinforcement_learning/readme.md b/deepLearning/reinforcement_learning/readme.md new file mode 100644 index 00000000..4ee5420c --- /dev/null +++ b/deepLearning/reinforcement_learning/readme.md @@ -0,0 +1,94 @@ +# 强化学习、反馈学习、遗传学习 自主学习... +[ 深度强化学习综述(上)](https://blog.csdn.net/SIGAI_CSDN/article/details/83862597) + +[UCL(伦敦大学)主讲的强化学习经典课程 AI = Deep Learning + Reinforcement Learning ](https://github.com/Ewenwan/UCL-DeepReinforcementLearning) + +[openAI Deep RL 学习](https://spinningup.openai.com/en/latest/) + +[CS294-112深度增强学习课程(加州大学伯克利分校 2017) B站视频](https://www.bilibili.com/video/av9802698/) + +[CS294-112官方课程主页](http://rail.eecs.berkeley.edu/deeprlcourse/) + +[CS294-112官方 github 作业](https://github.com/Ewenwan/homework) + +[Deep Reinforcement Learning Hands-On!!!推荐](https://github.com/PacktPublishing/Deep-Reinforcement-Learning-Hands-On) + + + 人工智能中的很多应用问题需要算法在每个时刻做出决策并执行动作。 + + 1. 对于围棋,每一步需要决定在棋盘的哪个位置放置棋子,以最大可能的战胜对手; + 2. 对于自动驾驶算法,需要根据路况来确定当前的行驶策略以保证安全的行驶到目的地; + 3. 对于机械手,要驱动手臂运动以抓取到设定的目标物体。 + + 这类问题有一个共同的特点: + 要根据当前的条件作出决策和动作,以达到某一预期目标。 + 解决这类问题的机器学习算法称为强化学习(reinforcement learning,RL)。 + 虽然传统的强化学习理论在过去几十年中得到了不断的完善, + 但还是难以解决现实世界中的复杂问题。 + +# 深度强化学习(DRL,deep reinforcement learning) + + 是深度学习与强化学习相结合的产物, + 它集成了深度学习在视觉等感知问题上强大的理解能力,以及强化学习的决策能力,实现了端到端学习。 + 深度强化学习的出现使得强化学习技术真正走向实用,得以解决现实场景中的复杂问题。 + 从2013年DQN(深度Q网络,deep Q network)出现到目前为止, + 深度强化学习领域出现了大量的算法,以及解决实际应用问题的论文。 + + +# 什么是强化学习 + + 强化学习是一类特殊的机器学习算法,借鉴于行为主义心理学。 + 与有监督学习和无监督学习的目标不同,算法要解决的问题是智能体(agent,即运行强化学习算法的实体) + 在环境中怎样执行动作以获得最大的累计奖励。 + + 例如, + 对于自动行驶的汽车,强化学习算法控制汽车的动作,保证安全行驶到目的地。 + 对于围棋算法,算法要根据当前的棋局来决定如何走子,以赢得这局棋。 + + 对于第一个问题, + 环境是车辆当前行驶状态(如速度)、路况这样的参数构成的系统的抽象, + 奖励是我们期望得到的结果,即汽车正确的在路面上行驶,到达目的地而不发生事故。 + + 很多控制、决策问题都可以抽象成这种模型。 + 和有监督学习类似,强化学习也有训练过程,需要不断的执行动作, + 观察执行动作后的效果,积累经验形成一个模型。 + 与有监督学习不同的是,这里每个动作一般没有直接标定的标签值作为监督信号, + 系统只给算法执行的动作一个反馈,这种反馈一般具有延迟性, + 当前的动作所产生的后果在未来才会完全体现, + 另外未来还具有随机性,例如下一个时刻路面上有哪些行人、车辆在运动, + 算法下一个棋子之后对手会怎么下,都是随机的而不是确定的。 + 当前下的棋产生的效果,在一局棋结束时才能体现出来。 + + 强化学习应用广泛,被认为是通向强人工智能/通用人工智能的核心技术之一。 + 所有需要做决策和控制的地方,都有它的身影。 + 典型的包括游戏与博弈,如打星际争霸、Atari游戏 + + 自动驾驶系统/无人车: + 算法需要根据当前的路况,无人车自身的状态(如速度、加速度)决定其行驶的行为,如控制方向盘,油门,刹车等。 + 机器人控制: + 机器人要根据当前所处的环境,自身的状态,决定其要执行的动作。 + + 所有这些问题总计起来都有一个特点,即 + 智能体需要观察环境和自身的状态, + 然后决定要执行的动作,以达到想要的目标 + |———————动作— —————| + | | + 智能体 <-奖励/惩罚---环境 + |——————反馈————— —| + + + 智能体是强化学习的动作实体。 + 对于自动驾驶的汽车,环境是当前的路况; + 对于围棋,状态是当前的棋局。 + 在每个时刻,智能体和环境有自己的状态, + 如汽车当前位置和速度,路面上的车辆和行人情况。 + 智能体根据当前状态确定一个动作,并执行该动作。 + 之后它和环境进入下一个状态, + 同时系统给它一个反馈值, + 对动作进行奖励或惩罚,以迫使智能体执行期望的动作。 + + + + + + diff --git "a/deepLearning/\345\212\250\342\274\277\345\255\246\346\267\261\345\272\246\345\255\246\344\271\240.pdf" "b/deepLearning/\345\212\250\342\274\277\345\255\246\346\267\261\345\272\246\345\255\246\344\271\240.pdf" new file mode 100644 index 00000000..bc16b82a Binary files /dev/null and "b/deepLearning/\345\212\250\342\274\277\345\255\246\346\267\261\345\272\246\345\255\246\344\271\240.pdf" differ diff --git a/opencv_app/Basic/common/readme.md b/opencv_app/Basic/common/readme.md index da0a426f..da73a02c 100644 --- a/opencv_app/Basic/common/readme.md +++ b/opencv_app/Basic/common/readme.md @@ -2,4 +2,16 @@ ## 读取、转换、存储图片 ## 简单画图 线 圆 椭圆 多边形 随机画图 ## 图像元素访问 查找表 阶梯化像素值 色域缩减 -## +## 快速 RGB 变 BGR +```c +cv::Mat rgb; +rgb = cv::Mat(480, 640, CV_8UC3);// 0~255 RGB 数据 + + // RGB 变 BGR=========================== + void flipColors() + { +#pragma omp parallel for + for (unsigned i = 0; i < rgb.total() * 3; i += 3) std::swap(rgb.data[i + 0], rgb.data[i + 2]); + } + +``` diff --git a/opencv_app/Basic/image_Processing/area_measuring_Src.cpp b/opencv_app/Basic/image_Processing/area_measuring_Src.cpp new file mode 100644 index 00000000..4205aadb --- /dev/null +++ b/opencv_app/Basic/image_Processing/area_measuring_Src.cpp @@ -0,0 +1,145 @@ +// Copyright 2018 Zeyu Zhong +// Lincese(MIT) +// Author: Zeyu Zhong +// Date: 2018.5.4 + +#include +#include +#include +// #include +// https://github.com/zhearing/image_measurement/blob/master/4-area-measuring/src/area_measuring.cpp + +using namespace cv; + +int main(int argc, char **argv) { + Mat image = imread("../../4-area-measuring/images/origin.bmp", -1); + // cvtColor(image,image,CV_BGR2GRAY); + // threshold(image,image,145,255,THRESH_BINARY); + // imwrite("../../4-area-measuring/output/origin.bmp", image); + Mat L; + image.copyTo(L); + + for (int i = 0; i < L.rows - 1; i++) + for (int j = 0; j < L.cols - 1; j++) { + L.at(i, j) = 0;//清零。。。。? + } + int nl = 0; + int T[90000] = {0}; + for (int i = 0; i < image.rows; i++) + for (int j = 0; j < image.cols; j++) { + if (static_castimage.at(i, j) == 0) { + continue; + } else { + int X[4]; +// [0][3] +// [1][] +// [2] + X[0] = L.at(i - 1, j - 1);//左上点 + X[1] = L.at(i - 1, j); + X[2] = L.at(i - 1, j + 1); + X[3] = L.at(i, j - 1); + int t = 0; + int L1[4]; + int L2[8]; + for (int k = 0; k < 4; k++) { + if (T[X[k]] != 0) { + L1[t] = T[X[k]]; + t++; + } + } + int n = 0; + if (t == 0) { + n = 0; + } else { + int tem; + for (int p = 0; p < t; p++) { + for (int q = 0; q < t - p - 1; q++) { + if (L1[q] > L1[q + 1]) { + tem = L1[q]; + L1[q] = L1[q + 1]; + L1[q + 1] = tem; + } + } + } + int d = L1[0]; + for (int w = 1; w < t; w++) { + if (L1[w] != d) { + L2[n] = d; + n++; + d = L1[w]; + } + } + if (L1[t - 1] == d) + L2[n] = d; + n = n + 1; + } + switch (n) { + case 0: + nl = nl + 1; + T[nl] = nl; + L.at(i, j) = nl; + continue; + case 1: + L.at(i, j) = L2[0]; + continue; + case 2: + L.at(i, j) = L2[0]; + for (int k = 2; k < nl + 1; k++) { + if (T[k] == L2[1]) + T[k] = L2[0]; + } + continue; + } + } + } + int T1[100]; + int T2[100]; + for (int k1 = 1; k1 < nl + 1; k1++) + T1[k1] = T[k1]; + int tem; + for (int p = 1; p < nl + 1; p++) { + for (int q = 1; q < nl - p + 1; q++) { + if (T1[q] > T1[q + 1]) { + tem = T1[q]; + T1[q] = T1[q + 1]; + T1[q + 1] = tem; + } + } + } + int d = T1[1]; + int n0 = 1; + for (int w = 2; w < nl + 1; w++) { + if (T1[w] != d) { + T2[n0] = d; + n0++; + d = T1[w]; + } + } + if (T1[nl] == d) + T2[n0] = d; + for (int i = 1; i < n0 + 1; i++) { + for (int k1 = 1; k1 < nl + 1; k1++) { + if (T[k1] == T2[i]) + T[k1] = i; + } + } + for (int i = 0; i < image.rows; i++) + for (int j = 0; j < image.cols; j++) { + if (L.at(i, j) > 0) + L.at(i, j) = T[L.at(i, j)]; + } + int area[100] = {0}; + for (int m = 0; m < n0 + 1; m++) { + for (int i = 0; i < image.rows; i++) + for (int j = 0; j < image.cols; j++) { + if (L.at(i, j) == m) + area[m] = area[m] + 1; + } + } + + for (int k1 = 0; k1 < n0 + 1; k1++) + std::cout << "area" << k1 << " " << area[k1] << "\n\r"; + + waitKey(0); + return 0; +} diff --git a/opencv_app/Basic/image_Processing/image_edge_detection_soceur.cpp b/opencv_app/Basic/image_Processing/image_edge_detection_soceur.cpp new file mode 100644 index 00000000..5af45cfe --- /dev/null +++ b/opencv_app/Basic/image_Processing/image_edge_detection_soceur.cpp @@ -0,0 +1,57 @@ +// Copyright 2018 Zeyu Zhong +// Lincese(MIT) +// Author: Zeyu Zhong +// Date: 2018.5.3 +// https://github.com/zhearing/image_measurement/blob/master/2-image-edge-detection/src/image_edge_detection.cpp + +// 源码 边缘检测 +// +#include +#include + +using namespace cv; + +int main(int argc, char **argv) { + Mat image = imread("../../2-image-edge-detection/images/mid_image_enhancement.bmp", -1); + Mat priwitt, smoothed; + image.copyTo(priwitt); + image.copyTo(smoothed); + + for (int i = 1; i < image.rows - 1; i++) + for (int j = 1; j < image.cols - 1; j++) { + int f[8]; + +// [3][4][5] +// [2][ ][6] +// [1][0][7] + f[0] = image.at(i, j + 1); + f[1] = image.at(i - 1, j + 1); + f[2] = image.at(i - 1, j); + f[3] = image.at(i - 1, j - 1); + f[4] = image.at(i, j - 1); + f[5] = image.at(i + 1, j - 1); + f[6] = image.at(i + 1, j); + f[7] = image.at(i + 1, j + 1); + int w1, w2, w; + w1 = f[3] + f[4] + f[2] - f[0] - f[6] - f[7]; // 左上角 - 右下角 + w2 = f[2] + f[1] + f[0] - f[4] - f[5] - f[6]; // 左下角 - 右上角 + w = abs(w1) + abs(w2); + if (w > 80) + priwitt.at(i, j) = 255;// 角点 + else + priwitt.at(i, j) = 0; + int Dx, Dy; + Dx = f[1] + f[0] + f[7] - f[3] - f[4] - f[5];// 下 - 上 + Dy = f[3] + f[2] + f[1] - f[5] - f[6] - f[7];// 左 - 右 + smoothed.at(i, j) = abs(Dx) + abs(Dy); + } + + namedWindow("priwitt", WINDOW_AUTOSIZE); + imshow("priwitt", priwitt); + imwrite("../../2-image-edge-detection/output/priwitt.bmp", priwitt); + namedWindow("smoothed", WINDOW_AUTOSIZE); + imshow("smoothed", smoothed); + imwrite("../../2-image-edge-detection/output/smoothed.bmp", smoothed); + waitKey(0); + return 0; +} diff --git a/opencv_app/Basic/image_Processing/image_enhacement.cpp b/opencv_app/Basic/image_Processing/image_enhacement.cpp new file mode 100644 index 00000000..dfa92917 --- /dev/null +++ b/opencv_app/Basic/image_Processing/image_enhacement.cpp @@ -0,0 +1,59 @@ +// Copyright 2018 Zeyu Zhong +// Lincese(MIT) +// Author: Zeyu Zhong +// Date: 2018.5.3 +// https://github.com/zhearing/image_measurement/blob/master/1-image-smoothing-and-image-enhancement/src/image_enhacement.cpp + +// 图像增强============== + +#include +#include + +using namespace cv; + +Mat Enhancement(Mat image, double alpha) { + Mat image_enhancement; + image.copyTo(image_enhancement); + for (int i = 1; i < image.rows - 1; i++) + for (int j = 1; j < image.cols - 1; j++) + image_enhancement.at(i, j) + = image.at(i, j) + + 4 * alpha * ( + image.at(i, j) - (image.at(i + 1, j) + image.at(i - 1, j) + image.at(i, j + 1) + image.at(i, j - 1)) / 4); + +// 中心点像素值 + 4*参数*(中心点像素值 - 上下左右四点像素均值) + + return image_enhancement; +} + +int main(int argc, char **argv) { + Mat image = imread("../../1-image-smoothing-and-image-enhancement/images/lena.bmp", -1); + Mat ave_image, salt_image; + image.copyTo(ave_image); + image.copyTo(salt_image); + + double alpha = 0.8; + namedWindow("origin", WINDOW_AUTOSIZE); + imshow("origin", image); + + namedWindow("origin_enhancement", WINDOW_AUTOSIZE); + imshow("origin_enhancement", Enhancement(image, alpha)); + imwrite("../../1-image-smoothing-and-image-enhancement/output/origin_enhancement.bmp", Enhancement(image, alpha)); + + namedWindow("mid_image", WINDOW_AUTOSIZE); + imshow("mid_image", ave_image); + + namedWindow("mid_image_enhancement", WINDOW_AUTOSIZE); + imshow("mid_image_enhancement", Enhancement(ave_image, alpha)); + imwrite("../../1-image-smoothing-and-image-enhancement/output/mid_image_enhancement.bmp", Enhancement(ave_image, alpha)); + + namedWindow("salt_image", WINDOW_AUTOSIZE); + imshow("salt_image", salt_image); + + namedWindow("salt_image_enhancement", WINDOW_AUTOSIZE); + imshow("salt_image_enhancement", Enhancement(salt_image, alpha)); + imwrite("../../1-image-smoothing-and-image-enhancement/output/salt_image_enhancement.bmp", Enhancement(salt_image, alpha)); + + waitKey(0); + return 0; +} diff --git a/opencv_app/Basic/image_Processing/image_refinement.cpp b/opencv_app/Basic/image_Processing/image_refinement.cpp new file mode 100644 index 00000000..442e0886 --- /dev/null +++ b/opencv_app/Basic/image_Processing/image_refinement.cpp @@ -0,0 +1,75 @@ +// Copyright 2018 Zeyu Zhong +// Lincese(MIT) +// Author: Zeyu Zhong +// Date: 2018.5.3 + +// https://github.com/zhearing/image_measurement/blob/master/3-image-thresholding-and-image-refinement/src/image_refinement.cpp + +#include +#include + +using namespace cv; + +int main(int argc, char **argv) { + Mat image = imread("../../3-image-thresholding-and-image-refinement/output/image_binary.bmp", -1); + Mat image_refine; + image.copyTo(image_refine); + + for (int i = 0; i < image.rows; i++) + for (int j = 0; j < image.cols; j++) { + if (image.at(i, j) == 255)// 白 + image.at(i, j) = 1;// 边黑 + } + + for (int i = 1; i < image_refine.rows - 1; i++) + for (int j = 1; j < image_refine.cols - 1; j++) { + int f[9]; + int a = 0; + int b = 0; + if (image.at(i, j) == 0) { + continue;// 跳过纯黑 + } + else + { +// [3][4][5] +// [2][ ][6] +// [1][0][7] + f[0] = image.at(i, j + 1); + f[1] = image.at(i - 1, j + 1); + f[2] = image.at(i - 1, j); + f[3] = image.at(i - 1, j - 1); + f[4] = image.at(i, j - 1); + f[5] = image.at(i + 1, j - 1); + f[6] = image.at(i + 1, j); + f[7] = image.at(i + 1, j + 1); + f[8] = f[0]; + } + for (int n = 0; n < 8; n++) { + a = abs(f[i + 1] - f[i]) + 0; + b = f[i] + b; + } + if ((a == 0 || a == 2 || a == 4) && (b != 1)) + { + if (((f[0] && f[2] && f[4]) == 0) && ((f[0] && f[2] && f[6]) == 0)) { + if (a != 4) + image_refine.at(i, j) = 0; + else if (((f[0] && f[6]) == 1) && ((f[1] || f[5]) == 1) && ((f[2] || f[3] || f[4] || f[7]) == 0)) + image_refine.at(i, j) = 0; + else if (((f[0] && f[2]) == 1) && ((f[3] || f[7]) == 1) && ((f[1] || f[4] || f[5] || f[6]) == 0)) + image_refine.at(i, j) = 0; + } else if (((f[2] && f[4] && f[6]) == 0) && ((f[4] && f[6] && f[0]) == 0)) { + if (a != 4) + image_refine.at(i, j) = 0; + else if (((f[4] && f[2]) == 1) && ((f[5] || f[1]) == 1) && ((f[0] || f[3] || f[6] || f[7]) == 0)) + image_refine.at(i, j) = 0; + else if (((f[6] && f[4]) == 1) && ((f[7] || f[3]) == 1) && ((f[0] || f[5] || f[2] || f[1]) == 0)) + image_refine.at(i, j) = 0; + } + } + } + namedWindow("image_refine", WINDOW_AUTOSIZE); + imshow("image_refine", image_refine); + imwrite("../../3-image-thresholding-and-image-refinement/output/image_refine.bmp", image_refine); + waitKey(0); + return 0; +} diff --git a/opencv_app/Basic/image_Processing/image_smoothing.cpp b/opencv_app/Basic/image_Processing/image_smoothing.cpp new file mode 100644 index 00000000..28226a13 --- /dev/null +++ b/opencv_app/Basic/image_Processing/image_smoothing.cpp @@ -0,0 +1,157 @@ +// Copyright 2018 Zeyu Zhong +// Lincese(MIT) +// Author: Zeyu Zhong +// Date: 2018.5.3 +// https://github.com/zhearing/image_measurement/blob/master/1-image-smoothing-and-image-enhancement/src/image_smoothing.cpp + +// 添加 椒盐噪声 +// 均值、最大值、中值、平均值、最小值平滑滤波 + +#include +#include + +using namespace cv; + +// 添加 椒盐噪声 +void Saltapepper(Mat &image, const int n) { + int i, j; + for (int k = 0; k < n; k++) {//噪声点数量 + + i = random() % image.cols; + j = random() % image.rows; + if (image.channels() == 1) + { + image.at(j, i) = 255; + } + else if (image.channels() == 3) + { + image.at(j, i)[0] = 255;// 白色点 + image.at(j, i)[1] = 255; + image.at(j, i)[2] = 255; + } + + i = random() % image.cols; + j = random() % image.rows; + if (image.channels() == 1) + { + image.at(j, i) = 0; + } + else if (image.channels() == 3) + { + image.at(j, i)[0] = 0;// 黑色点 + image.at(j, i)[1] = 0; + image.at(j, i)[2] = 0; + } + } +} +// 冒泡排序=============== +void sort(int *src, int len) { + int tem; + for (int i = 0; i < len; i++) { + for (int j = 0; j < len - i - 1; j++) + if (src[j] > src[j + 1]) { + tem = src[j]; + src[j] = src[j + 1]; + src[j + 1] = tem; + } + } +} + +int main(int argc, char** argv) { + Mat image = imread("../../1-image-smoothing-and-image-enhancement/images/lena.bmp", -1); +// previous picture is like a grayscale picture but not a grayscale picture +// Mat mat = imread("../images/lena.bmp", IMREAD_GRAYSCALE); +// imwrite("../output/gray_image.bmp", mat); + Mat ave_image, mid_image, max_image, min_image; + image.copyTo(ave_image); + image.copyTo(mid_image); + image.copyTo(max_image); + image.copyTo(min_image); + +// 均值、最大值、中值、平均值、最小值平滑滤波============= + for (int i = 1; i < image.rows - 1; i++) + for (int j = 1; j < image.cols - 1; j++) { + int f[9]; + // 当前点 一周 8个点 + 自己,3*3的滑动窗口======= + f[0] = image.at(i, j + 1); + f[1] = image.at(i - 1, j + 1); + f[2] = image.at(i - 1, j); + f[3] = image.at(i - 1, j - 1); + f[4] = image.at(i, j - 1); + f[5] = image.at(i + 1, j - 1); + f[6] = image.at(i + 1, j); + f[7] = image.at(i + 1, j + 1); + f[8] = image.at(i, j); + sort(f, 9); + ave_image.at(i, j) = (f[0] + f[1] + f[2] + + f[3] + f[4] + f[5] + f[6] + f[7] + f[8]) / 9;// 均值 + mid_image.at(i, j) = f[4];// 中值 + max_image.at(i, j) = f[8];// 最大值 + min_image.at(i, j) = f[0];// 最小值 + } + + namedWindow("origin", WINDOW_AUTOSIZE); + imshow("origin", image); + + namedWindow("ave_image", WINDOW_AUTOSIZE); + imshow("ave_image", ave_image); + imwrite("../../1-image-smoothing-and-image-enhancement/output/ave_image.bmp", ave_image); + + namedWindow("mid_image", WINDOW_AUTOSIZE); + imshow("mid_image", mid_image); + imwrite("../../1-image-smoothing-and-image-enhancement/output/mid_image.bmp", mid_image); + + namedWindow("max_image", WINDOW_AUTOSIZE); + imshow("max_image", max_image); + imwrite("../../1-image-smoothing-and-image-enhancement/output/max_image.bmp", max_image); + + namedWindow("min_image", WINDOW_AUTOSIZE); + imshow("min_image", min_image); + imwrite("../../1-image-smoothing-and-image-enhancement/output/min_image.bmp", min_image); + + Saltapepper(image, 5000); // 椒盐噪声============== + +// 均值、最大值、中值、平均值、最小值平滑滤波============= + for (int i = 2; i < image.rows - 1; i++) + for (int j = 2; j < image.cols - 1; j++) { + int f[9]; + f[0] = image.at(i, j + 1); + f[1] = image.at(i - 1, j + 1); + f[2] = image.at(i - 1, j); + f[3] = image.at(i - 1, j - 1); + f[4] = image.at(i, j - 1); + f[5] = image.at(i + 1, j - 1); + f[6] = image.at(i + 1, j); + f[7] = image.at(i + 1, j + 1); + f[8] = image.at(i, j); + sort(f, 9); + ave_image.at(i, j) = (f[0] + f[1] + f[2] + f[3] + + f[4] + f[5] + f[6] + f[7] + f[8]) / 9; + mid_image.at(i, j) = f[4]; + max_image.at(i, j) = f[8]; + min_image.at(i, j) = f[0]; + } + + namedWindow("salt_image", WINDOW_AUTOSIZE); + imshow("salt_image", image); + imwrite("../../1-image-smoothing-and-image-enhancement/output/salt_image.bmp", image); + + namedWindow("salt_ave_image", WINDOW_AUTOSIZE); + imshow("salt_ave_image", ave_image); + imwrite("../../1-image-smoothing-and-image-enhancement/output/salt_ave_image.bmp", ave_image); + + namedWindow("salt_mid_image", WINDOW_AUTOSIZE); + imshow("salt_mid_image", mid_image); + imwrite("../../1-image-smoothing-and-image-enhancement/output/salt_mid_image.bmp", mid_image); + + namedWindow("salt_max_image", WINDOW_AUTOSIZE); + imshow("salt_max_image", max_image); + imwrite("../../1-image-smoothing-and-image-enhancement/output/salt_max_image.bmp", max_image); + + namedWindow("salt_min_image", WINDOW_AUTOSIZE); + imshow("salt_min_image", min_image); + imwrite("../../1-image-smoothing-and-image-enhancement/output/salt_min_image.bmp", min_image); + + waitKey(0); + return 0; +} diff --git a/opencv_app/Basic/image_Processing/image_thresholding_src.cpp b/opencv_app/Basic/image_Processing/image_thresholding_src.cpp new file mode 100644 index 00000000..5a0eaadb --- /dev/null +++ b/opencv_app/Basic/image_Processing/image_thresholding_src.cpp @@ -0,0 +1,102 @@ +// Copyright 2018 Zeyu Zhong +// Lincese(MIT) +// Author: Zeyu Zhong +// Date: 2018.5.3 +// https://github.com/zhearing/image_measurement/blob/master/3-image-thresholding-and-image-refinement/src/image_thresholding.cpp + + +#include +#include + +using namespace cv; + +int main(int argc, char **argv) { + Mat image = imread("../../3-image-thresholding-and-image-refinement/images/smoothed.bmp", -1); + Mat image_binary; + image.copyTo(image_binary); + + int s1[image.rows][image.cols]; + for (int m = 1; m < image.rows - 1; m++) + { + for (int n = 1; n < image.cols - 1; n++) + { + int D = 0; + for (int k1 = -1; k1 < 2; k1++) + { // -1 0 1 + for (int k2 = -1; k2 < 2; k2++) + { // -1 0 1 + // 3*3周围9个点=============== + if (image.at(m, n) > image.at(m + k1, n + k2))// 比外圈大 + D = (image.at(m, n) - image.at(m + k1, n + k2) + D);// 大的值求和 + else + D = 0 + D;// 小的不加 + } + } + s1[m][n] = D; + } + } + + int C1 = 0; + int threshold1 = 0; + for (int i = 0; i < 256; i++) + {// 0~255像素值 + int S = 0; + for (int m = 1; m < image.rows - 1; m++) + { + for (int n = 1; n < image.cols - 1; n++) + { + if (image.at(m, n) == i)// 为1像素的点 为2像素的点 ... + S = S + s1[m][n]; + } + } + + if (S > C1) { + C1 = S;// 最大 + threshold1 = i;// 对应像素阈值 + } + } + for (int m = 1; m < image.rows - 1; m++) + for (int n = 1; n < image.cols - 1; n++) + { + int D = 0; + for (int k1 = -1; k1 < 2; k1++) // -1 0 1 + for (int k2 = -1; k2 < 2; k2++) // -1 0 1 + {// 3*3周围9个点=============== + if (image.at(m, n) < image.at(m + k1, n + k2)) + D = (image.at(m, n) - image.at(m + k1, n + k2)) + D; + } + s1[m][n] = D; + } + int C2; + int threshold2 = 0; + for (int i = 0; i < 256; i++) { + int S = 0; + for (int m = 1; m < image.rows - 1; m++) + for (int n = 1; n < image.cols - 1; n++) + { + if (image.at(m, n) == i)// 为1像素的点 为2像素的点 ... + S = S + s1[m][n]; + } + if (S != 0 || S > C2) { + C2 = S; + threshold2 = i; + } + } + + int threshold_final = (threshold2 - threshold1) / 2;// 阈值 + + for (int m = 0; m < image_binary.rows; m++) + for (int n = 0; n < image_binary.cols; n++) { + // 阈值二值化============================================== + if (image_binary.at(m, n) >= threshold_final) + image_binary.at(m, n) = 255; + else + image_binary.at(m, n) = 0; + } + + namedWindow("image_binary", WINDOW_AUTOSIZE); + imshow("image_binary", image_binary); + imwrite("../../3-image-thresholding-and-image-refinement/output/image_binary.bmp", image_binary); + waitKey(0); + return 0; +} diff --git a/opencv_app/Basic/machine_learning/readme.md b/opencv_app/Basic/machine_learning/readme.md index 96772630..f3b92c6c 100644 --- a/opencv_app/Basic/machine_learning/readme.md +++ b/opencv_app/Basic/machine_learning/readme.md @@ -8,3 +8,13 @@ ## 主成分分析 数据降维 + + +## 级联回归分类器 +[基于 级联回归人脸检测 + ann 笑脸检测](https://github.com/Ewenwan/MVision/blob/master/opencv_app/Basic/machine_learning/smile_dec.cpp) + +[基于 级联回归人脸检测 + svm 笑脸检测](https://github.com/Ewenwan/MVision/blob/master/opencv_app/Basic/machine_learning/smile_dec_svm.cpp) + +[级联回归 分类器训练](http://blog.topspeedsnail.com/archives/10511) + + diff --git a/opencv_app/Basic/obj_track/CMakeLists.txt b/opencv_app/Basic/obj_track/CMakeLists.txt new file mode 100644 index 00000000..31e7df44 --- /dev/null +++ b/opencv_app/Basic/obj_track/CMakeLists.txt @@ -0,0 +1,12 @@ +# CMake版本限制 +cmake_minimum_required(VERSION 2.8) +# 工程名字 +project( DisplayImage ) +# 找opencv +find_package( OpenCV REQUIRED ) +# 包含opencv +include_directories( ${OpenCV_INCLUDE_DIRS} ) + + +add_executable( single_tracker single_tracker.cpp ) +target_link_libraries( single_tracker ${OpenCV_LIBS} ) diff --git a/opencv_app/Basic/obj_track/multitracker.cpp b/opencv_app/Basic/obj_track/multitracker.cpp new file mode 100644 index 00000000..5334f4bc --- /dev/null +++ b/opencv_app/Basic/obj_track/multitracker.cpp @@ -0,0 +1,93 @@ +/*---------------------------------------------- + * Usage: + * example_tracking_multitracker [algorithm] + * + * example: + * example_tracking_multitracker Bolt/img/%04d.jpg + * example_tracking_multitracker faceocc2.webm KCF + *--------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace cv; + +int main( int argc, char** argv ){ + // set the default tracking algorithm + std::string trackingAlg = "KCF"; +// 跟踪器的创建可选以下几种,代表使用的跟踪算法; +// MIL +// BOOSTING +// MEDIANFLOW +// TLD +// KCF + // set the tracking algorithm from parameter + if(argc>2) + trackingAlg = argv[2]; + // create the tracker + //! [create] + MultiTracker trackers(trackingAlg); + //! [create] + + // container of the tracked objects + //! [roi] + vector objects;// 多目标 + //! [roi] + + // set input video + std::string video = argv[1]; + VideoCapture cap(video); + + Mat frame; + + // get bounding box + cap >> frame; + //! [selectmulti] + selectROI("tracker",frame,objects); + //! [selectmulti] + + //quit when the tracked object(s) is not provided + if(objects.size()<1) + return 0; + + // initialize the tracker + //! [init] + trackers.add(frame,objects); + //! [init] + + // do the tracking + printf("Start the tracking process, press ESC to quit.\n"); + for ( ;; ) + { + // get frame from the video + cap >> frame; + + // stop the program if no more images + if(frame.rows==0 || frame.cols==0) + break; + + //update the tracking result + //! [update] + trackers.update(frame);// 获得跟踪结果 + //! [update] + + //! [result] + // draw the tracked object + for(unsigned i=0;i +#include +#include +#include +#include +#include + +using namespace std; +using namespace cv; + +int main( int argc, char** argv ) +{ + // show help + //! [help] + //! [help] + + // declares all required variables + //! [vars] + Rect2d roi; + Mat frame; + //! [vars] + + // create a tracker object + //! [create] + Ptr tracker = Tracker::create( "KCF" ); + //! [create] +// 跟踪器的创建可选以下几种,代表使用的跟踪算法; +// MIL +// BOOSTING +// MEDIANFLOW +// TLD +// KCF + + // set input video + //! [setvideo] + // std::string video = argv[1]; + VideoCapture cap(0);// 打开摄像头 + //! [setvideo] + if( !cap.isOpened() ) + { + printf("打开摄像头失败\r\n"); + return -1; + } + int track_flag_ok=0; + // get bounding box + //! [getframe] + cap.read(frame);// 读取第一帧=============== + cout<< frame.size() << endl; + //cap >> frame; + //! [getframe] + //! [selectroi] + roi=selectROI("tracker",frame);// 选取目标框============ + //! [selectroi] + + //quit if ROI was not selected + if(roi.width==0 || roi.height==0) + return 0; + + // initialize the tracker + //! [init] + tracker->init(frame,roi);// 初始化 目标框=================== + //! [init] + track_flag_ok=1; + // perform the tracking process + printf("Start the tracking process, press ESC to quit.\n"); + //for ( ;; ){ + while(cap.read(frame)) + { + // get frame from the video + // cap >> frame; + if(!track_flag_ok) + { + roi=selectROI("tracker",frame);// 选取目标框============ + tracker->init(frame,roi);// 初始化 目标框=================== + track_flag_ok=1; + } + // stop the program if no more images + if(frame.rows==0 || frame.cols==0) + break; + + // update the tracking result + //! [update] + int flag_t = tracker->update(frame,roi);// 获得跟踪结果 + // cout<< flag_t << endl; // 发现不了跟踪失败 + //! [update] + + //! [visualization] + // draw the tracked object + + if ( ((roi.x+roi.width/2)<0) || ((roi.x+roi.width/2)>640) || + ((roi.y+roi.height/2)<0) || ((roi.y+roi.height/2)>480) + ) + { + printf("lost.\n"); + track_flag_ok=0; + continue; + } + + rectangle( frame, roi, Scalar( 255, 0, 0 ), 2, 1 );// 绘制目标跟踪结果 + // cout<< roi.x << "\t "<< roi.y << "\t "<libcv-dev + + sudo apt-get install libgtk2.0-dev + sudo apt-get install libatlas-base-dev gfortran + + + # 编译 + cd opencv-master + mkdir release + cd release + 生成makefile + + sudo cmake -D CMAKE_BUILD_TYPE=RELEASE \ + -D CMAKE_INSTALL_PREFIX=/usr/local .. + + sudo make -j2 + sudo make install + sudo ldconfig diff --git a/opencv_app/project/BackgroundSubtraction/readme.md b/opencv_app/project/BackgroundSubtraction/readme.md new file mode 100644 index 00000000..5c40ca5e --- /dev/null +++ b/opencv_app/project/BackgroundSubtraction/readme.md @@ -0,0 +1,3 @@ +# Background Subtraction 背景去除 + +[参考](https://github.com/Ewenwan/bgslibrary) diff --git a/opencv_app/project/Bag-of-Features-Framework/readme.md b/opencv_app/project/Bag-of-Features-Framework/readme.md new file mode 100644 index 00000000..07d81228 --- /dev/null +++ b/opencv_app/project/Bag-of-Features-Framework/readme.md @@ -0,0 +1,21 @@ +# 视觉词袋模型分类 Bag-of-Features-Framework Bag of Features(BoF)图像分类实践 + +[penCV探索之路(二十八):Bag of Features(BoF)图像分类实践](https://www.cnblogs.com/skyfsm/p/8097397.html) + +[代码](https://github.com/Ewenwan/Bag-of-Features-Framework/blob/master/README.md) + +在深度学习在图像识别任务上大放异彩之前,词袋模型Bag of Features一直是各类比赛的首选方法 + +在2012年之前,词袋模型是VOC竞赛分类算法的基本框架,几乎所有算法都是基于词袋模型的,可以这么说,词袋模型在图像分类中统治了很多年。虽然现在深度学习在图像识别任务中的效果更胜一筹,但是我们也不要忘记在10年前,Bag of Features的框架曾经也引领过一个时代。那这篇文章就是要重温BoF这个经典框架,并从实践上看看它在图像物体分类中效果到底如何。 + +其实Bag of Features 是Bag of Words在图像识别领域的延伸,Bag of Words最初产生于自然处理领域,通过建模文档中单词出现的频率来对文档进行描述与表达。 + +词包模型还有一个起源就是纹理检测(texture recognition),有些图像是由一些重复的基础纹理元素图案所组成,所以我们也可以将这些图案做成频率直方图,形成词包模型。 + +词包模型于2004年首次被引入计算机视觉领域,由此开始大量集中于词包模型的研究,在各类图像识别比赛中也大放异彩,逐渐形成了由下面4部分组成的标准物体分类框架: + + 底层特征提取 + 特征编码 + 特征汇聚 + 使用SVM等分类器进行分类 + diff --git a/opencv_app/project/Cascade/readme.md b/opencv_app/project/Cascade/readme.md new file mode 100644 index 00000000..e71a0384 --- /dev/null +++ b/opencv_app/project/Cascade/readme.md @@ -0,0 +1,251 @@ +# 级联回归分类器 +[基于 级联回归人脸检测 + ann 笑脸检测](https://github.com/Ewenwan/MVision/blob/master/opencv_app/Basic/machine_learning/smile_dec.cpp) + +[基于 级联回归人脸检测 + svm 笑脸检测](https://github.com/Ewenwan/MVision/blob/master/opencv_app/Basic/machine_learning/smile_dec_svm.cpp) + +[级联回归 分类器训练](http://blog.topspeedsnail.com/archives/10511) + +Haar Cascade常用来做人脸检测,其实它可以检测任何对象。 + +OpenCV项目源码中有很多训练好的Haar分类器。 +opencv/data/haarcascades/..... + +先了解怎么使用这些现成的分类器,最后再训练自己的Haar分类器。 + +如果你要检测什么物体,先Google,也许已经有训练好的Haar分类器了(像汽车、猫,狗之类的)。 + + python 示例代码 +## 检测图像 +```python +#-*- coding:utf-8 -*- +# 检测图像 python face_detect.py lena.jpg +import cv2 +import sys + +img = cv2.imread(sys.argv[1]) + +# 加载分类器 +face_haar = cv2.CascadeClassifier("data/haarcascades/haarcascade_frontalface_default.xml") +eye_haar = cv2.CascadeClassifier("data/haarcascades/haarcascade_eye.xml") +# 把图像转为黑白图像 +gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) +# 检测图像中的所有脸 +faces = face_haar.detectMultiScale(gray_img, 1.3, 5) +for face_x,face_y,face_w,face_h in faces: + cv2.rectangle(img, (face_x, face_y), (face_x+face_w, face_y+face_h), (0,255,0), 2) + # 眼长在脸上 + roi_gray_img = gray_img[face_y:face_y+face_h, face_x:face_x+face_w] + roi_img = img[face_y:face_y+face_h, face_x:face_x+face_w] + eyes = eye_haar.detectMultiScale(roi_gray_img, 1.3, 5) + for eye_x,eye_y,eye_w,eye_h in eyes: + cv2.rectangle(roi_img, (eye_x,eye_y), (eye_x+eye_w, eye_y+eye_h), (255,0,0), 2) + +cv2.imshow('img', img) +cv2.waitKey(0) + +cv2.destroyAllWindows() + +``` + +## 使用摄像头做为输入,实时检测: +```python +#-*- coding:utf-8 -*- +import cv2 + +face_haar = cv2.CascadeClassifier("data/haarcascades/haarcascade_frontalface_default.xml") +eye_haar = cv2.CascadeClassifier("data/haarcascades/haarcascade_eye.xml") + +cam = cv2.VideoCapture(0) + +while True: + _, img = cam.read() + gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) + + faces = face_haar.detectMultiScale(gray_img, 1.3, 5) + for face_x,face_y,face_w,face_h in faces: + cv2.rectangle(img, (face_x, face_y), (face_x+face_w, face_y+face_h), (0,255,0), 2) + + roi_gray_img = gray_img[face_y:face_y+face_h, face_x:face_x+face_w] + roi_img = img[face_y:face_y+face_h, face_x:face_x+face_w] + eyes = eye_haar.detectMultiScale(roi_gray_img, 1.3, 5) + for eye_x,eye_y,eye_w,eye_h in eyes: + cv2.rectangle(roi_img, (eye_x,eye_y), (eye_x+eye_w, eye_y+eye_h), (255,0,0), 2) + + cv2.imshow('img', img) + key = cv2.waitKey(30) & 0xff + if key == 27: + break + +cam.release() +cv2.destroyAllWindows() + +``` + +## 训练分类器 + 上面我们使用的是训练好的分类器文件, + 如果你要检测的物体没有现成的Haar分类器, + 我们只能自己训练了,其中最费事的部分就是制作训练样本。 + + +### 训练Haar分类器的主要步骤: + + 1. 搜集制作成千上万张”消极”图像,什么图片都行,但是确保要检测的对象不在图像中 + 2. 搜集制作成千上万张”积极”图像,确保这些图像中包含要检测的对象 + http://image-net.org是不错的图像资源站 + 3. 创建”积极”向量文件 + 4. 使用OpenCV训练Haar分类器 + +为了简单,我使用一张图片制作”积极”图像 + + 做一个能检测我鼠标的Haar分类器 + 这是我的鼠标,我就使用这一张图片制作”积极”图像,没错, + 最后训练出来的Haar分类器只能识别这个特定鼠标。 + 如果你想要识别各种各样的鼠标,你需要搜集整理包含各种鼠标的图片(标记出图片中鼠标所在位置-ROI), + 即使有工具的帮助,这个工作也是相当痛苦的。 + +## 下载”消极”图像 + + 找点和鼠标不想干的图片:image-net + +Downloads中包含图像地址: +写一个简单的Python脚本下载图片: + +```python +# Python3 + +import urllib.request +import cv2 +import os + +# 创建图片保存目录 +if not os.path.exists('neg'): + os.makedirs('neg') + +neg_img_url = ['http://image-net.org/api/text/imagenet.synset.geturls?wnid=n00523513', 'http://image-net.org/api/text/imagenet.synset.geturls?wnid=n07942152'] + +urls = '' +for img_url in neg_img_url: + urls += urllib.request.urlopen(img_url).read().decode() + +img_index = 1 +for url in urls.split('\n'): + try: + print(url) + urllib.request.urlretrieve(url, 'neg/'+str(img_index)+'.jpg') + # 把图片转为灰度图片 + gray_img = cv2.imread('neg/'+str(img_index)+'.jpg', cv2.IMREAD_GRAYSCALE) + # 更改图像大小 + image = cv2.resize(gray_img, (150, 150)) + # 保存图片 + cv2.imwrite('neg/'+str(img_index)+'.jpg', image) + img_index += 1 + except Exception as e: + print(e) + +# 判断两张图片是否完全一样 +def is_same_image(img_file1, img_file2): + img1 = cv2.imread(img_file1) + img2 = cv2.imread(img_file2) + if img1.shape == img2.shape and not (np.bitwise_xor(img1, img2).any()): + return True + else: + return False + +# 去除重复图片 +""" +file_list = os.listdir('neg') +try: + for img1 in file_list: + for img2 in file_list: + if img1 != img2: + if is_same_image('neg/'+img1, 'neg/'+img2) is True: + print(img1, img2) + os.remove('neg/'+img1) + file_list.remove(img1) +except Exception as e: + print(e) +""" + +``` + +很多url被墙,你可能需要使用代理。(参考:使用Tor的匿名Python爬虫) + +下载的文件很多,为了提速,你可以把上面代码改为多线程。 + + +### 创建消极图片列表: + + +```python +import os +import numpy as np + +with open('neg.txt', 'w') as f: + for img in os.listdir('neg'): + line = 'neg/'+img+'\n' + f.write(line) +``` + +创建neg.txt + +## 制作”积极”图像 + +我使用OpenCV提供的opencv_createsamples命令创建pos.txt文件。 + +它会把要识别的图片嵌入到消极图像中,允许我们快速创建”积极”图像: + + $ opencv_createsamples -img mouse.jpg -bg neg.txt -info pos.txt -maxxangle 0.5 -maxyangle -0.5 -maxzangle 0.5 -num 2000 + + 生成pos.txt + + 第一列代表“积极”图像路径;后面数字代表图像中有几个要识别对象和对象所在位置 + 你可以看看生成的“积极”图像,这些图像中嵌入了要识别的鼠标。 + + 上面的”积极图像”是自动生成的,这要是手工制作,那工作量可想而知。 + +### 创建向量文件 + +不管你用什么方法制作”积极”图像,都需要把它转换为向量格式: + +$ opencv_createsamples -info pos.txt -num 2000 -w 20 -h 30 -vec pos.vec + +## 开始训练 + +$ mkdir data + +$ opencv_traincascade -data data -vec pos.vec -bg neg.txt -numPos 1800 -numNeg 900 -numStages 15 -w 20 -h 30 + +# pos一般是neg的1倍 + +大概需要几个小时,我电脑不给力,上面参数设置的都比较小。 + +训练完成之后生成的haar分类器(cascade.xml)保存在data目录。 + +## 测试生成的haar分类器 +```python +import cv2 + +mouse_haar = cv2.CascadeClassifier("data/cascade.xml") + +cam = cv2.VideoCapture(0) + +while True: + _, img = cam.read() + gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) + + #http://docs.opencv.org/2.4/modules/objdetect/doc/cascade_classification.html + mouse = mouse_haar.detectMultiScale(gray_img, 1.2, 3) # 调整参数 + + for mouse_x,mouse_y,mouse_w,mouse_h in mouse: + cv2.rectangle(img, (mouse_x, mouse_y), (mouse_x+mouse_w, mouse_y+mouse_h), (0,255,0), 2) + + cv2.imshow('img', img) + key = cv2.waitKey(30) & 0xff + if key == 27: + break + +cam.release() +cv2.destroyAllWindows() +``` + + diff --git a/opencv_app/project/LaneMarkings_TrafficSigns_Detection/readme.md b/opencv_app/project/LaneMarkings_TrafficSigns_Detection/readme.md new file mode 100644 index 00000000..2847a969 --- /dev/null +++ b/opencv_app/project/LaneMarkings_TrafficSigns_Detection/readme.md @@ -0,0 +1,2 @@ +# LaneMarkings_TrafficSigns_Detection +[参考](https://github.com/ZhangChaoZhong/LaneMarkings_TrafficSigns_Detection) diff --git a/opencv_app/project/PedestrianDetection/readme.md b/opencv_app/project/PedestrianDetection/readme.md new file mode 100644 index 00000000..e917774e --- /dev/null +++ b/opencv_app/project/PedestrianDetection/readme.md @@ -0,0 +1,5 @@ +# 行人检测与跟踪 +[参考](https://github.com/xmfbit/PedestrianDetection) + + 检测方法和Dalal 2005年的论文相同,使用了HOG特征和SVM 进行行人目标的检测。 + 跟踪方法使用Kalman滤波器,建立了行人的简单的线性运动模型,进行预测,实现检测——跟踪框架。 diff --git a/opencv_app/project/Scanner/readme.md b/opencv_app/project/Scanner/readme.md new file mode 100644 index 00000000..a2251564 --- /dev/null +++ b/opencv_app/project/Scanner/readme.md @@ -0,0 +1,72 @@ +# ORC scanner 简易扫描软件 轮廓检测+透视变换 + +[OpenCV探索之路(二十二):制作一个类“全能扫描王”的简易扫描软件](https://www.cnblogs.com/skyfsm/p/7324346.html) + +[代码](https://github.com/AstarLight/my_scanner) + +[基于轮廓和直线的图片校正](https://www.cnblogs.com/skyfsm/p/6902524.html) + +相信很多人手机里都装了个“扫描全能王”APP,平时可以用它来可以扫描一些证件、文本,确实很好用,第一次用的时候确实感觉功能很强大啊算法很牛逼啊。但是仔细一想,其实这些实现起来也是很简单的,我想了下,实现的步骤应该就只有下面三个: + + 将证件轮廓找到 + 提取证件矩形轮廓四点进行透视变换 + 二值化 +知道原理之后,我马上利用强大的opencv开发一个类似“全能扫描王”扫描工具。 + +整理一下我们要制作的这个扫描工具有哪些功能: + + 图像的信息区域的提取与矫正 + 图像的二值化 + 锐化和增强 +第二第三点都非常简单,那么制作这个工具的难点完全落在了第一点“ 图像的信息区域的提取与矫正”上了。在编码实现的过程中,确实有很多坑需要踩一踩。 + + +对于图像矫正的问题,在图像处理领域还真得多,比如人民币的矫正、文本的矫正、车牌的矫正、身份证矫正等等。这些都是因为拍摄者总不可能100%正确地拍摄好图片,这就要求我们通过后期的图像处理技术将图片还原好,才能进一步做后面的处理,比如数字分割啊数字识别啊,不然歪歪扭扭的文字数字,想识别出来估计就很难了。 + +上面几个图,我们在日常生活中遇到的可不少,因为拍摄时拍的不好,导致拍出来的图片歪歪扭扭的,很不自然,那么我们能不能把这些图片尽可能地矫正过来呢? + +OpenCV告诉我们,没问题!工具我给你,算法你自己设计! + +比如图一,我要想将人民币矫正,并且把人民币整个抠出来保存,该怎么做?那就涉及到了图像的矫正和感兴趣区域提取两大技术了。 + +总的来说,要进行进行图像矫正,至少有以下几项知识储备: + + 轮廓提取技术 + 霍夫变换知识 + ROI感兴趣区域知识 + +没错,我们就抓住**人民币的的边缘比较明显**来做文章!我们是不是可以先把人民币的轮廓找出来(找出来的轮廓当然就是一个大大的矩形),然后用矩形去包围它,得到他的旋转角度,然后根据得到的角度进行旋转,那样不就可以实现矫正了吗! + +再详细地总结处理步骤: + + 图片灰度化 + 阈值二值化 + 检测轮廓 + 寻找轮廓的包围矩阵,并且获取角度 + 根据角度进行旋转矫正 + 对旋转后的图像进行轮廓提取 + 对轮廓内的图像区域抠出来,成为一张独立图像 + + + + +人民币图像和发票图像他们有明显的的边界轮廓,而**文本图像**没有。文本图像的背景是白色的,所以我们没有办法像人民币发票那类有明显边界的矩形物体那样,提取出轮廓并旋转矫正。 + +经过深入分析可以看出,虽然文本类图像没有明显的边缘轮廓,但是他们有一个很重要的特征,那就是每一行文字都是呈现一条直线形状,而且这些直线都是平行的! + +对于这种情况,我想到了另一种方法:基于直线探测的矫正算法。 + +首先介绍一下我的算法思路: + + 用霍夫线变换探测出图像中的所有直线 + 计算出每条直线的倾斜角,求他们的平均值 + 根据倾斜角旋转矫正 + 最后根据文本尺寸裁剪图片 + + +最后总结一下两个算法的应用场景: + + 基于轮廓提取的矫正算法更适用于车牌、身份证、人民币、书本、发票一类矩形形状而且边界明显的物体矫正。 + + 基于直线探测的矫正算法更适用于文本类的矫正。 + diff --git a/opencv_app/project/SkinDetector/readme.md b/opencv_app/project/SkinDetector/readme.md new file mode 100644 index 00000000..68b394b7 --- /dev/null +++ b/opencv_app/project/SkinDetector/readme.md @@ -0,0 +1,16 @@ +# opencv写的一个人的皮肤检测器,里面封装了多种算法 + +[OpenCV探索之路(二十七):皮肤检测技术](https://www.cnblogs.com/skyfsm/p/7868877.html) + +[代码](https://github.com/AstarLight/skin-detector) + +里面封装了以下6种主流的皮肤检测算法: + + RGB color space + Ycrcb之cr分量+otsu阈值化 + YCrCb中133<=Cr<=173 77<=Cb<=127 + HSV中 748,v>50 + 基于椭圆皮肤模型的皮肤检测 + opencv自带肤色检测类AdaptiveSkinDetector + + diff --git a/opencv_app/project/TextSegementation/readme.md b/opencv_app/project/TextSegementation/readme.md new file mode 100644 index 00000000..b514111f --- /dev/null +++ b/opencv_app/project/TextSegementation/readme.md @@ -0,0 +1,26 @@ +# Text Segementation 文字定位与切割 + +[【OCR技术系列之二】文字定位与切割](https://www.cnblogs.com/skyfsm/p/8029668.html) + +[代码](https://github.com/AstarLight/text_segementation) + + +们实际上要识别的图片很可能没上面那张图片如此整洁, +很可能是倾斜的,或者是带噪声的,又或者这张图片是用手机拍下来下来的, +变得歪歪扭扭,所以需要进行图片预处理,把文本位置矫正, +把噪声去除,然后才可以进行进一步的字符分割和文字识别。 +这些预处理的方法在我的前面几篇博客都有提到了,大家可以参考参考: + +[透视矫正](https://www.cnblogs.com/skyfsm/p/7324346.html) + +[水平矫正](https://www.cnblogs.com/skyfsm/p/6902524.html) + +在预处理工作做好之后,我们就可以开始切割字符了。最普通的切割算法可以总结为以下几个步骤: + +对图片进行水平投影,找到每一行的上界限和下界限,进行行切割 +对切割出来的每一行,进行垂直投影,找到每一个字符的左右边界,进行单个字符的切割 +一看只有两个步骤,好像不太难,马上编程实现看看效果。 + +首先是行切割。这里提到了水平投影的概念,估计有的读者没听过这个名词,我来解释一下吧。水平投影,就是对一张图片的每一行元素进行统计(就是往水平方向统计),然后我们根据这个统计结果画出统计结果图,进而确定每一行的起始点和结束点。 +下面提到的垂直投影也是类似的,只是它的投影方向是往下的,即统计每一列的元素个数。 + diff --git a/opencv_app/project/TrafficLightDetection/TrafficLight.xml b/opencv_app/project/TrafficLightDetection/TrafficLight.xml new file mode 100644 index 00000000..842f7deb --- /dev/null +++ b/opencv_app/project/TrafficLightDetection/TrafficLight.xml @@ -0,0 +1,7721 @@ + + + + + 32 48 + + <_> + + <_> + <_> + + + <_> + 0 17 32 4 -1. + <_> + 8 17 16 4 2. + 0 + -0.0218745097517967 + 0.8975061178207398 + -0.7855733036994934 + <_> + <_> + + + <_> + 2 7 15 32 -1. + <_> + 7 7 5 32 3. + 0 + -0.0305939596146345 + 0.7952377796173096 + -0.4895249009132385 + <_> + <_> + + + <_> + 18 12 14 12 -1. + <_> + 15 15 14 6 2. + 1 + -0.0268830899149179 + 0.7531449794769287 + -0.3944652974605560 + <_> + <_> + + + <_> + 11 2 6 12 -1. + <_> + 11 6 6 4 3. + 0 + -9.8022399470210075e-003 + 0.6961730718612671 + -0.3479569852352142 + <_> + <_> + + + <_> + 3 11 6 13 -1. + <_> + 5 11 2 13 3. + 0 + -5.3088441491127014e-003 + 0.8113191723823547 + -0.2676127851009369 + -1.2062009572982788 + -1 + -1 + <_> + + <_> + <_> + + + <_> + 0 6 32 25 -1. + <_> + 8 6 16 25 2. + 0 + -0.1765801012516022 + 0.8014621734619141 + -0.6149455904960632 + <_> + <_> + + + <_> + 10 2 12 9 -1. + <_> + 10 5 12 3 3. + 0 + -0.0158672109246254 + 0.7699044942855835 + -0.3684819936752319 + <_> + <_> + + + <_> + 15 13 15 29 -1. + <_> + 20 13 5 29 3. + 0 + -0.0312508903443813 + 0.5884590148925781 + -0.3443016111850739 + <_> + <_> + + + <_> + 7 18 12 30 -1. + <_> + 7 33 12 15 2. + 0 + 5.4612178355455399e-003 + -0.5498496890068054 + 0.3117164969444275 + <_> + <_> + + + <_> + 10 9 2 32 -1. + <_> + 11 9 1 32 2. + 0 + 1.1829819995909929e-003 + -0.3565149009227753 + 0.5702667236328125 + <_> + <_> + + + <_> + 6 12 18 12 -1. + <_> + 12 16 6 4 9. + 0 + -0.0410475805401802 + 0.4932096898555756 + -0.3163577914237976 + <_> + <_> + + + <_> + 6 28 4 14 -1. + <_> + 7 28 2 14 2. + 0 + -2.1241600625216961e-003 + 0.6917337775230408 + -0.2443948984146118 + -1.8620860576629639 + 0 + -1 + <_> + + <_> + <_> + + + <_> + 0 15 32 6 -1. + <_> + 8 15 16 6 2. + 0 + -0.0590173304080963 + 0.7004452943801880 + -0.5502151846885681 + <_> + <_> + + + <_> + 10 2 15 12 -1. + <_> + 10 5 15 6 2. + 0 + -0.0159869901835918 + 0.5486698150634766 + -0.4056116044521332 + <_> + <_> + + + <_> + 15 9 16 14 -1. + <_> + 19 13 8 14 2. + 1 + -0.0552215985953808 + 0.5003771781921387 + -0.4194011986255646 + <_> + <_> + + + <_> + 3 8 12 33 -1. + <_> + 7 8 4 33 3. + 0 + -0.0450762696564198 + 0.5675873160362244 + -0.3151431083679199 + <_> + <_> + + + <_> + 18 24 8 24 -1. + <_> + 18 36 8 12 2. + 0 + 8.0440111923962831e-004 + -0.4764809906482697 + 0.3403803110122681 + <_> + <_> + + + <_> + 4 17 4 31 -1. + <_> + 5 17 2 31 2. + 0 + -2.6298209559172392e-003 + 0.6877502202987671 + -0.2265540063381195 + <_> + <_> + + + <_> + 15 46 9 1 -1. + <_> + 18 46 3 1 3. + 0 + -7.1021227631717920e-004 + 0.5902823209762573 + -0.2154971063137054 + <_> + <_> + + + <_> + 13 43 6 5 -1. + <_> + 15 43 2 5 3. + 0 + -1.6685070004314184e-003 + 0.6367638111114502 + -0.1942173987627029 + -1.1804800033569336 + 1 + -1 + <_> + + <_> + <_> + + + <_> + 0 6 32 23 -1. + <_> + 8 6 16 23 2. + 0 + -0.2216420024633408 + 0.6556056141853333 + -0.4604220986366272 + <_> + <_> + + + <_> + 9 2 17 9 -1. + <_> + 9 5 17 3 3. + 0 + -0.0243632700294256 + 0.5933312773704529 + -0.3064866960048676 + <_> + <_> + + + <_> + 12 6 7 33 -1. + <_> + 12 17 7 11 3. + 0 + -0.0486545003950596 + 0.4160378873348236 + -0.4347094893455505 + <_> + <_> + + + <_> + 7 30 20 18 -1. + <_> + 7 36 20 6 3. + 0 + -0.0249917395412922 + 0.4900675117969513 + -0.3649911880493164 + <_> + <_> + + + <_> + 12 4 2 5 -1. + <_> + 12 4 1 5 2. + 1 + 2.7416490484029055e-003 + -0.2430323958396912 + 0.6616610884666443 + <_> + <_> + + + <_> + 0 29 14 1 -1. + <_> + 7 29 7 1 2. + 0 + -3.4379099961370230e-003 + 0.5417212247848511 + -0.2432505041360855 + <_> + <_> + + + <_> + 16 35 10 10 -1. + <_> + 16 35 5 5 2. + <_> + 21 40 5 5 2. + 0 + 0.0115415398031473 + -0.2063425034284592 + 0.6839674711227417 + <_> + <_> + + + <_> + 10 5 9 4 -1. + <_> + 10 6 9 2 2. + 0 + 2.4196070153266191e-003 + -0.1540305018424988 + 0.8089500069618225 + <_> + <_> + + + <_> + 9 3 18 4 -1. + <_> + 9 4 18 2 2. + 0 + 4.1173771023750305e-003 + -0.1161938980221748 + 0.7194226980209351 + <_> + <_> + + + <_> + 5 6 6 16 -1. + <_> + 7 6 2 16 3. + 0 + -0.0111171295866370 + 0.6622462272644043 + -0.1781266033649445 + -1.0822410583496094 + 2 + -1 + <_> + + <_> + <_> + + + <_> + 16 18 16 1 -1. + <_> + 24 18 8 1 2. + 0 + 3.0777999199926853e-003 + -0.6651492714881897 + 0.4068110883235931 + <_> + <_> + + + <_> + 12 10 9 28 -1. + <_> + 15 10 3 28 3. + 0 + 4.2411950416862965e-003 + -0.5042582154273987 + 0.3802866935729981 + <_> + <_> + + + <_> + 0 0 14 12 -1. + <_> + 0 0 7 6 2. + <_> + 7 6 7 6 2. + 0 + -0.0155244702473283 + 0.4429385960102081 + -0.3817510902881622 + <_> + <_> + + + <_> + 7 0 19 48 -1. + <_> + 7 16 19 16 3. + 0 + -0.1563097983598709 + 0.3439775109291077 + -0.4976831972599030 + <_> + <_> + + + <_> + 2 30 27 18 -1. + <_> + 11 36 9 6 9. + 0 + -0.0787191689014435 + 0.4019029140472412 + -0.3583006858825684 + <_> + <_> + + + <_> + 9 8 8 32 -1. + <_> + 11 8 4 32 2. + 0 + 5.2453568205237389e-003 + -0.3118863105773926 + 0.4215934872627258 + <_> + <_> + + + <_> + 17 33 15 3 -1. + <_> + 22 33 5 3 3. + 0 + -7.6794810593128204e-003 + 0.5228086709976196 + -0.2538084983825684 + <_> + <_> + + + <_> + 16 45 3 3 -1. + <_> + 17 45 1 3 3. + 0 + 4.2081880383193493e-004 + -0.1758829951286316 + 0.7091686129570007 + <_> + <_> + + + <_> + 23 14 9 27 -1. + <_> + 23 23 9 9 3. + 0 + -0.0558755584061146 + -0.7098664045333862 + 0.2057686001062393 + <_> + <_> + + + <_> + 14 46 6 1 -1. + <_> + 16 46 2 1 3. + 0 + -6.3265068456530571e-004 + 0.6239765286445618 + -0.2170017957687378 + -1.2463330030441284 + 3 + -1 + <_> + + <_> + <_> + + + <_> + 0 5 32 26 -1. + <_> + 8 5 16 26 2. + 0 + -0.1881130933761597 + 0.4952228069305420 + -0.5445271730422974 + <_> + <_> + + + <_> + 19 7 9 31 -1. + <_> + 22 7 3 31 3. + 0 + -0.0416516289114952 + 0.6643825173377991 + -0.2265163958072662 + <_> + <_> + + + <_> + 9 1 7 12 -1. + <_> + 9 4 7 6 2. + 0 + -0.0109009696170688 + 0.4314399957656860 + -0.3018642067909241 + <_> + <_> + + + <_> + 16 7 16 15 -1. + <_> + 11 12 16 5 3. + 1 + -0.0972250178456306 + 0.4415077865123749 + -0.2800396978855133 + <_> + <_> + + + <_> + 6 33 4 4 -1. + <_> + 7 33 2 4 2. + 0 + -1.1660070158541203e-003 + 0.6759309172630310 + -0.1754194945096970 + <_> + <_> + + + <_> + 26 9 2 16 -1. + <_> + 26 13 2 8 2. + 0 + -2.2334600798785686e-003 + -0.5722131133079529 + 0.2003547996282578 + <_> + <_> + + + <_> + 6 10 3 3 -1. + <_> + 7 10 1 3 3. + 0 + 7.1577017661184072e-004 + -0.1459915041923523 + 0.7640817165374756 + <_> + <_> + + + <_> + 6 11 4 4 -1. + <_> + 7 11 2 4 2. + 0 + -1.6721970168873668e-003 + 0.7303234934806824 + -0.1121110990643501 + <_> + <_> + + + <_> + 6 1 12 22 -1. + <_> + 6 12 12 11 2. + 0 + -0.0243021100759506 + 0.2496646046638489 + -0.4811781048774719 + <_> + <_> + + + <_> + 15 23 3 12 -1. + <_> + 15 26 3 6 2. + 0 + -4.8862108960747719e-003 + 0.5166280865669251 + -0.2303497046232224 + <_> + <_> + + + <_> + 10 24 9 24 -1. + <_> + 10 32 9 8 3. + 0 + -0.0177276507019997 + 0.4464916884899139 + -0.2848205864429474 + <_> + <_> + + + <_> + 11 2 10 6 -1. + <_> + 11 4 10 2 3. + 0 + 7.2767292149364948e-003 + -0.1669079065322876 + 0.5878301858901978 + <_> + <_> + + + <_> + 14 0 10 5 -1. + <_> + 19 0 5 5 2. + 0 + -3.9053950458765030e-003 + -0.5930811166763306 + 0.2007322013378143 + -1.1375039815902710 + 4 + -1 + <_> + + <_> + <_> + + + <_> + 0 6 32 24 -1. + <_> + 8 6 16 24 2. + 0 + -0.2814126014709473 + 0.7154381275177002 + -0.3515818119049072 + <_> + <_> + + + <_> + 10 0 12 15 -1. + <_> + 10 5 12 5 3. + 0 + -0.0376315899193287 + 0.5602353811264038 + -0.3522501885890961 + <_> + <_> + + + <_> + 11 7 8 33 -1. + <_> + 11 18 8 11 3. + 0 + -0.0456619597971439 + 0.2809210121631622 + -0.4472259879112244 + <_> + <_> + + + <_> + 6 9 11 4 -1. + <_> + 6 9 11 2 2. + 1 + -2.7991449460387230e-003 + 0.2989613115787506 + -0.3861038982868195 + <_> + <_> + + + <_> + 11 13 8 23 -1. + <_> + 13 13 4 23 2. + 0 + 1.6904779477044940e-003 + -0.3974553942680359 + 0.3117608129978180 + <_> + <_> + + + <_> + 1 21 30 27 -1. + <_> + 11 30 10 9 9. + 0 + -0.4000712037086487 + 0.6357200741767883 + -0.1967588067054749 + <_> + <_> + + + <_> + 15 6 6 33 -1. + <_> + 17 6 2 33 3. + 0 + 1.0170850437134504e-003 + -0.3968569934368134 + 0.3349072933197022 + <_> + <_> + + + <_> + 18 6 6 33 -1. + <_> + 20 6 2 33 3. + 0 + 2.5362719316035509e-003 + -0.2757635116577148 + 0.4357610940933228 + <_> + <_> + + + <_> + 4 1 27 18 -1. + <_> + 13 7 9 6 9. + 0 + -0.2455938011407852 + 0.6207857728004456 + -0.1880972981452942 + <_> + <_> + + + <_> + 11 5 8 6 -1. + <_> + 11 7 8 2 3. + 0 + 6.3347448594868183e-003 + -0.1796204000711441 + 0.7256529927253723 + <_> + <_> + + + <_> + 1 5 5 8 -1. + <_> + 1 9 5 4 2. + 0 + 5.5937832221388817e-003 + 0.1601283997297287 + -0.7509906888008118 + <_> + <_> + + + <_> + 4 7 3 9 -1. + <_> + 5 7 1 9 3. + 0 + -2.0763180218636990e-003 + 0.7953718900680542 + -0.1473286002874374 + -1.0925780534744263 + 5 + -1 + <_> + + <_> + <_> + + + <_> + 0 18 32 1 -1. + <_> + 8 18 16 1 2. + 0 + -0.0146832698956132 + 0.5792641043663025 + -0.3574607968330383 + <_> + <_> + + + <_> + 15 30 15 11 -1. + <_> + 20 30 5 11 3. + 0 + -0.0272596292197704 + 0.5344812273979187 + -0.2716957032680512 + <_> + <_> + + + <_> + 9 4 15 4 -1. + <_> + 9 5 15 2 2. + 0 + -5.5869170464575291e-003 + 0.6362134814262390 + -0.1798384934663773 + <_> + <_> + + + <_> + 12 34 6 6 -1. + <_> + 10 36 6 2 3. + 1 + -8.8016483932733536e-003 + 0.6091176867485046 + -0.2043260931968689 + <_> + <_> + + + <_> + 30 0 2 10 -1. + <_> + 30 5 2 5 2. + 0 + -3.5758540034294128e-003 + -0.5671203732490540 + 0.2164247930049896 + <_> + <_> + + + <_> + 22 35 4 2 -1. + <_> + 23 35 2 2 2. + 0 + 4.4419069308787584e-004 + -0.1151377037167549 + 0.7472153902053833 + <_> + <_> + + + <_> + 20 30 4 8 -1. + <_> + 21 30 2 8 2. + 0 + 1.6317500267177820e-003 + -0.1306069046258926 + 0.7388030290603638 + <_> + <_> + + + <_> + 14 7 4 6 -1. + <_> + 14 10 4 3 2. + 0 + 2.0566860621329397e-004 + -0.3404084146022797 + 0.3151192963123322 + <_> + <_> + + + <_> + 16 0 14 24 -1. + <_> + 16 12 14 12 2. + 0 + -0.0140403695404530 + 0.1764649003744125 + -0.5562359094619751 + <_> + <_> + + + <_> + 0 0 5 20 -1. + <_> + 0 5 5 10 2. + 0 + -0.0132652902975678 + -0.7366558909416199 + 0.0997700169682503 + <_> + <_> + + + <_> + 3 0 28 4 -1. + <_> + 17 0 14 4 2. + 0 + 0.0230848491191864 + 0.1662147045135498 + -0.6236956715583801 + <_> + <_> + + + <_> + 11 36 8 3 -1. + <_> + 10 37 8 1 3. + 1 + 2.3849350400269032e-003 + -0.1558035016059876 + 0.7287256121635437 + <_> + <_> + + + <_> + 3 7 6 32 -1. + <_> + 3 15 6 16 2. + 0 + -0.0314990393817425 + -0.5446755290031433 + 0.1761175990104675 + -1.0776499509811401 + 6 + -1 + <_> + + <_> + <_> + + + <_> + 7 0 17 10 -1. + <_> + 7 5 17 5 2. + 0 + -0.0391186587512493 + 0.3852876126766205 + -0.4454804062843323 + <_> + <_> + + + <_> + 16 8 16 16 -1. + <_> + 20 12 8 16 2. + 1 + -0.0615105703473091 + 0.3085057139396668 + -0.4392845034599304 + <_> + <_> + + + <_> + 10 12 4 27 -1. + <_> + 12 12 2 27 2. + 0 + 1.0512729641050100e-003 + -0.4196395874023438 + 0.2862440943717957 + <_> + <_> + + + <_> + 13 17 4 4 -1. + <_> + 13 17 4 2 2. + 1 + 1.8050030339509249e-003 + 0.2048400044441223 + -0.5999863743782044 + <_> + <_> + + + <_> + 21 12 11 33 -1. + <_> + 21 23 11 11 3. + 0 + 0.0161220505833626 + 0.1747801005840302 + -0.5925865769386292 + <_> + <_> + + + <_> + 12 18 16 2 -1. + <_> + 12 18 16 1 2. + 1 + 1.9041889754589647e-004 + -0.3267045021057129 + 0.2883198857307434 + <_> + <_> + + + <_> + 19 11 2 26 -1. + <_> + 20 11 1 26 2. + 0 + -2.3807919933460653e-004 + 0.2600775063037872 + -0.3423070907592773 + <_> + <_> + + + <_> + 13 4 6 6 -1. + <_> + 13 6 6 2 3. + 0 + 5.9077828191220760e-003 + -0.1691561043262482 + 0.6540285944938660 + <_> + <_> + + + <_> + 8 3 18 9 -1. + <_> + 8 6 18 3 3. + 0 + -0.0257809497416019 + 0.4036684930324554 + -0.1991758048534393 + <_> + <_> + + + <_> + 2 7 24 30 -1. + <_> + 10 17 8 10 9. + 0 + -0.2110837996006012 + 0.2368118017911911 + -0.4031893014907837 + <_> + <_> + + + <_> + 14 16 4 14 -1. + <_> + 16 16 2 14 2. + 0 + 3.0627390369772911e-003 + 0.1394497007131577 + -0.5929412841796875 + <_> + <_> + + + <_> + 17 21 12 6 -1. + <_> + 17 21 12 3 2. + 1 + 0.0215592794120312 + -0.1606997996568680 + 0.5343831181526184 + <_> + <_> + + + <_> + 22 7 2 29 -1. + <_> + 23 7 1 29 2. + 0 + -1.1500320397317410e-003 + 0.4869709908962250 + -0.1791218966245651 + <_> + <_> + + + <_> + 11 25 7 18 -1. + <_> + 11 31 7 6 3. + 0 + 0.0656065791845322 + -0.1136296987533569 + 0.6726086139678955 + <_> + <_> + + + <_> + 19 29 12 3 -1. + <_> + 25 29 6 3 2. + 0 + 4.5243669301271439e-003 + -0.3268114924430847 + 0.2491164058446884 + <_> + <_> + + + <_> + 14 47 3 1 -1. + <_> + 15 47 1 1 3. + 0 + 1.7844549438450485e-004 + -0.1259890943765640 + 0.5774288773536682 + <_> + <_> + + + <_> + 14 47 3 1 -1. + <_> + 15 47 1 1 3. + 0 + -1.6106219845823944e-004 + 0.5699470043182373 + -0.1239940002560616 + -1.2768460512161255 + 7 + -1 + <_> + + <_> + <_> + + + <_> + 13 12 6 26 -1. + <_> + 15 12 2 26 3. + 0 + 5.1357760639803018e-006 + -0.5463433265686035 + 0.2502805888652802 + <_> + <_> + + + <_> + 1 6 12 14 -1. + <_> + 7 6 6 14 2. + 0 + -0.0346261896193028 + 0.2543446123600006 + -0.4589630961418152 + <_> + <_> + + + <_> + 11 11 10 24 -1. + <_> + 11 17 10 12 2. + 0 + -0.0239239893853664 + 0.2803201079368591 + -0.3934690952301025 + <_> + <_> + + + <_> + 21 0 11 6 -1. + <_> + 21 0 11 3 2. + 1 + 0.0332736708223820 + -0.2692402899265289 + 0.4240899980068207 + <_> + <_> + + + <_> + 17 39 1 8 -1. + <_> + 17 39 1 4 2. + 1 + -1.6080209752544761e-003 + 0.3633139133453369 + -0.2886041998863220 + <_> + <_> + + + <_> + 10 11 6 28 -1. + <_> + 12 11 2 28 3. + 0 + 1.2169140391051769e-003 + -0.3074459135532379 + 0.3004981875419617 + <_> + <_> + + + <_> + 16 20 2 9 -1. + <_> + 16 23 2 3 3. + 0 + 4.9603440857026726e-005 + -0.3494226038455963 + 0.2525396943092346 + <_> + <_> + + + <_> + 16 8 6 31 -1. + <_> + 18 8 2 31 3. + 0 + 1.3759690336883068e-003 + -0.2647993862628937 + 0.3145459890365601 + <_> + <_> + + + <_> + 6 0 18 24 -1. + <_> + 12 8 6 8 9. + 0 + -0.1855888068675995 + 0.4475226998329163 + -0.2138957977294922 + <_> + <_> + + + <_> + 8 1 12 9 -1. + <_> + 8 4 12 3 3. + 0 + -0.0226572602987289 + 0.4830267131328583 + -0.1591649055480957 + <_> + <_> + + + <_> + 10 2 8 45 -1. + <_> + 10 17 8 15 3. + 0 + -0.0691973268985748 + 0.1716523021459580 + -0.4074114859104157 + <_> + <_> + + + <_> + 6 23 3 12 -1. + <_> + 7 23 1 12 3. + 0 + -2.4569479282945395e-003 + 0.6122543811798096 + -0.1195200979709625 + <_> + <_> + + + <_> + 14 47 4 1 -1. + <_> + 15 47 2 1 2. + 0 + 2.2052100393921137e-004 + -0.1315250992774963 + 0.5343679785728455 + <_> + <_> + + + <_> + 16 17 16 1 -1. + <_> + 24 17 8 1 2. + 0 + 1.6309299971908331e-003 + -0.4878408014774323 + 0.1766172945499420 + <_> + <_> + + + <_> + 21 6 4 42 -1. + <_> + 21 6 2 21 2. + <_> + 23 27 2 21 2. + 0 + 8.9546963572502136e-003 + -0.1567454040050507 + 0.5772156119346619 + <_> + <_> + + + <_> + 22 32 4 10 -1. + <_> + 23 33 2 10 2. + 1 + 3.4682389814406633e-003 + -0.1574091017246246 + 0.5617622733116150 + <_> + <_> + + + <_> + 12 8 6 6 -1. + <_> + 12 11 6 3 2. + 0 + 6.6259621235076338e-005 + -0.3336561024188995 + 0.2673544883728027 + <_> + <_> + + + <_> + 4 2 10 24 -1. + <_> + 4 14 10 12 2. + 0 + -9.1350331786088645e-005 + 0.1239653006196022 + -0.6334651112556458 + <_> + <_> + + + <_> + 14 44 4 4 -1. + <_> + 15 44 2 4 2. + 0 + -5.9831532416865230e-004 + 0.4568153023719788 + -0.1997597962617874 + <_> + <_> + + + <_> + 14 14 6 25 -1. + <_> + 16 14 2 25 3. + 0 + 1.0653310164343566e-004 + -0.3202087879180908 + 0.2439759969711304 + <_> + <_> + + + <_> + 6 31 3 2 -1. + <_> + 7 31 1 2 3. + 0 + 3.6885248846374452e-004 + -0.1944434940814972 + 0.5452955961227417 + <_> + <_> + + + <_> + 11 7 6 30 -1. + <_> + 13 7 2 30 3. + 0 + 3.3100589644163847e-004 + -0.3451220989227295 + 0.2572900950908661 + <_> + <_> + + + <_> + 6 2 15 21 -1. + <_> + 11 9 5 7 9. + 0 + -0.0546734593808651 + 0.3515861034393311 + -0.3467364907264710 + -1.4787969589233398 + 8 + -1 + <_> + + <_> + <_> + + + <_> + 0 5 32 25 -1. + <_> + 8 5 16 25 2. + 0 + -0.2022158950567246 + 0.4426831901073456 + -0.4989081919193268 + <_> + <_> + + + <_> + 14 9 3 31 -1. + <_> + 15 9 1 31 3. + 0 + -9.5231708837673068e-004 + -0.6792523860931397 + 0.1949152946472168 + <_> + <_> + + + <_> + 14 13 3 18 -1. + <_> + 15 13 1 18 3. + 0 + 1.6709800111129880e-003 + 0.1647866070270538 + -0.8015493750572205 + <_> + <_> + + + <_> + 0 0 32 1 -1. + <_> + 8 0 16 1 2. + 0 + -6.2497509643435478e-003 + -0.7179738879203796 + 0.1703695058822632 + <_> + <_> + + + <_> + 15 6 16 33 -1. + <_> + 19 6 8 33 2. + 0 + -0.0541259199380875 + 0.3206759095191956 + -0.3532192111015320 + <_> + <_> + + + <_> + 19 11 9 6 -1. + <_> + 19 11 9 3 2. + 1 + 0.0199727397412062 + -0.2222384065389633 + 0.4241591989994049 + <_> + <_> + + + <_> + 11 24 10 12 -1. + <_> + 11 28 10 4 3. + 0 + -0.0232687704265118 + 0.5303568243980408 + -0.1893332004547119 + <_> + <_> + + + <_> + 8 27 15 21 -1. + <_> + 8 34 15 7 3. + 0 + -0.0258632004261017 + 0.4164674878120422 + -0.2726373076438904 + <_> + <_> + + + <_> + 13 19 5 20 -1. + <_> + 13 29 5 10 2. + 0 + 0.0583295598626137 + -0.1586326956748962 + 0.7568194866180420 + <_> + <_> + + + <_> + 9 1 9 6 -1. + <_> + 12 4 3 6 3. + 1 + -0.0258279498666525 + 0.5293679237365723 + -0.1929772943258286 + <_> + <_> + + + <_> + 13 2 6 9 -1. + <_> + 13 2 3 9 2. + 1 + 0.0312921889126301 + -0.1840668022632599 + 0.5067638158798218 + <_> + <_> + + + <_> + 12 10 8 28 -1. + <_> + 12 24 8 14 2. + 0 + -0.0300902798771858 + 0.4706341922283173 + -0.2114782929420471 + <_> + <_> + + + <_> + 14 9 4 32 -1. + <_> + 14 25 4 16 2. + 0 + 0.0419703312218189 + -0.1572566926479340 + 0.4931587874889374 + -1.3628530502319336 + 9 + -1 + <_> + + <_> + <_> + + + <_> + 0 18 32 1 -1. + <_> + 8 18 16 1 2. + 0 + -0.0133225601166487 + 0.3342022001743317 + -0.3411031067371368 + <_> + <_> + + + <_> + 22 30 8 10 -1. + <_> + 24 32 4 10 2. + 1 + -0.0173518303781748 + 0.4936828911304474 + -0.1899081021547318 + <_> + <_> + + + <_> + 9 3 14 6 -1. + <_> + 9 5 14 2 3. + 0 + -0.0178806800395250 + 0.5169709920883179 + -0.1688573956489563 + <_> + <_> + + + <_> + 13 24 2 12 -1. + <_> + 14 24 1 12 2. + 0 + -4.7262210864573717e-004 + -0.5554103255271912 + 0.1423164010047913 + <_> + <_> + + + <_> + 10 34 9 4 -1. + <_> + 9 35 9 2 2. + 1 + -5.8351308107376099e-003 + 0.5858452916145325 + -0.1269195973873138 + <_> + <_> + + + <_> + 14 12 5 28 -1. + <_> + 14 26 5 14 2. + 0 + -0.0168039705604315 + 0.3879500925540924 + -0.1880125999450684 + <_> + <_> + + + <_> + 16 18 2 6 -1. + <_> + 16 18 2 3 2. + 1 + 1.3198519591242075e-003 + 0.2171746939420700 + -0.4963554143905640 + <_> + <_> + + + <_> + 9 4 12 6 -1. + <_> + 9 7 12 3 2. + 0 + -0.0259042605757713 + 0.4659473896026611 + -0.1784226000308991 + <_> + <_> + + + <_> + 7 8 16 30 -1. + <_> + 7 18 16 10 3. + 0 + -0.0408573001623154 + 0.1554705947637558 + -0.4373931884765625 + <_> + <_> + + + <_> + 6 9 10 2 -1. + <_> + 6 9 10 1 2. + 1 + -1.6666549490764737e-003 + 0.2951743900775909 + -0.2478168010711670 + <_> + <_> + + + <_> + 9 9 2 32 -1. + <_> + 10 9 1 32 2. + 0 + 1.5287280548363924e-003 + -0.1975719034671783 + 0.3827919065952301 + <_> + <_> + + + <_> + 5 21 24 27 -1. + <_> + 13 30 8 9 9. + 0 + -0.2767542898654938 + 0.4831961989402771 + -0.1660057008266449 + <_> + <_> + + + <_> + 13 3 4 22 -1. + <_> + 13 3 2 11 2. + <_> + 15 14 2 11 2. + 0 + -2.7170139364898205e-003 + -0.5373407006263733 + 0.1583137065172195 + <_> + <_> + + + <_> + 10 3 10 18 -1. + <_> + 10 3 5 9 2. + <_> + 15 12 5 9 2. + 0 + 0.0115381097421050 + 0.1030127033591270 + -0.6449890136718750 + <_> + <_> + + + <_> + 23 32 4 10 -1. + <_> + 24 33 2 10 2. + 1 + 4.7883410006761551e-003 + -0.1281580030918121 + 0.5838270187377930 + <_> + <_> + + + <_> + 18 14 4 23 -1. + <_> + 20 14 2 23 2. + 0 + -1.3079680502414703e-003 + 0.2581051886081696 + -0.2630183100700378 + <_> + <_> + + + <_> + 6 27 24 3 -1. + <_> + 14 28 8 1 9. + 0 + -9.1663817875087261e-004 + 0.1461535990238190 + -0.4175851941108704 + <_> + <_> + + + <_> + 5 13 6 14 -1. + <_> + 5 20 6 7 2. + 0 + 0.0110543901100755 + 0.0738277062773705 + -0.6955193877220154 + <_> + <_> + + + <_> + 15 47 3 1 -1. + <_> + 16 47 1 1 3. + 0 + 1.2170850095571950e-004 + -0.1491042971611023 + 0.3751587867736816 + <_> + <_> + + + <_> + 12 1 20 3 -1. + <_> + 22 1 10 3 2. + 0 + -9.2606823891401291e-003 + -0.5772761106491089 + 0.0933944731950760 + <_> + <_> + + + <_> + 20 17 2 4 -1. + <_> + 20 17 1 4 2. + 1 + 4.1007250547409058e-004 + 0.1308607012033463 + -0.3923696875572205 + -1.2182730436325073 + 10 + -1 + <_> + + <_> + <_> + + + <_> + 13 1 4 10 -1. + <_> + 13 1 2 10 2. + 1 + 0.0182647891342640 + -0.2458876073360443 + 0.4469409883022308 + <_> + <_> + + + <_> + 12 5 8 33 -1. + <_> + 14 5 4 33 2. + 0 + 2.2555470932275057e-003 + -0.4243207871913910 + 0.2456026971340179 + <_> + <_> + + + <_> + 15 7 17 15 -1. + <_> + 10 12 17 5 3. + 1 + -0.1071159988641739 + 0.3202598989009857 + -0.2489165961742401 + <_> + <_> + + + <_> + 12 7 20 11 -1. + <_> + 17 7 10 11 2. + 0 + -0.0296763703227043 + 0.3156779110431671 + -0.2237775027751923 + <_> + <_> + + + <_> + 15 37 10 1 -1. + <_> + 15 37 5 1 2. + 1 + -3.6467718891799450e-003 + 0.3602007031440735 + -0.1997299939393997 + <_> + <_> + + + <_> + 17 10 6 29 -1. + <_> + 19 10 2 29 3. + 0 + 1.1497730156406760e-003 + -0.2384368926286697 + 0.2906086146831513 + <_> + <_> + + + <_> + 20 2 7 6 -1. + <_> + 20 2 7 3 2. + 1 + 0.0278956200927496 + -0.1536498069763184 + 0.5127211213111877 + <_> + <_> + + + <_> + 9 33 9 6 -1. + <_> + 7 35 9 2 3. + 1 + -0.0163637902587652 + 0.5491611957550049 + -0.1244503036141396 + <_> + <_> + + + <_> + 8 1 15 9 -1. + <_> + 8 4 15 3 3. + 0 + -0.0344880595803261 + 0.4778347909450531 + -0.1156195998191834 + <_> + <_> + + + <_> + 11 33 8 4 -1. + <_> + 10 34 8 2 2. + 1 + -7.3130670934915543e-003 + 0.6449282169342041 + -0.1212799996137619 + <_> + <_> + + + <_> + 12 1 6 7 -1. + <_> + 14 3 2 7 3. + 1 + 8.7166950106620789e-003 + -0.1142463982105255 + 0.5577235221862793 + <_> + <_> + + + <_> + 12 15 16 12 -1. + <_> + 8 19 16 4 3. + 1 + -0.0396253503859043 + 0.4199005067348480 + -0.1670874953269959 + <_> + <_> + + + <_> + 17 7 1 30 -1. + <_> + 17 17 1 10 3. + 0 + -7.0857270620763302e-003 + 0.2166838049888611 + -0.2644016146659851 + <_> + <_> + + + <_> + 3 2 29 12 -1. + <_> + 3 5 29 6 2. + 0 + -8.8340640068054199e-003 + 0.1900839954614639 + -0.3632022142410278 + <_> + <_> + + + <_> + 7 0 9 2 -1. + <_> + 7 0 9 1 2. + 1 + 4.1646980680525303e-003 + 0.0692129433155060 + -0.7270056009292603 + <_> + <_> + + + <_> + 15 25 3 3 -1. + <_> + 16 25 1 3 3. + 0 + -3.1318218680098653e-004 + -0.6093580722808838 + 0.0750923827290535 + <_> + <_> + + + <_> + 24 21 7 16 -1. + <_> + 24 25 7 8 2. + 0 + -6.8199750967323780e-003 + -0.4836550056934357 + 0.1037606000900269 + <_> + <_> + + + <_> + 9 0 7 6 -1. + <_> + 9 0 7 3 2. + 1 + -0.0195161793380976 + -0.7686462998390198 + 0.0658475607633591 + <_> + <_> + + + <_> + 30 0 1 15 -1. + <_> + 30 5 1 5 3. + 0 + -2.6757840532809496e-003 + -0.5501589179039002 + 0.0819720774888992 + <_> + <_> + + + <_> + 11 25 7 12 -1. + <_> + 11 29 7 4 3. + 0 + -2.1882040891796350e-003 + 0.2227405011653900 + -0.2327487021684647 + <_> + <_> + + + <_> + 5 5 8 36 -1. + <_> + 5 5 4 18 2. + <_> + 9 23 4 18 2. + 0 + 0.0446752198040485 + -0.1087931990623474 + 0.4678288996219635 + <_> + <_> + + + <_> + 10 24 11 24 -1. + <_> + 10 32 11 8 3. + 0 + -0.0180339496582747 + 0.3013502061367035 + -0.2257715016603470 + -1.1566350460052490 + 11 + -1 + <_> + + <_> + <_> + + + <_> + 0 4 14 15 -1. + <_> + 7 4 7 15 2. + 0 + -0.0567807182669640 + 0.2626147866249085 + -0.3585151135921478 + <_> + <_> + + + <_> + 16 10 1 28 -1. + <_> + 16 17 1 14 2. + 0 + -6.1715459451079369e-003 + 0.2763979136943817 + -0.3066428005695343 + <_> + <_> + + + <_> + 17 20 2 13 -1. + <_> + 18 20 1 13 2. + 0 + 3.5895919427275658e-004 + 0.1413145959377289 + -0.5034450888633728 + <_> + <_> + + + <_> + 16 12 6 23 -1. + <_> + 18 12 2 23 3. + 0 + -3.7504630745388567e-004 + -0.2605223953723908 + 0.2736341953277588 + <_> + <_> + + + <_> + 27 10 4 10 -1. + <_> + 27 10 2 10 2. + 1 + -3.5705089103430510e-003 + 0.1979576051235199 + -0.3845691978931427 + <_> + <_> + + + <_> + 10 45 12 3 -1. + <_> + 14 45 4 3 3. + 0 + -4.4579240493476391e-003 + 0.3969258069992065 + -0.1694658994674683 + <_> + <_> + + + <_> + 12 11 5 30 -1. + <_> + 12 26 5 15 2. + 0 + -0.0143890902400017 + 0.3182103931903839 + -0.2065501958131790 + <_> + <_> + + + <_> + 2 0 30 12 -1. + <_> + 2 6 30 6 2. + 0 + -0.0487453490495682 + 0.2089453935623169 + -0.3286783099174500 + <_> + <_> + + + <_> + 12 4 6 33 -1. + <_> + 12 15 6 11 3. + 0 + -0.0311932396143675 + 0.1557905972003937 + -0.3866128027439117 + <_> + <_> + + + <_> + 11 13 6 27 -1. + <_> + 13 13 2 27 3. + 0 + 2.7526040867087431e-005 + -0.3117986023426056 + 0.2018004953861237 + <_> + <_> + + + <_> + 2 28 27 3 -1. + <_> + 11 29 9 1 9. + 0 + -9.7433589398860931e-003 + 0.1438522040843964 + -0.3583754003047943 + <_> + <_> + + + <_> + 19 26 8 6 -1. + <_> + 17 28 8 2 3. + 1 + 0.0116548100486398 + -0.1048706993460655 + 0.5900533199310303 + <_> + <_> + + + <_> + 12 28 12 20 -1. + <_> + 12 33 12 10 2. + 0 + -5.1200147718191147e-003 + 0.2339573055505753 + -0.2520189881324768 + <_> + <_> + + + <_> + 15 23 2 15 -1. + <_> + 15 28 2 5 3. + 0 + -5.2731940522789955e-003 + 0.3535105884075165 + -0.1611499041318893 + <_> + <_> + + + <_> + 11 6 4 4 -1. + <_> + 12 7 2 4 2. + 1 + 2.7859129477292299e-003 + -0.0967521369457245 + 0.6048477292060852 + <_> + <_> + + + <_> + 13 7 6 6 -1. + <_> + 13 10 6 3 2. + 0 + 4.5158120337873697e-004 + -0.2591809034347534 + 0.2127479016780853 + <_> + <_> + + + <_> + 4 6 24 7 -1. + <_> + 12 6 8 7 3. + 0 + -0.0389086194336414 + 0.2443124949932098 + -0.2394285947084427 + <_> + <_> + + + <_> + 10 8 2 31 -1. + <_> + 11 8 1 31 2. + 0 + 7.4827182106673717e-004 + -0.2368014007806778 + 0.2460877001285553 + <_> + <_> + + + <_> + 14 46 4 2 -1. + <_> + 15 46 2 2 2. + 0 + 3.5381168709136546e-004 + -0.1494600027799606 + 0.3718386888504028 + <_> + <_> + + + <_> + 11 17 3 2 -1. + <_> + 11 17 3 1 2. + 1 + 7.8486057464033365e-004 + 0.1019195988774300 + -0.5606232285499573 + <_> + <_> + + + <_> + 0 8 30 33 -1. + <_> + 10 19 10 11 9. + 0 + -0.4360947906970978 + 0.1819971054792404 + -0.2785970866680145 + <_> + <_> + + + <_> + 18 21 4 5 -1. + <_> + 20 21 2 5 2. + 0 + -1.1402939708204940e-004 + 0.2355592995882034 + -0.2397909015417099 + <_> + <_> + + + <_> + 14 22 3 7 -1. + <_> + 15 22 1 7 3. + 0 + -5.6736369151622057e-004 + -0.6222413182258606 + 0.0864567905664444 + <_> + <_> + + + <_> + 17 10 8 6 -1. + <_> + 19 10 4 6 2. + 0 + 2.0343179348856211e-003 + -0.1601565927267075 + 0.3457680046558380 + <_> + <_> + + + <_> + 22 32 6 7 -1. + <_> + 24 34 2 7 3. + 1 + 0.0142263602465391 + -0.0735971331596375 + 0.6207298040390015 + <_> + <_> + + + <_> + 1 28 7 20 -1. + <_> + 1 33 7 10 2. + 0 + 6.3095060177147388e-003 + 0.1227357983589172 + -0.3991366028785706 + -1.1522890329360962 + 12 + -1 + <_> + + <_> + <_> + + + <_> + 13 6 8 32 -1. + <_> + 15 6 4 32 2. + 0 + 3.5659680142998695e-003 + -0.3347742855548859 + 0.2175834029912949 + <_> + <_> + + + <_> + 13 2 2 10 -1. + <_> + 13 2 1 10 2. + 1 + 4.1590621694922447e-003 + -0.2538071870803833 + 0.3003436923027039 + <_> + <_> + + + <_> + 7 42 18 6 -1. + <_> + 13 42 6 6 3. + 0 + -0.0117900297045708 + 0.2951912879943848 + -0.2002981007099152 + <_> + <_> + + + <_> + 23 11 9 6 -1. + <_> + 23 11 9 3 2. + 1 + 0.0101436302065849 + -0.4304685890674591 + 0.1369518041610718 + <_> + <_> + + + <_> + 8 29 15 9 -1. + <_> + 13 32 5 3 9. + 0 + 0.0818177908658981 + -0.0899346694350243 + 0.5714123845100403 + <_> + <_> + + + <_> + 14 10 14 30 -1. + <_> + 14 10 7 15 2. + <_> + 21 25 7 15 2. + 0 + 0.0290596093982458 + -0.1582432985305786 + 0.4631207883358002 + <_> + <_> + + + <_> + 10 3 14 18 -1. + <_> + 10 3 7 9 2. + <_> + 17 12 7 9 2. + 0 + -0.0146658504381776 + -0.5074486732482910 + 0.1108788028359413 + <_> + <_> + + + <_> + 19 0 8 12 -1. + <_> + 16 3 8 6 2. + 1 + -0.0238735992461443 + 0.2993986010551453 + -0.2125084996223450 + <_> + <_> + + + <_> + 9 0 8 6 -1. + <_> + 11 2 4 6 2. + 1 + -0.0260215401649475 + 0.6607018709182739 + -0.1079628020524979 + <_> + <_> + + + <_> + 17 7 6 32 -1. + <_> + 19 7 2 32 3. + 0 + 1.0719819692894816e-003 + -0.1762654036283493 + 0.2959679067134857 + <_> + <_> + + + <_> + 15 15 4 8 -1. + <_> + 17 15 2 8 2. + 0 + 1.3768200296908617e-003 + 0.0958962365984917 + -0.5049006938934326 + <_> + <_> + + + <_> + 23 11 2 14 -1. + <_> + 23 11 1 14 2. + 1 + -2.2588151041418314e-003 + 0.3923125863075256 + -0.1378747969865799 + <_> + <_> + + + <_> + 13 7 6 30 -1. + <_> + 15 17 2 10 9. + 0 + -0.0134190302342176 + 0.1422670036554337 + -0.4513286054134369 + <_> + <_> + + + <_> + 13 17 19 12 -1. + <_> + 9 21 19 4 3. + 1 + -0.0494457110762596 + 0.3507763147354126 + -0.1786850988864899 + <_> + <_> + + + <_> + 10 9 12 4 -1. + <_> + 10 9 12 2 2. + 1 + -0.0101562896743417 + 0.4219771027565002 + -0.1445077955722809 + <_> + <_> + + + <_> + 16 27 9 8 -1. + <_> + 14 29 9 4 2. + 1 + 0.0237737093120813 + -0.1057965978980064 + 0.4062871038913727 + <_> + <_> + + + <_> + 23 10 4 3 -1. + <_> + 24 10 2 3 2. + 0 + -1.3737389817833900e-003 + 0.5441873073577881 + -0.0874131098389626 + <_> + <_> + + + <_> + 0 0 28 2 -1. + <_> + 14 0 14 2 2. + 0 + -3.0952550005167723e-003 + -0.3420327007770538 + 0.1515717953443527 + <_> + <_> + + + <_> + 19 2 13 42 -1. + <_> + 19 16 13 14 3. + 0 + -0.1967415958642960 + -0.7698674201965332 + 0.0496639087796211 + <_> + <_> + + + <_> + 14 8 6 18 -1. + <_> + 14 17 6 9 2. + 0 + 2.7587029617279768e-003 + 0.1005211025476456 + -0.4521270096302033 + <_> + <_> + + + <_> + 16 16 4 17 -1. + <_> + 17 16 2 17 2. + 0 + -7.6133961556479335e-004 + -0.3513661921024323 + 0.1325466036796570 + <_> + <_> + + + <_> + 13 24 12 24 -1. + <_> + 17 32 4 8 9. + 0 + -0.0405589006841183 + 0.2406090050935745 + -0.2368506938219070 + <_> + <_> + + + <_> + 6 10 2 30 -1. + <_> + 6 10 1 15 2. + <_> + 7 25 1 15 2. + 0 + 4.9466909840703011e-003 + -0.0865392312407494 + 0.5191279053688049 + <_> + <_> + + + <_> + 5 30 6 12 -1. + <_> + 7 30 2 12 3. + 0 + -5.9373970143496990e-003 + 0.3227533102035523 + -0.1480710953474045 + <_> + <_> + + + <_> + 12 3 3 6 -1. + <_> + 13 4 1 6 3. + 1 + 1.8873310182243586e-003 + -0.1083898991346359 + 0.4322502017021179 + <_> + <_> + + + <_> + 24 8 6 11 -1. + <_> + 26 8 2 11 3. + 0 + -9.6149174496531487e-003 + 0.5773208737373352 + -0.0727421268820763 + <_> + <_> + + + <_> + 14 16 2 15 -1. + <_> + 15 16 1 15 2. + 0 + 1.3040209887549281e-003 + 0.0825148820877075 + -0.5759180188179016 + -0.9169915914535523 + 13 + -1 + <_> + + <_> + <_> + + + <_> + 20 20 1 4 -1. + <_> + 20 20 1 2 2. + 1 + -2.4927530830609612e-005 + 0.2053970992565155 + -0.3632400929927826 + <_> + <_> + + + <_> + 8 2 14 9 -1. + <_> + 8 5 14 3 3. + 0 + -0.0229693204164505 + 0.2816925942897797 + -0.2282540947198868 + <_> + <_> + + + <_> + 12 1 6 36 -1. + <_> + 12 10 6 18 2. + 0 + -0.0912888869643211 + 0.4789518117904663 + -0.1221026033163071 + <_> + <_> + + + <_> + 0 1 21 32 -1. + <_> + 7 1 7 32 3. + 0 + -0.0846359506249428 + 0.1985473036766052 + -0.3261174857616425 + <_> + <_> + + + <_> + 8 24 19 24 -1. + <_> + 8 36 19 12 2. + 0 + 0.0124962301924825 + -0.3476786911487579 + 0.1870159953832626 + <_> + <_> + + + <_> + 11 33 11 4 -1. + <_> + 10 34 11 2 2. + 1 + -6.4234021119773388e-003 + 0.5211520195007324 + -0.1240243986248970 + <_> + <_> + + + <_> + 7 4 18 3 -1. + <_> + 7 5 18 1 3. + 0 + 3.0469179619103670e-003 + -0.1071569994091988 + 0.4552027881145477 + <_> + <_> + + + <_> + 21 7 2 28 -1. + <_> + 22 7 1 28 2. + 0 + -1.1288820533081889e-003 + 0.3270472884178162 + -0.1755225062370300 + <_> + <_> + + + <_> + 8 32 10 6 -1. + <_> + 6 34 10 2 3. + 1 + -0.0153848798945546 + 0.4662229120731354 + -0.1244667023420334 + <_> + <_> + + + <_> + 6 39 24 3 -1. + <_> + 12 39 12 3 2. + 0 + -7.4599292129278183e-003 + 0.2800185978412628 + -0.2254669964313507 + <_> + <_> + + + <_> + 14 4 4 6 -1. + <_> + 15 5 2 6 2. + 1 + 3.5344120115041733e-003 + -0.0825409367680550 + 0.5609217882156372 + <_> + <_> + + + <_> + 7 0 20 8 -1. + <_> + 12 0 10 8 2. + 0 + -6.0984282754361629e-004 + 0.1707669049501419 + -0.2986795008182526 + <_> + <_> + + + <_> + 11 11 8 24 -1. + <_> + 13 11 4 24 2. + 0 + 1.6679279506206512e-003 + -0.3368641138076782 + 0.1170241013169289 + <_> + <_> + + + <_> + 19 22 1 4 -1. + <_> + 19 22 1 2 2. + 1 + -6.5516651375219226e-004 + -0.3745996952056885 + 0.1419163048267365 + <_> + <_> + + + <_> + 19 4 5 4 -1. + <_> + 19 4 5 2 2. + 1 + 0.0111396098509431 + -0.1218288987874985 + 0.4120829999446869 + <_> + <_> + + + <_> + 15 7 6 32 -1. + <_> + 17 7 2 32 3. + 0 + 3.3056829124689102e-004 + -0.3083876967430115 + 0.1900637000799179 + <_> + <_> + + + <_> + 11 34 11 3 -1. + <_> + 10 35 11 1 3. + 1 + 2.0181920845061541e-003 + -0.1147705987095833 + 0.3973694145679474 + <_> + <_> + + + <_> + 26 0 6 4 -1. + <_> + 29 0 3 4 2. + 0 + -1.6060629859566689e-003 + -0.4615530073642731 + 0.0928468927741051 + <_> + <_> + + + <_> + 23 3 6 4 -1. + <_> + 22 4 6 2 2. + 1 + -6.8103889934718609e-003 + 0.6657456159591675 + -0.0738960281014442 + <_> + <_> + + + <_> + 31 0 1 18 -1. + <_> + 31 9 1 9 2. + 0 + 1.6974210666376166e-005 + -0.1900651007890701 + 0.2347782999277115 + <_> + <_> + + + <_> + 18 4 14 14 -1. + <_> + 18 11 14 7 2. + 0 + 0.0174405407160521 + 0.0969182997941971 + -0.5270084142684937 + <_> + <_> + + + <_> + 6 11 12 4 -1. + <_> + 10 11 4 4 3. + 0 + 0.0116618201136589 + -0.0927109420299530 + 0.5109962821006775 + <_> + <_> + + + <_> + 8 1 17 21 -1. + <_> + 8 8 17 7 3. + 0 + -0.0261016599833965 + 0.2000744938850403 + -0.2287525981664658 + <_> + <_> + + + <_> + 13 14 4 8 -1. + <_> + 13 16 4 4 2. + 0 + -5.7503599673509598e-003 + 0.4543879032135010 + -0.1251173019409180 + <_> + <_> + + + <_> + 1 8 27 30 -1. + <_> + 10 18 9 10 9. + 0 + -0.2703951001167297 + 0.1382135003805161 + -0.3384085893630981 + <_> + <_> + + + <_> + 15 20 1 9 -1. + <_> + 15 23 1 3 3. + 0 + 1.2405340385157615e-004 + -0.2276767939329147 + 0.2061284035444260 + <_> + <_> + + + <_> + 8 19 19 6 -1. + <_> + 6 21 19 2 3. + 1 + 0.0176202505826950 + -0.1293618977069855 + 0.3920623064041138 + <_> + <_> + + + <_> + 15 27 9 18 -1. + <_> + 15 33 9 6 3. + 0 + -3.4028588561341166e-004 + 0.2226548939943314 + -0.2183520942926407 + <_> + <_> + + + <_> + 20 30 6 7 -1. + <_> + 22 32 2 7 3. + 1 + 0.0108319502323866 + -0.1059779003262520 + 0.4716166853904724 + <_> + <_> + + + <_> + 9 10 6 30 -1. + <_> + 11 10 2 30 3. + 0 + -2.7355350903235376e-004 + -0.1995155960321426 + 0.2160613983869553 + <_> + <_> + + + <_> + 14 11 3 24 -1. + <_> + 15 11 1 24 3. + 0 + -7.9479831038042903e-004 + -0.5279554724693298 + 0.0977905616164207 + <_> + <_> + + + <_> + 26 0 6 6 -1. + <_> + 26 3 6 3 2. + 0 + 2.2506350651383400e-003 + 0.0730385333299637 + -0.5606986284255981 + -1.1347910165786743 + 14 + -1 + <_> + + <_> + <_> + + + <_> + 20 0 12 8 -1. + <_> + 20 0 6 4 2. + <_> + 26 4 6 4 2. + 0 + 5.1560858264565468e-003 + -0.2610827982425690 + 0.2569968104362488 + <_> + <_> + + + <_> + 13 7 6 33 -1. + <_> + 15 7 2 33 3. + 0 + 9.1058132238686085e-004 + -0.4031434953212738 + 0.1575772017240524 + <_> + <_> + + + <_> + 21 32 6 7 -1. + <_> + 23 34 2 7 3. + 1 + -0.0164671801030636 + 0.4609701931476593 + -0.1165079027414322 + <_> + <_> + + + <_> + 2 18 21 5 -1. + <_> + 9 18 7 5 3. + 0 + -9.7723528742790222e-003 + 0.1391634047031403 + -0.3804601132869721 + <_> + <_> + + + <_> + 12 47 6 1 -1. + <_> + 14 47 2 1 3. + 0 + -6.4513488905504346e-004 + 0.4118607938289642 + -0.1200387030839920 + <_> + <_> + + + <_> + 13 47 4 1 -1. + <_> + 14 47 2 1 2. + 0 + 1.0841710172826424e-004 + -0.1655955016613007 + 0.3400593101978302 + <_> + <_> + + + <_> + 6 6 4 24 -1. + <_> + 6 14 4 8 3. + 0 + -0.0194579698145390 + -0.5900229215621948 + 0.1105789989233017 + <_> + <_> + + + <_> + 6 6 5 24 -1. + <_> + 6 12 5 12 2. + 0 + 7.7574751339852810e-003 + 0.0888549312949181 + -0.5317453742027283 + <_> + <_> + + + <_> + 13 12 2 28 -1. + <_> + 13 26 2 14 2. + 0 + -6.4143179915845394e-003 + 0.3415961861610413 + -0.1644757986068726 + <_> + <_> + + + <_> + 15 5 6 33 -1. + <_> + 17 16 2 11 9. + 0 + -0.0296691693365574 + 0.1709744930267334 + -0.3527347147464752 + <_> + <_> + + + <_> + 5 2 23 16 -1. + <_> + 5 6 23 8 2. + 0 + -0.0288803000003099 + 0.1952552050352097 + -0.2596133053302765 + <_> + <_> + + + <_> + 20 14 2 14 -1. + <_> + 21 14 1 14 2. + 0 + -9.3913222372066230e-005 + 0.2259621024131775 + -0.2194329053163528 + <_> + <_> + + + <_> + 0 1 4 16 -1. + <_> + 0 5 4 8 2. + 0 + -6.2589491717517376e-003 + -0.5122287869453430 + 0.0847537368535995 + <_> + <_> + + + <_> + 22 34 3 10 -1. + <_> + 23 35 1 10 3. + 1 + 1.4945480506867170e-003 + -0.1269921958446503 + 0.3318152129650116 + <_> + <_> + + + <_> + 12 35 9 12 -1. + <_> + 15 39 3 4 9. + 0 + -1.1937189847230911e-003 + 0.1595999002456665 + -0.2707698047161102 + <_> + <_> + + + <_> + 15 17 3 4 -1. + <_> + 15 17 3 2 2. + 1 + 8.6428131908178329e-004 + 0.1216358989477158 + -0.3556757867336273 + <_> + <_> + + + <_> + 13 3 4 22 -1. + <_> + 13 3 2 11 2. + <_> + 15 14 2 11 2. + 0 + -1.5510140219703317e-003 + -0.3691368103027344 + 0.1163882985711098 + <_> + <_> + + + <_> + 7 9 24 33 -1. + <_> + 15 20 8 11 9. + 0 + -0.2427545040845871 + 0.1700772047042847 + -0.2755658924579620 + <_> + <_> + + + <_> + 14 15 4 16 -1. + <_> + 14 19 4 8 2. + 0 + 0.0170235894620419 + -0.0835393816232681 + 0.6732826828956604 + <_> + <_> + + + <_> + 14 9 3 27 -1. + <_> + 15 18 1 9 9. + 0 + -6.4246761612594128e-003 + 0.1413756012916565 + -0.3602938055992127 + <_> + <_> + + + <_> + 19 17 1 20 -1. + <_> + 19 27 1 10 2. + 0 + 9.5664191758260131e-004 + 0.2047650068998337 + -0.2331725060939789 + <_> + <_> + + + <_> + 14 7 6 20 -1. + <_> + 14 7 3 10 2. + <_> + 17 17 3 10 2. + 0 + 3.1860270537436008e-003 + 0.1257620006799698 + -0.3808588087558746 + <_> + <_> + + + <_> + 10 2 6 5 -1. + <_> + 12 4 2 5 3. + 1 + -0.0167146399617195 + 0.4631553888320923 + -0.1010254994034767 + <_> + <_> + + + <_> + 11 0 8 36 -1. + <_> + 11 9 8 18 2. + 0 + -0.1174127981066704 + 0.3770566880702972 + -0.1119090989232063 + <_> + <_> + + + <_> + 31 0 1 4 -1. + <_> + 31 2 1 2 2. + 0 + 8.4238172348705120e-006 + -0.1750769019126892 + 0.2519958913326263 + <_> + <_> + + + <_> + 20 0 12 4 -1. + <_> + 26 0 6 4 2. + 0 + -5.4449908202514052e-004 + -0.3330337107181549 + 0.1314388066530228 + <_> + <_> + + + <_> + 8 33 11 3 -1. + <_> + 7 34 11 1 3. + 1 + -4.0244688279926777e-003 + 0.4155085980892181 + -0.1011321023106575 + <_> + <_> + + + <_> + 11 16 10 4 -1. + <_> + 11 17 10 2 2. + 0 + 1.0842960327863693e-003 + -0.0938822403550148 + 0.4475842118263245 + <_> + <_> + + + <_> + 24 0 6 1 -1. + <_> + 24 0 3 1 2. + 1 + -1.6783650498837233e-003 + -0.5228074193000794 + 0.0835699066519737 + <_> + <_> + + + <_> + 5 6 3 20 -1. + <_> + 6 6 1 20 3. + 0 + -3.9357710629701614e-003 + 0.4895322918891907 + -0.0887887030839920 + <_> + <_> + + + <_> + 8 1 11 4 -1. + <_> + 8 1 11 2 2. + 1 + 9.7808092832565308e-003 + 0.0946740731596947 + -0.4615156948566437 + <_> + <_> + + + <_> + 9 34 7 3 -1. + <_> + 8 35 7 1 3. + 1 + 2.4131010286509991e-003 + -0.0904192999005318 + 0.4876500070095062 + <_> + <_> + + + <_> + 11 4 8 8 -1. + <_> + 11 6 8 4 2. + 0 + 6.2217740342020988e-003 + -0.0787857174873352 + 0.4732921123504639 + <_> + <_> + + + <_> + 9 2 16 12 -1. + <_> + 9 6 16 4 3. + 0 + -0.0459213815629482 + 0.2805229127407074 + -0.1759258061647415 + -1.1371920108795166 + 15 + -1 + <_> + + <_> + <_> + + + <_> + 6 2 17 9 -1. + <_> + 6 5 17 3 3. + 0 + -0.0324662812054157 + 0.3039638996124268 + -0.1903236955404282 + <_> + <_> + + + <_> + 16 16 16 3 -1. + <_> + 24 16 8 3 2. + 0 + 7.4793538078665733e-003 + -0.4710904061794281 + 0.1173494011163712 + <_> + <_> + + + <_> + 14 8 9 33 -1. + <_> + 17 8 3 33 3. + 0 + 5.1927231252193451e-003 + -0.2179691046476364 + 0.3265633881092072 + <_> + <_> + + + <_> + 11 10 8 30 -1. + <_> + 13 10 4 30 2. + 0 + 2.4242310319095850e-003 + -0.3805586099624634 + 0.1453333944082260 + <_> + <_> + + + <_> + 17 39 1 8 -1. + <_> + 17 39 1 4 2. + 1 + -2.0807320252060890e-003 + 0.2196232974529266 + -0.2510665953159332 + <_> + <_> + + + <_> + 19 4 5 2 -1. + <_> + 19 4 5 1 2. + 1 + 2.8372351080179214e-003 + -0.1386727988719940 + 0.3647134900093079 + <_> + <_> + + + <_> + 17 8 8 29 -1. + <_> + 19 8 4 29 2. + 0 + 2.4023340083658695e-003 + -0.1483796983957291 + 0.3501685857772827 + <_> + <_> + + + <_> + 18 22 8 2 -1. + <_> + 20 24 4 2 2. + 1 + 9.3386822845786810e-004 + 0.1266088932752609 + -0.4283660948276520 + <_> + <_> + + + <_> + 12 15 14 2 -1. + <_> + 12 15 7 2 2. + 1 + 5.6245732121169567e-003 + 0.0799629464745522 + -0.5351322293281555 + <_> + <_> + + + <_> + 11 18 15 4 -1. + <_> + 10 19 15 2 2. + 1 + -7.3368018493056297e-003 + 0.4855501055717468 + -0.1085975989699364 + <_> + <_> + + + <_> + 3 3 8 27 -1. + <_> + 3 12 8 9 3. + 0 + -0.0362997204065323 + -0.5094090104103088 + 0.0983420014381409 + <_> + <_> + + + <_> + 11 0 7 8 -1. + <_> + 9 2 7 4 2. + 1 + -0.0265847593545914 + -0.7376736998558044 + 0.0667715966701508 + <_> + <_> + + + <_> + 22 4 4 6 -1. + <_> + 22 4 2 6 2. + 1 + -0.0124296899884939 + -0.7961040139198303 + 0.0479637086391449 + <_> + <_> + + + <_> + 13 1 8 8 -1. + <_> + 15 3 4 8 2. + 1 + -0.0244186092168093 + 0.4146968126296997 + -0.1287637054920197 + <_> + <_> + + + <_> + 3 7 9 8 -1. + <_> + 6 7 3 8 3. + 0 + -0.0267906505614519 + 0.5383982062339783 + -0.0788511633872986 + <_> + <_> + + + <_> + 12 4 12 4 -1. + <_> + 15 7 6 4 2. + 1 + -0.0184865295886993 + 0.3938249945640564 + -0.1129425987601280 + <_> + <_> + + + <_> + 15 10 4 27 -1. + <_> + 16 10 2 27 2. + 0 + -1.5502869791816920e-004 + -0.3397634923458099 + 0.1282863020896912 + <_> + <_> + + + <_> + 14 8 5 20 -1. + <_> + 14 13 5 10 2. + 0 + 1.1274799471721053e-003 + 0.1168809011578560 + -0.3506088852882385 + <_> + <_> + + + <_> + 14 8 1 6 -1. + <_> + 14 11 1 3 2. + 0 + 4.3377490328566637e-006 + -0.2637923061847687 + 0.1694667041301727 + <_> + <_> + + + <_> + 14 44 3 3 -1. + <_> + 15 45 1 1 9. + 0 + -7.5999670661985874e-004 + 0.3541651070117950 + -0.1236087977886200 + <_> + <_> + + + <_> + 14 6 6 36 -1. + <_> + 16 6 2 36 3. + 0 + 0.0179570801556110 + 0.0630755275487900 + -0.6831303238868713 + <_> + <_> + + + <_> + 19 0 12 5 -1. + <_> + 22 0 6 5 2. + 0 + -7.9441936686635017e-003 + -0.6397883296012878 + 0.0512169189751148 + <_> + <_> + + + <_> + 22 37 3 8 -1. + <_> + 23 38 1 8 3. + 1 + 2.0747499074786901e-003 + -0.0941726490855217 + 0.4486300051212311 + <_> + <_> + + + <_> + 14 4 5 4 -1. + <_> + 14 6 5 2 2. + 0 + 6.1493911780416965e-003 + -0.0593560487031937 + 0.6764311194419861 + <_> + <_> + + + <_> + 19 0 12 7 -1. + <_> + 23 4 4 7 3. + 1 + -4.2592990212142467e-003 + 0.1572678983211517 + -0.3399276137351990 + <_> + <_> + + + <_> + 15 10 9 28 -1. + <_> + 18 10 3 28 3. + 0 + 7.0916470140218735e-003 + -0.1452832072973251 + 0.3092780113220215 + <_> + <_> + + + <_> + 11 30 18 6 -1. + <_> + 17 32 6 2 9. + 0 + -0.0249142702668905 + 0.2694596052169800 + -0.2037568986415863 + <_> + <_> + + + <_> + 23 34 4 10 -1. + <_> + 24 35 2 10 2. + 1 + -7.1876570582389832e-003 + 0.5062612891197205 + -0.0741537883877754 + <_> + <_> + + + <_> + 21 36 3 9 -1. + <_> + 22 37 1 9 3. + 1 + 1.2363620335236192e-003 + -0.1196231991052628 + 0.3301286995410919 + <_> + <_> + + + <_> + 16 29 13 18 -1. + <_> + 16 35 13 6 3. + 0 + -6.7285839468240738e-003 + 0.1823327988386154 + -0.2203885018825531 + <_> + <_> + + + <_> + 26 36 4 8 -1. + <_> + 26 36 4 4 2. + 1 + -0.0206027105450630 + -0.7015135884284973 + 0.0704326778650284 + <_> + <_> + + + <_> + 6 11 19 30 -1. + <_> + 6 21 19 10 3. + 0 + -0.0317063294351101 + 0.1271570026874542 + -0.3211661875247955 + <_> + <_> + + + <_> + 13 25 4 8 -1. + <_> + 14 25 2 8 2. + 0 + -5.7940912665799260e-004 + -0.5432162284851074 + 0.0760642737150192 + -1.0525219440460205 + 16 + -1 + <_> + + <_> + <_> + + + <_> + 2 13 18 3 -1. + <_> + 8 13 6 3 3. + 0 + -5.1720421761274338e-003 + 0.1591023951768875 + -0.3885805010795593 + <_> + <_> + + + <_> + 14 8 5 4 -1. + <_> + 14 10 5 2 2. + 0 + 1.3409119856078178e-004 + -0.3251490890979767 + 0.1743420064449310 + <_> + <_> + + + <_> + 13 8 5 30 -1. + <_> + 13 18 5 10 3. + 0 + -0.0248214695602655 + 0.2184471935033798 + -0.3198319971561432 + <_> + <_> + + + <_> + 18 0 14 10 -1. + <_> + 18 0 7 5 2. + <_> + 25 5 7 5 2. + 0 + 0.0103786103427410 + -0.2900767922401428 + 0.1776996999979019 + <_> + <_> + + + <_> + 13 25 18 4 -1. + <_> + 13 25 9 2 2. + <_> + 22 27 9 2 2. + 0 + 4.8796460032463074e-004 + -0.2116630971431732 + 0.2611202001571655 + <_> + <_> + + + <_> + 13 46 18 2 -1. + <_> + 19 46 6 2 3. + 0 + 3.1192600727081299e-003 + -0.1465214937925339 + 0.3364233076572418 + <_> + <_> + + + <_> + 17 4 8 16 -1. + <_> + 17 12 8 8 2. + 0 + 3.8724069017916918e-003 + 0.0778768882155418 + -0.5160806775093079 + <_> + <_> + + + <_> + 24 20 6 24 -1. + <_> + 24 28 6 8 3. + 0 + 0.0200406406074762 + 0.0801388993859291 + -0.5306345224380493 + <_> + <_> + + + <_> + 9 46 12 1 -1. + <_> + 12 46 6 1 2. + 0 + 9.1706047533079982e-004 + -0.1302940994501114 + 0.3543314933776856 + <_> + <_> + + + <_> + 13 12 4 16 -1. + <_> + 13 12 2 8 2. + <_> + 15 20 2 8 2. + 0 + -3.7578109186142683e-003 + -0.6723951101303101 + 0.0812122225761414 + <_> + <_> + + + <_> + 8 30 18 18 -1. + <_> + 8 36 18 6 3. + 0 + -0.0295332893729210 + 0.1991707980632782 + -0.2033832073211670 + <_> + <_> + + + <_> + 9 26 12 12 -1. + <_> + 9 30 12 4 3. + 0 + -0.0153763797134161 + 0.3554900884628296 + -0.1299345046281815 + <_> + <_> + + + <_> + 1 11 30 24 -1. + <_> + 11 19 10 8 9. + 0 + -0.3612424135208130 + 0.2033322006464005 + -0.2029083073139191 + <_> + <_> + + + <_> + 26 1 6 8 -1. + <_> + 24 3 6 4 2. + 1 + -0.0232372097671032 + 0.5779861807823181 + -0.0978644564747810 + <_> + <_> + + + <_> + 13 7 6 28 -1. + <_> + 13 21 6 14 2. + 0 + 0.0126332901418209 + -0.1755934953689575 + 0.2618930041790009 + <_> + <_> + + + <_> + 14 13 2 28 -1. + <_> + 14 27 2 14 2. + 0 + -4.9736998043954372e-003 + 0.3246139883995056 + -0.1598287969827652 + <_> + <_> + + + <_> + 10 35 6 3 -1. + <_> + 9 36 6 1 3. + 1 + -4.7239558771252632e-003 + 0.5832179784774780 + -0.0716993436217308 + <_> + <_> + + + <_> + 12 13 4 8 -1. + <_> + 13 13 2 8 2. + 0 + 1.8682880327105522e-003 + 0.0687939301133156 + -0.6960105895996094 + <_> + <_> + + + <_> + 25 1 2 5 -1. + <_> + 25 1 1 5 2. + 1 + 3.6855249200016260e-003 + 0.0445724911987782 + -0.7650830149650574 + <_> + <_> + + + <_> + 9 0 3 6 -1. + <_> + 9 0 3 3 2. + 1 + -5.3956201300024986e-003 + -0.4844548106193543 + 0.0769112631678581 + <_> + <_> + + + <_> + 8 34 10 4 -1. + <_> + 7 35 10 2 2. + 1 + 4.6425061300396919e-003 + -0.0977346524596214 + 0.4725498855113983 + <_> + <_> + + + <_> + 11 38 6 4 -1. + <_> + 10 39 6 2 2. + 1 + -4.0225139819085598e-003 + 0.5072348713874817 + -0.0927651301026344 + <_> + <_> + + + <_> + 0 27 8 12 -1. + <_> + 0 33 8 6 2. + 0 + 5.6185619905591011e-003 + 0.1094985008239746 + -0.4045788943767548 + <_> + <_> + + + <_> + 6 15 4 24 -1. + <_> + 6 21 4 12 2. + 0 + 4.1883741505444050e-003 + 0.0916806533932686 + -0.4371629059314728 + <_> + <_> + + + <_> + 1 2 2 8 -1. + <_> + 1 6 2 4 2. + 0 + 1.7508920791442506e-005 + -0.1974201947450638 + 0.2209922969341278 + <_> + <_> + + + <_> + 0 0 7 14 -1. + <_> + 0 7 7 7 2. + 0 + 6.8793259561061859e-003 + 0.0886543393135071 + -0.4603740870952606 + <_> + <_> + + + <_> + 11 11 13 3 -1. + <_> + 10 12 13 1 3. + 1 + -3.6316108889877796e-003 + 0.4049116075038910 + -0.1142103001475334 + <_> + <_> + + + <_> + 7 2 14 3 -1. + <_> + 7 3 14 1 3. + 0 + -3.1504929065704346e-003 + 0.6294767856597900 + -0.0661639794707298 + <_> + <_> + + + <_> + 18 13 2 19 -1. + <_> + 19 13 1 19 2. + 0 + -3.8807559758424759e-004 + 0.2089063972234726 + -0.1959272027015686 + <_> + <_> + + + <_> + 5 4 23 36 -1. + <_> + 5 16 23 12 3. + 0 + -0.3176749050617218 + -0.7574244141578674 + 0.0495881997048855 + -0.9814273118972778 + 17 + -1 + <_> + + <_> + <_> + + + <_> + 23 31 6 10 -1. + <_> + 25 33 2 10 3. + 1 + -0.0161894205957651 + 0.4460271894931793 + -0.1391475945711136 + <_> + <_> + + + <_> + 3 3 16 13 -1. + <_> + 7 3 8 13 2. + 0 + -0.0243140608072281 + 0.2449412941932678 + -0.2753838002681732 + <_> + <_> + + + <_> + 11 3 21 36 -1. + <_> + 18 15 7 12 9. + 0 + -0.2751105129718781 + 0.2191523015499115 + -0.2452449947595596 + <_> + <_> + + + <_> + 10 6 8 34 -1. + <_> + 12 6 4 34 2. + 0 + 4.3554129078984261e-003 + -0.2423648983240128 + 0.2146122008562088 + <_> + <_> + + + <_> + 11 44 6 4 -1. + <_> + 13 44 2 4 3. + 0 + -2.3293560370802879e-003 + 0.4434621036052704 + -0.0877754986286163 + <_> + <_> + + + <_> + 12 38 8 10 -1. + <_> + 12 38 4 5 2. + <_> + 16 43 4 5 2. + 0 + -4.2710988782346249e-003 + 0.3471372127532959 + -0.1692395955324173 + <_> + <_> + + + <_> + 14 9 5 9 -1. + <_> + 14 12 5 3 3. + 0 + 1.3863759522791952e-004 + -0.3221074044704437 + 0.1410287022590637 + <_> + <_> + + + <_> + 9 4 9 18 -1. + <_> + 12 10 3 6 9. + 0 + -0.0497867688536644 + 0.4503012895584106 + -0.1048228964209557 + <_> + <_> + + + <_> + 8 4 15 4 -1. + <_> + 8 5 15 2 2. + 0 + -4.3509937822818756e-003 + 0.2828885018825531 + -0.1718529015779495 + <_> + <_> + + + <_> + 5 22 6 16 -1. + <_> + 7 22 2 16 3. + 0 + -0.0162898097187281 + 0.4590002894401550 + -0.0761803314089775 + <_> + <_> + + + <_> + 0 6 4 42 -1. + <_> + 2 6 2 42 2. + 0 + 7.5984261929988861e-003 + 0.0985261425375938 + -0.4189974963665009 + <_> + <_> + + + <_> + 8 29 3 2 -1. + <_> + 9 30 1 2 3. + 1 + 1.1419199872761965e-003 + -0.0940674915909767 + 0.4647271037101746 + <_> + <_> + + + <_> + 12 23 3 14 -1. + <_> + 13 23 1 14 3. + 0 + -3.8020839565433562e-004 + -0.3433778882026672 + 0.1188758015632629 + <_> + <_> + + + <_> + 9 27 12 6 -1. + <_> + 13 29 4 2 9. + 0 + -5.8866932522505522e-004 + 0.1837272942066193 + -0.2270005047321320 + <_> + <_> + + + <_> + 12 29 6 3 -1. + <_> + 12 30 6 1 3. + 0 + 3.6254859878681600e-004 + -0.1315148025751114 + 0.3440802097320557 + <_> + <_> + + + <_> + 19 16 10 32 -1. + <_> + 19 24 10 16 2. + 0 + 2.1581570617854595e-003 + 0.1251415014266968 + -0.3051261901855469 + <_> + <_> + + + <_> + 11 2 6 33 -1. + <_> + 13 2 2 33 3. + 0 + 0.0160614494234324 + 0.0541181899607182 + -0.6891291141510010 + <_> + <_> + + + <_> + 12 46 4 2 -1. + <_> + 13 46 2 2 2. + 0 + 3.2183629809878767e-004 + -0.1269109994173050 + 0.3347525000572205 + <_> + <_> + + + <_> + 0 0 30 11 -1. + <_> + 10 0 10 11 3. + 0 + -0.0262784399092197 + 0.1189005970954895 + -0.3073745965957642 + <_> + <_> + + + <_> + 22 6 4 9 -1. + <_> + 24 6 2 9 2. + 0 + -6.0809529386460781e-003 + 0.6540256142616272 + -0.0668434202671051 + <_> + <_> + + + <_> + 20 5 5 3 -1. + <_> + 19 6 5 1 3. + 1 + -4.4067199341952801e-003 + 0.6187611222267151 + -0.0627684965729713 + <_> + <_> + + + <_> + 16 30 9 5 -1. + <_> + 19 33 3 5 3. + 1 + 0.0275703407824039 + -0.0883492678403854 + 0.4874804913997650 + <_> + <_> + + + <_> + 9 33 21 9 -1. + <_> + 16 36 7 3 9. + 0 + -0.0137473298236728 + 0.1812745928764343 + -0.2454026043415070 + <_> + <_> + + + <_> + 18 27 8 6 -1. + <_> + 16 29 8 2 3. + 1 + 0.0126829296350479 + -0.1032790020108223 + 0.3997527956962585 + <_> + <_> + + + <_> + 19 11 8 4 -1. + <_> + 21 11 4 4 2. + 0 + -8.3017796277999878e-003 + 0.4848122894763947 + -0.0785148367285728 + <_> + <_> + + + <_> + 11 0 6 6 -1. + <_> + 11 0 6 3 2. + 1 + -0.0152528202161193 + -0.8384873270988464 + 0.0489941909909248 + <_> + <_> + + + <_> + 7 9 2 24 -1. + <_> + 7 9 1 12 2. + <_> + 8 21 1 12 2. + 0 + -3.9478549733757973e-003 + 0.5886045098304749 + -0.0765701830387115 + <_> + <_> + + + <_> + 14 7 2 16 -1. + <_> + 14 7 1 8 2. + <_> + 15 15 1 8 2. + 0 + -1.0594209888949990e-003 + -0.5541247725486755 + 0.0734699368476868 + <_> + <_> + + + <_> + 9 11 10 3 -1. + <_> + 8 12 10 1 3. + 1 + 1.1575090466067195e-003 + -0.1077454015612602 + 0.4058643877506256 + <_> + <_> + + + <_> + 21 7 9 21 -1. + <_> + 24 7 3 21 3. + 0 + -0.0473634414374828 + 0.5503035783767700 + -0.0653080269694328 + <_> + <_> + + + <_> + 18 5 7 2 -1. + <_> + 18 5 7 1 2. + 1 + 3.6405769642442465e-003 + -0.1118758022785187 + 0.3347791135311127 + <_> + <_> + + + <_> + 27 0 1 2 -1. + <_> + 27 1 1 1 2. + 0 + 4.0733912101131864e-006 + -0.1552219986915588 + 0.2679066956043243 + <_> + <_> + + + <_> + 14 8 3 21 -1. + <_> + 15 15 1 7 9. + 0 + -3.5573750210460275e-005 + 0.1193322017788887 + -0.3422695994377136 + <_> + <_> + + + <_> + 7 6 2 32 -1. + <_> + 7 6 1 16 2. + <_> + 8 22 1 16 2. + 0 + 3.2678889110684395e-003 + -0.1268963962793350 + 0.3349390029907227 + -0.9860544204711914 + 18 + -1 + <_> + + <_> + <_> + + + <_> + 2 1 18 42 -1. + <_> + 8 15 6 14 9. + 0 + -0.2977561950683594 + 0.2051210999488831 + -0.2882811129093170 + <_> + <_> + + + <_> + 18 22 4 6 -1. + <_> + 20 22 2 6 2. + 0 + -4.7089738473005127e-006 + 0.2078963965177536 + -0.2948715090751648 + <_> + <_> + + + <_> + 0 0 32 15 -1. + <_> + 0 5 32 5 3. + 0 + -0.0570193305611610 + 0.2089810967445374 + -0.2353688925504684 + <_> + <_> + + + <_> + 14 8 6 18 -1. + <_> + 14 17 6 9 2. + 0 + 2.1603459026664495e-003 + 0.1428025066852570 + -0.3933134973049164 + <_> + <_> + + + <_> + 14 7 5 20 -1. + <_> + 14 17 5 10 2. + 0 + -4.0643191896378994e-003 + -0.2099640965461731 + 0.2884778976440430 + <_> + <_> + + + <_> + 12 8 8 30 -1. + <_> + 12 23 8 15 2. + 0 + -0.0460438504815102 + 0.3874391019344330 + -0.1527816951274872 + <_> + <_> + + + <_> + 7 9 3 9 -1. + <_> + 7 12 3 3 3. + 0 + 7.6398742385208607e-004 + 0.1653634011745453 + -0.3299095034599304 + <_> + <_> + + + <_> + 23 2 6 6 -1. + <_> + 21 4 6 2 3. + 1 + 7.2054541669785976e-003 + -0.1143992990255356 + 0.4310468137264252 + <_> + <_> + + + <_> + 6 1 1 6 -1. + <_> + 6 1 1 3 2. + 1 + -1.8284039470017888e-005 + 0.2252390980720520 + -0.2073123008012772 + <_> + <_> + + + <_> + 12 46 6 2 -1. + <_> + 14 46 2 2 3. + 0 + -7.9511571675539017e-004 + 0.3320463001728058 + -0.1436139047145844 + <_> + <_> + + + <_> + 19 22 4 14 -1. + <_> + 20 22 2 14 2. + 0 + 2.6318538584746420e-004 + -0.1663399934768677 + 0.2829839885234833 + <_> + <_> + + + <_> + 14 24 6 14 -1. + <_> + 16 24 2 14 3. + 0 + -9.4987178454175591e-004 + -0.4547114968299866 + 0.1367025971412659 + <_> + <_> + + + <_> + 15 47 6 1 -1. + <_> + 17 47 2 1 3. + 0 + -6.6909467568621039e-004 + 0.3695616126060486 + -0.1371538043022156 + <_> + <_> + + + <_> + 10 24 6 15 -1. + <_> + 12 24 2 15 3. + 0 + 4.5260530896484852e-006 + -0.2436800003051758 + 0.1917141973972321 + <_> + <_> + + + <_> + 17 0 14 22 -1. + <_> + 17 11 14 11 2. + 0 + -0.0266543496400118 + 0.1475736945867539 + -0.3557994067668915 + <_> + <_> + + + <_> + 6 11 8 1 -1. + <_> + 8 11 4 1 2. + 0 + 1.0338389547541738e-003 + -0.0869987830519676 + 0.5418463945388794 + <_> + <_> + + + <_> + 4 27 27 3 -1. + <_> + 13 28 9 1 9. + 0 + -6.4091570675373077e-003 + 0.1204269006848335 + -0.3796887993812561 + <_> + <_> + + + <_> + 5 2 10 36 -1. + <_> + 5 2 5 18 2. + <_> + 10 20 5 18 2. + 0 + 0.0523008815944195 + -0.1214606985449791 + 0.4707033038139343 + <_> + <_> + + + <_> + 23 1 6 6 -1. + <_> + 21 3 6 2 3. + 1 + -0.0211491193622351 + 0.7065731287002564 + -0.0748629420995712 + <_> + <_> + + + <_> + 0 0 3 8 -1. + <_> + 0 4 3 4 2. + 0 + 4.5586768537759781e-003 + 0.0641048327088356 + -0.6908230185508728 + <_> + <_> + + + <_> + 3 12 6 16 -1. + <_> + 5 12 2 16 3. + 0 + -9.8913265392184258e-003 + 0.4566341936588287 + -0.0992304310202599 + <_> + <_> + + + <_> + 11 25 4 7 -1. + <_> + 11 25 2 7 2. + 1 + 9.3495808541774750e-003 + -0.1231518015265465 + 0.3202393949031830 + <_> + <_> + + + <_> + 12 24 4 7 -1. + <_> + 13 24 2 7 2. + 0 + -4.8743889783509076e-004 + -0.4415754973888397 + 0.0971890389919281 + <_> + <_> + + + <_> + 15 30 7 12 -1. + <_> + 15 34 7 4 3. + 0 + 0.0310087706893682 + -0.1000055968761444 + 0.4254876077175140 + <_> + <_> + + + <_> + 12 27 5 21 -1. + <_> + 12 34 5 7 3. + 0 + -2.3338910250458866e-004 + 0.2052273005247116 + -0.2536886930465698 + <_> + <_> + + + <_> + 10 7 7 30 -1. + <_> + 10 17 7 10 3. + 0 + -0.0128705604001880 + 0.1167137026786804 + -0.3885658085346222 + <_> + <_> + + + <_> + 10 8 15 6 -1. + <_> + 10 8 15 3 2. + 1 + -0.0225015804171562 + 0.3544884026050568 + -0.1594616025686264 + <_> + <_> + + + <_> + 8 23 6 15 -1. + <_> + 10 23 2 15 3. + 0 + 3.3663999056443572e-004 + -0.1531786024570465 + 0.3046655952930450 + <_> + <_> + + + <_> + 8 9 4 38 -1. + <_> + 8 9 2 19 2. + <_> + 10 28 2 19 2. + 0 + -7.8897634521126747e-003 + 0.3788172900676727 + -0.1115242987871170 + <_> + <_> + + + <_> + 1 1 30 27 -1. + <_> + 11 1 10 27 3. + 0 + -0.2020969986915588 + 0.1592365950345993 + -0.2574897110462189 + <_> + <_> + + + <_> + 12 5 8 25 -1. + <_> + 14 5 4 25 2. + 0 + 2.0249930676072836e-003 + -0.2580868899822235 + 0.2034415006637573 + <_> + <_> + + + <_> + 19 36 6 12 -1. + <_> + 19 36 3 6 2. + <_> + 22 42 3 6 2. + 0 + 6.1646532267332077e-003 + -0.1008339971303940 + 0.3947617113590241 + <_> + <_> + + + <_> + 15 10 12 6 -1. + <_> + 19 10 4 6 3. + 0 + 9.3816686421632767e-003 + -0.1080358028411865 + 0.4140104949474335 + <_> + <_> + + + <_> + 19 10 2 2 -1. + <_> + 19 10 2 1 2. + 1 + -6.6391767177265137e-005 + 0.1998784989118576 + -0.1871495991945267 + <_> + <_> + + + <_> + 13 25 3 5 -1. + <_> + 14 25 1 5 3. + 0 + 6.9919892121106386e-004 + 0.0596634708344936 + -0.6201426982879639 + <_> + <_> + + + <_> + 25 6 5 10 -1. + <_> + 25 11 5 5 2. + 0 + 0.0122280996292830 + 0.0310413297265768 + -0.8233888149261475 + -1.0882439613342285 + 19 + -1 + <_> + + <_> + <_> + + + <_> + 21 0 11 8 -1. + <_> + 19 2 11 4 2. + 1 + -0.0171925295144320 + 0.3289281129837036 + -0.1636175066232681 + <_> + <_> + + + <_> + 8 31 8 16 -1. + <_> + 8 31 4 8 2. + <_> + 12 39 4 8 2. + 0 + -2.5137080810964108e-003 + 0.1998953968286514 + -0.2618654966354370 + <_> + <_> + + + <_> + 6 2 8 18 -1. + <_> + 6 11 8 9 2. + 0 + -5.4037338122725487e-003 + 0.1145588979125023 + -0.4429601132869721 + <_> + <_> + + + <_> + 31 1 1 6 -1. + <_> + 31 4 1 3 2. + 0 + 4.1723228605405893e-006 + -0.1738854944705963 + 0.2609759867191315 + <_> + <_> + + + <_> + 9 4 21 14 -1. + <_> + 9 11 21 7 2. + 0 + -8.7189795449376106e-003 + -0.1312364935874939 + 0.3033815920352936 + <_> + <_> + + + <_> + 14 20 3 8 -1. + <_> + 14 22 3 4 2. + 0 + 1.4408420247491449e-004 + -0.2890456914901733 + 0.1214544996619225 + <_> + <_> + + + <_> + 1 8 30 27 -1. + <_> + 11 17 10 9 9. + 0 + -0.3272173106670380 + 0.1663330942392349 + -0.3636147081851959 + <_> + <_> + + + <_> + 16 5 6 34 -1. + <_> + 18 5 2 34 3. + 0 + 2.0755049772560596e-003 + -0.2004979997873306 + 0.2257502973079681 + <_> + <_> + + + <_> + 12 7 6 29 -1. + <_> + 14 7 2 29 3. + 0 + 1.0619499953463674e-003 + -0.3395603895187378 + 0.1612467020750046 + <_> + <_> + + + <_> + 11 4 12 16 -1. + <_> + 11 8 12 8 2. + 0 + -0.0302706696093082 + 0.4654717147350311 + -0.1373468041419983 + <_> + <_> + + + <_> + 18 9 9 5 -1. + <_> + 21 9 3 5 3. + 0 + 6.5612341277301311e-003 + -0.1227878034114838 + 0.4011098146438599 + <_> + <_> + + + <_> + 13 6 3 6 -1. + <_> + 14 7 1 6 3. + 1 + 2.8333798982203007e-003 + -0.0673750936985016 + 0.6065192818641663 + <_> + <_> + + + <_> + 7 1 20 6 -1. + <_> + 7 3 20 2 3. + 0 + 0.0169769302010536 + -0.1260410994291306 + 0.3028025031089783 + <_> + <_> + + + <_> + 9 3 13 3 -1. + <_> + 9 4 13 1 3. + 0 + -2.9060509987175465e-003 + 0.4869351089000702 + -0.0916975811123848 + <_> + <_> + + + <_> + 14 8 6 33 -1. + <_> + 16 8 2 33 3. + 0 + 1.6101419460028410e-003 + -0.2851710021495819 + 0.1509283035993576 + <_> + <_> + + + <_> + 21 33 6 5 -1. + <_> + 23 35 2 5 3. + 1 + 0.0103675797581673 + -0.0833982005715370 + 0.5458555221557617 + <_> + <_> + + + <_> + 16 40 10 6 -1. + <_> + 21 40 5 6 2. + 0 + 2.1976130083203316e-003 + -0.2156579047441483 + 0.2012812048196793 + <_> + <_> + + + <_> + 11 27 3 2 -1. + <_> + 11 27 3 1 2. + 1 + 7.3421042179688811e-004 + 0.0885826125741005 + -0.4860736131668091 + <_> + <_> + + + <_> + 11 9 3 28 -1. + <_> + 12 9 1 28 3. + 0 + 5.9429101384012029e-005 + -0.2578220069408417 + 0.2000299990177155 + <_> + <_> + + + <_> + 17 13 6 28 -1. + <_> + 19 13 2 28 3. + 0 + 9.0766069479286671e-004 + -0.1788693070411682 + 0.2391306012868881 + <_> + <_> + + + <_> + 9 3 16 8 -1. + <_> + 13 3 8 8 2. + 0 + -3.6279750056564808e-003 + 0.1683968007564545 + -0.2347262948751450 + <_> + <_> + + + <_> + 22 30 8 10 -1. + <_> + 22 30 8 5 2. + 1 + 0.0400380901992321 + 0.0853790566325188 + -0.5731585025787354 + <_> + <_> + + + <_> + 18 3 7 4 -1. + <_> + 17 4 7 2 2. + 1 + 4.7586658038198948e-003 + -0.0753867328166962 + 0.6275324225425720 + <_> + <_> + + + <_> + 18 0 5 2 -1. + <_> + 18 1 5 1 2. + 0 + 5.1203102339059114e-004 + 0.0920799598097801 + -0.4607042074203491 + <_> + <_> + + + <_> + 16 15 2 12 -1. + <_> + 17 15 1 12 2. + 0 + 9.0750277740880847e-004 + 0.0440583899617195 + -0.6532173752784729 + <_> + <_> + + + <_> + 10 18 5 2 -1. + <_> + 10 18 5 1 2. + 1 + 1.3250960037112236e-003 + 0.0447401590645313 + -0.6538137793540955 + <_> + <_> + + + <_> + 14 5 3 10 -1. + <_> + 15 6 1 10 3. + 1 + -4.3023489415645599e-003 + 0.4555636942386627 + -0.0831138715147972 + <_> + <_> + + + <_> + 0 0 32 2 -1. + <_> + 0 1 32 1 2. + 0 + -9.7636511782184243e-004 + -0.3237073123455048 + 0.1106562018394470 + <_> + <_> + + + <_> + 14 47 3 1 -1. + <_> + 15 47 1 1 3. + 0 + 1.2418429832905531e-004 + -0.1163239032030106 + 0.3104239106178284 + <_> + <_> + + + <_> + 11 47 9 1 -1. + <_> + 14 47 3 1 3. + 0 + -5.2678771317005157e-004 + 0.2365964949131012 + -0.1524728983640671 + <_> + <_> + + + <_> + 13 12 3 25 -1. + <_> + 14 12 1 25 3. + 0 + -3.6805970012210310e-004 + -0.3714311122894287 + 0.1082331016659737 + <_> + <_> + + + <_> + 19 26 6 6 -1. + <_> + 17 28 6 2 3. + 1 + 0.0169800501316786 + -0.0677116513252258 + 0.6042426824569702 + <_> + <_> + + + <_> + 12 26 8 12 -1. + <_> + 12 29 8 6 2. + 0 + -9.4963668379932642e-004 + 0.2311625927686691 + -0.1728644073009491 + <_> + <_> + + + <_> + 9 13 12 21 -1. + <_> + 9 20 12 7 3. + 0 + -0.0158714707940817 + 0.1431398987770081 + -0.2742567062377930 + <_> + <_> + + + <_> + 7 10 8 2 -1. + <_> + 7 10 8 1 2. + 1 + -1.4097680104896426e-003 + 0.2039137929677963 + -0.2465737015008926 + <_> + <_> + + + <_> + 10 10 3 30 -1. + <_> + 11 10 1 30 3. + 0 + -3.8154391222633421e-004 + -0.2454032003879547 + 0.2077358067035675 + <_> + <_> + + + <_> + 12 11 12 4 -1. + <_> + 11 12 12 2 2. + 1 + 1.8105059862136841e-003 + -0.0886538922786713 + 0.4708065092563629 + -0.9675772786140442 + 20 + -1 + <_> + + <_> + <_> + + + <_> + 2 3 12 6 -1. + <_> + 8 3 6 6 2. + 0 + -8.7176617234945297e-003 + 0.1587868928909302 + -0.3087812960147858 + <_> + <_> + + + <_> + 15 7 6 32 -1. + <_> + 17 7 2 32 3. + 0 + 7.5917987851426005e-004 + -0.3162926137447357 + 0.1653062999248505 + <_> + <_> + + + <_> + 14 7 5 18 -1. + <_> + 14 16 5 9 2. + 0 + 2.1138500887900591e-003 + 0.1573031991720200 + -0.4331406950950623 + <_> + <_> + + + <_> + 15 10 1 24 -1. + <_> + 15 18 1 8 3. + 0 + 7.9175382852554321e-003 + -0.0780236870050430 + 0.8861157894134522 + <_> + <_> + + + <_> + 14 18 18 1 -1. + <_> + 23 18 9 1 2. + 0 + 2.9891130980104208e-003 + -0.5088546872138977 + 0.1178615018725395 + <_> + <_> + + + <_> + 10 34 9 4 -1. + <_> + 13 34 3 4 3. + 0 + 2.7751970264944248e-005 + -0.3157913982868195 + 0.1484252065420151 + <_> + <_> + + + <_> + 12 9 9 3 -1. + <_> + 11 10 9 1 3. + 1 + 1.4359289780259132e-003 + -0.1167649030685425 + 0.4012225866317749 + <_> + <_> + + + <_> + 0 47 32 1 -1. + <_> + 8 47 16 1 2. + 0 + -0.0111336698755622 + -0.5935838222503662 + 0.0821303874254227 + <_> + <_> + + + <_> + 13 44 16 2 -1. + <_> + 21 44 8 2 2. + 0 + 2.3212779778987169e-003 + -0.2240175008773804 + 0.1884389966726303 + <_> + <_> + + + <_> + 14 4 6 16 -1. + <_> + 14 4 3 8 2. + <_> + 17 12 3 8 2. + 0 + -3.3007059246301651e-003 + -0.3570261001586914 + 0.1246019974350929 + <_> + <_> + + + <_> + 9 26 6 5 -1. + <_> + 11 28 2 5 3. + 1 + -0.0166743695735931 + 0.5634220242500305 + -0.0814267918467522 + <_> + <_> + + + <_> + 11 35 8 2 -1. + <_> + 11 35 8 1 2. + 1 + -4.2926319874823093e-003 + 0.6050165295600891 + -0.0755431130528450 + <_> + <_> + + + <_> + 17 22 10 2 -1. + <_> + 17 22 10 1 2. + 1 + -3.7003189208917320e-004 + -0.3132956922054291 + 0.1331911981105804 + <_> + <_> + + + <_> + 16 7 4 34 -1. + <_> + 16 24 4 17 2. + 0 + 0.0592420510947704 + -0.1017137020826340 + 0.4255366921424866 + <_> + <_> + + + <_> + 22 1 2 31 -1. + <_> + 23 1 1 31 2. + 0 + -1.6784629551693797e-003 + 0.4217154979705811 + -0.1007881984114647 + <_> + <_> + + + <_> + 1 0 10 1 -1. + <_> + 6 0 5 1 2. + 0 + -7.2429602732881904e-004 + -0.3753792047500610 + 0.1027007997035980 + <_> + <_> + + + <_> + 18 40 6 2 -1. + <_> + 18 40 3 1 2. + <_> + 21 41 3 1 2. + 0 + -3.4758399124257267e-004 + 0.3768458068370819 + -0.1022548004984856 + <_> + <_> + + + <_> + 15 4 6 16 -1. + <_> + 15 4 3 8 2. + <_> + 18 12 3 8 2. + 0 + 3.1677898950874805e-003 + 0.0944234579801559 + -0.3961910009384155 + <_> + <_> + + + <_> + 16 45 4 3 -1. + <_> + 17 45 2 3 2. + 0 + 6.0593069065362215e-004 + -0.1035407036542893 + 0.3802320063114166 + <_> + <_> + + + <_> + 10 9 14 6 -1. + <_> + 8 11 14 2 3. + 1 + -0.0230216495692730 + 0.4872168004512787 + -0.0702433288097382 + <_> + <_> + + + <_> + 10 34 10 3 -1. + <_> + 9 35 10 1 3. + 1 + -6.2999320216476917e-003 + 0.5414118766784668 + -0.0600615106523037 + <_> + <_> + + + <_> + 20 37 12 10 -1. + <_> + 26 37 6 10 2. + 0 + 5.8868258747679647e-006 + -0.2894780039787293 + 0.1375886052846909 + <_> + <_> + + + <_> + 15 16 16 8 -1. + <_> + 15 16 8 4 2. + <_> + 23 20 8 4 2. + 0 + -7.3050498031079769e-003 + 0.3075628876686096 + -0.1378595978021622 + <_> + <_> + + + <_> + 12 4 4 18 -1. + <_> + 12 4 2 9 2. + <_> + 14 13 2 9 2. + 0 + 3.7536039017140865e-003 + 0.0781634896993637 + -0.5922815203666687 + <_> + <_> + + + <_> + 0 22 28 5 -1. + <_> + 7 22 14 5 2. + 0 + -0.0127964001148939 + 0.1010608002543449 + -0.3623242974281311 + <_> + <_> + + + <_> + 12 34 4 4 -1. + <_> + 11 35 4 2 2. + 1 + 3.4985060337930918e-003 + -0.0684525072574615 + 0.6207485795021057 + <_> + <_> + + + <_> + 5 8 4 26 -1. + <_> + 5 8 2 13 2. + <_> + 7 21 2 13 2. + 0 + 0.0172151792794466 + -0.0518582016229630 + 0.6497529149055481 + <_> + <_> + + + <_> + 14 13 2 28 -1. + <_> + 14 27 2 14 2. + 0 + -3.3028179313987494e-003 + 0.2789609134197235 + -0.1344265043735504 + <_> + <_> + + + <_> + 14 31 4 8 -1. + <_> + 15 31 2 8 2. + 0 + 6.6051608882844448e-005 + -0.2671726047992706 + 0.1456511020660400 + <_> + <_> + + + <_> + 14 24 4 7 -1. + <_> + 15 24 2 7 2. + 0 + 1.6995379701256752e-003 + 0.0508588217198849 + -0.7037150859832764 + <_> + <_> + + + <_> + 15 24 4 15 -1. + <_> + 15 29 4 5 3. + 0 + 0.0313232205808163 + -0.0768466219305992 + 0.5539982914924622 + <_> + <_> + + + <_> + 12 23 12 4 -1. + <_> + 15 26 6 4 2. + 1 + -1.5424180310219526e-004 + 0.2022089958190918 + -0.2193786054849625 + <_> + <_> + + + <_> + 29 14 3 29 -1. + <_> + 30 14 1 29 3. + 0 + 4.4828761019743979e-004 + 0.1556259989738464 + -0.2406429946422577 + <_> + <_> + + + <_> + 14 15 3 8 -1. + <_> + 15 16 1 8 3. + 1 + 1.0528790298849344e-003 + -0.0919027328491211 + 0.3909038007259369 + <_> + <_> + + + <_> + 3 2 2 3 -1. + <_> + 3 2 1 3 2. + 1 + -4.3288318920531310e-006 + 0.2107463032007217 + -0.1708424985408783 + <_> + <_> + + + <_> + 0 0 6 11 -1. + <_> + 3 0 3 11 2. + 0 + 1.4604129828512669e-003 + 0.1186446994543076 + -0.3227553069591522 + <_> + <_> + + + <_> + 22 36 8 4 -1. + <_> + 22 36 8 2 2. + 1 + 4.3476051650941372e-003 + 0.1128780990839005 + -0.3135570883750916 + <_> + <_> + + + <_> + 10 26 9 13 -1. + <_> + 13 26 3 13 3. + 0 + 7.0836758241057396e-003 + -0.1730847954750061 + 0.2324849069118500 + <_> + <_> + + + <_> + 14 14 2 18 -1. + <_> + 14 14 1 9 2. + <_> + 15 23 1 9 2. + 0 + -1.3083920348435640e-003 + -0.6916018724441528 + 0.0535656884312630 + <_> + <_> + + + <_> + 12 11 11 3 -1. + <_> + 11 12 11 1 3. + 1 + -5.1133269444108009e-003 + 0.5658153295516968 + -0.0795868933200836 + <_> + <_> + + + <_> + 11 10 8 4 -1. + <_> + 10 11 8 2 2. + 1 + 2.5531630963087082e-003 + -0.0647788196802139 + 0.5570831894874573 + <_> + <_> + + + <_> + 6 2 8 4 -1. + <_> + 6 2 8 2 2. + 1 + 0.0117238098755479 + 0.0511469915509224 + -0.8184295892715454 + -1.1344679594039917 + 21 + -1 + <_> + + <_> + <_> + + + <_> + 8 0 5 22 -1. + <_> + 8 11 5 11 2. + 0 + -8.9049059897661209e-003 + 0.1087919026613236 + -0.5006157159805298 + <_> + <_> + + + <_> + 15 14 6 3 -1. + <_> + 17 16 2 3 3. + 1 + -1.1031040048692375e-004 + 0.1626991033554077 + -0.3225426077842712 + <_> + <_> + + + <_> + 16 17 4 7 -1. + <_> + 18 17 2 7 2. + 0 + 3.9447488961741328e-004 + 0.1657536029815674 + -0.3742505908012390 + <_> + <_> + + + <_> + 9 0 14 12 -1. + <_> + 9 3 14 6 2. + 0 + -0.0271371193230152 + 0.2987560927867889 + -0.1322928965091705 + <_> + <_> + + + <_> + 15 18 10 10 -1. + <_> + 15 18 10 5 2. + 1 + -0.0722216293215752 + 0.4460769891738892 + -0.1109754964709282 + <_> + <_> + + + <_> + 19 15 2 18 -1. + <_> + 19 24 2 9 2. + 0 + 2.0029500592499971e-003 + 0.1675457954406738 + -0.2940837144851685 + <_> + <_> + + + <_> + 16 25 9 3 -1. + <_> + 15 26 9 1 3. + 1 + 2.1959349978715181e-003 + -0.0771005675196648 + 0.4648905992507935 + <_> + <_> + + + <_> + 13 3 8 8 -1. + <_> + 15 5 4 8 2. + 1 + -0.0177626404911280 + 0.3188967108726502 + -0.1158680990338326 + <_> + <_> + + + <_> + 21 7 5 24 -1. + <_> + 21 13 5 12 2. + 0 + 5.6768842041492462e-003 + 0.0807807967066765 + -0.4153038859367371 + <_> + <_> + + + <_> + 4 6 8 17 -1. + <_> + 6 6 4 17 2. + 0 + -0.0236335508525372 + 0.3472653031349182 + -0.1044474020600319 + <_> + <_> + + + <_> + 12 32 10 4 -1. + <_> + 11 33 10 2 2. + 1 + 3.9141820743680000e-003 + -0.0933686569333076 + 0.4195348024368286 + <_> + <_> + + + <_> + 7 29 13 6 -1. + <_> + 7 29 13 3 2. + 1 + -0.0513451583683491 + 0.6389960050582886 + -0.0722599029541016 + <_> + <_> + + + <_> + 16 34 4 2 -1. + <_> + 16 34 4 1 2. + 1 + -4.8659418825991452e-004 + -0.2845937907695770 + 0.1299135982990265 + <_> + <_> + + + <_> + 17 24 8 2 -1. + <_> + 17 24 8 1 2. + 1 + 2.7822390620713122e-005 + -0.2341025024652481 + 0.1657306998968124 + <_> + <_> + + + <_> + 13 3 9 3 -1. + <_> + 13 4 9 1 3. + 0 + 8.3324511069804430e-004 + -0.1416071951389313 + 0.2642089128494263 + <_> + <_> + + + <_> + 15 6 6 34 -1. + <_> + 17 6 2 34 3. + 0 + 1.4958169776946306e-003 + -0.2381864935159683 + 0.1390489041805267 + <_> + <_> + + + <_> + 15 10 6 35 -1. + <_> + 17 10 2 35 3. + 0 + 0.0178654100745916 + 0.0628657266497612 + -0.7047213912010193 + <_> + <_> + + + <_> + 15 4 3 10 -1. + <_> + 16 5 1 10 3. + 1 + 8.0203928519040346e-004 + -0.1217579022049904 + 0.3103356957435608 + <_> + <_> + + + <_> + 9 33 8 3 -1. + <_> + 8 34 8 1 3. + 1 + 1.4314210275188088e-003 + -0.0912925824522972 + 0.3740335106849670 + <_> + <_> + + + <_> + 10 33 6 3 -1. + <_> + 9 34 6 1 3. + 1 + -5.0236908718943596e-003 + 0.5849642753601074 + -0.0605874694883823 + <_> + <_> + + + <_> + 30 0 2 9 -1. + <_> + 30 3 2 3 3. + 0 + 2.4552030954509974e-003 + 0.0709708482027054 + -0.5448635220527649 + <_> + <_> + + + <_> + 13 44 4 4 -1. + <_> + 14 44 2 4 2. + 0 + -6.1353767523542047e-004 + 0.2867903113365173 + -0.1268268972635269 + <_> + <_> + + + <_> + 10 8 4 25 -1. + <_> + 12 8 2 25 2. + 0 + 1.2587209930643439e-003 + -0.2303825020790100 + 0.1612862050533295 + <_> + <_> + + + <_> + 11 1 21 18 -1. + <_> + 11 7 21 6 3. + 0 + -0.0585747882723808 + 0.2135511040687561 + -0.1849295943975449 + <_> + <_> + + + <_> + 3 7 24 30 -1. + <_> + 11 17 8 10 9. + 0 + -0.3166919052600861 + 0.2255486994981766 + -0.1847517937421799 + <_> + <_> + + + <_> + 14 9 6 32 -1. + <_> + 14 25 6 16 2. + 0 + -0.0273504406213760 + 0.3338268101215363 + -0.1579629033803940 + <_> + <_> + + + <_> + 14 0 18 42 -1. + <_> + 14 0 9 21 2. + <_> + 23 21 9 21 2. + 0 + -0.0909027233719826 + 0.4312117099761963 + -0.1112976968288422 + <_> + <_> + + + <_> + 1 22 9 16 -1. + <_> + 4 22 3 16 3. + 0 + -0.0274412203580141 + 0.5565173029899597 + -0.0716778486967087 + <_> + <_> + + + <_> + 21 21 6 17 -1. + <_> + 23 21 2 17 3. + 0 + -0.0169991794973612 + 0.4388718903064728 + -0.0878521278500557 + <_> + <_> + + + <_> + 14 46 6 2 -1. + <_> + 16 46 2 2 3. + 0 + -6.9970771437510848e-004 + 0.2887707054615021 + -0.1320355981588364 + <_> + <_> + + + <_> + 18 14 5 30 -1. + <_> + 18 24 5 10 3. + 0 + -1.1233140248805285e-003 + 0.1154114976525307 + -0.3102774024009705 + <_> + <_> + + + <_> + 10 13 8 4 -1. + <_> + 10 13 8 2 2. + 1 + 9.0486078988760710e-004 + 0.1182276010513306 + -0.3477909862995148 + <_> + <_> + + + <_> + 7 16 16 4 -1. + <_> + 7 16 8 2 2. + <_> + 15 18 8 2 2. + 0 + 2.5414540432393551e-003 + -0.1079612970352173 + 0.4738101959228516 + <_> + <_> + + + <_> + 6 44 12 4 -1. + <_> + 6 44 6 2 2. + <_> + 12 46 6 2 2. + 0 + 1.2524890480563045e-003 + -0.1454291939735413 + 0.2704761922359467 + <_> + <_> + + + <_> + 0 4 3 4 -1. + <_> + 1 4 1 4 3. + 0 + 1.2755370698869228e-004 + 0.1118289008736610 + -0.3136644959449768 + <_> + <_> + + + <_> + 16 5 3 9 -1. + <_> + 17 6 1 9 3. + 1 + 1.5864979941397905e-003 + -0.0990065410733223 + 0.3575206995010376 + <_> + <_> + + + <_> + 14 4 4 20 -1. + <_> + 14 4 2 10 2. + <_> + 16 14 2 10 2. + 0 + 1.7153009539470077e-003 + 0.1035841032862663 + -0.4003409147262573 + <_> + <_> + + + <_> + 5 12 22 4 -1. + <_> + 5 12 11 2 2. + <_> + 16 14 11 2 2. + 0 + -4.7771320678293705e-003 + -0.5933225154876709 + 0.0616511404514313 + <_> + <_> + + + <_> + 20 26 7 3 -1. + <_> + 19 27 7 1 3. + 1 + 1.6136510530486703e-003 + -0.0770679712295532 + 0.4986394941806793 + <_> + <_> + + + <_> + 16 5 2 20 -1. + <_> + 16 5 1 10 2. + <_> + 17 15 1 10 2. + 0 + -8.1270089140161872e-004 + -0.4194312989711762 + 0.0933991074562073 + <_> + <_> + + + <_> + 20 4 8 4 -1. + <_> + 19 5 8 2 2. + 1 + 3.2309750095009804e-003 + -0.0957716107368469 + 0.4541470110416412 + <_> + <_> + + + <_> + 14 21 3 19 -1. + <_> + 15 21 1 19 3. + 0 + 3.0239850748330355e-003 + 0.0517625883221626 + -0.7150886058807373 + -1.0751069784164429 + 22 + -1 + <_> + + <_> + <_> + + + <_> + 0 0 29 16 -1. + <_> + 0 4 29 8 2. + 0 + -0.0161848608404398 + 0.1366720050573349 + -0.3486647903919220 + <_> + <_> + + + <_> + 18 33 2 7 -1. + <_> + 19 33 1 7 2. + 0 + -1.8796090444084257e-005 + 0.1568956971168518 + -0.2962532043457031 + <_> + <_> + + + <_> + 8 4 5 27 -1. + <_> + 8 13 5 9 3. + 0 + 8.9424904435873032e-003 + 0.1162585988640785 + -0.5396658182144165 + <_> + <_> + + + <_> + 9 14 2 16 -1. + <_> + 9 22 2 8 2. + 0 + 2.6768338866531849e-003 + 0.0911546573042870 + -0.4058134853839874 + <_> + <_> + + + <_> + 20 11 3 12 -1. + <_> + 21 12 1 12 3. + 1 + 1.9062990322709084e-003 + -0.0818805769085884 + 0.4221881926059723 + <_> + <_> + + + <_> + 16 5 16 15 -1. + <_> + 11 10 16 5 3. + 1 + -0.1151907965540886 + 0.2699753940105438 + -0.1351788938045502 + <_> + <_> + + + <_> + 8 18 10 4 -1. + <_> + 8 18 5 2 2. + <_> + 13 20 5 2 2. + 0 + 1.1125080054625869e-003 + -0.1400332003831863 + 0.3000448048114777 + <_> + <_> + + + <_> + 20 16 7 27 -1. + <_> + 20 25 7 9 3. + 0 + -0.0424706190824509 + -0.5792772173881531 + 0.0696459710597992 + <_> + <_> + + + <_> + 22 28 2 4 -1. + <_> + 22 28 1 4 2. + 1 + 7.9986598575487733e-004 + 0.0849977284669876 + -0.4442254900932312 + <_> + <_> + + + <_> + 22 11 5 36 -1. + <_> + 22 23 5 12 3. + 0 + -9.7261853516101837e-003 + 0.1711181998252869 + -0.2235164046287537 + <_> + <_> + + + <_> + 0 9 19 9 -1. + <_> + 0 12 19 3 3. + 0 + 0.0484269186854362 + 0.0264023095369339 + -0.8425363898277283 + <_> + <_> + + + <_> + 1 5 4 1 -1. + <_> + 1 5 2 1 2. + 1 + -8.4694866018253379e-006 + 0.1974688023328781 + -0.1894029974937439 + <_> + <_> + + + <_> + 14 11 9 4 -1. + <_> + 13 12 9 2 2. + 1 + 2.3363009095191956e-003 + -0.0927786231040955 + 0.4608100056648254 + <_> + <_> + + + <_> + 0 0 10 3 -1. + <_> + 5 0 5 3 2. + 0 + 3.8181859999895096e-003 + 0.0869487822055817 + -0.4722630977630615 + <_> + <_> + + + <_> + 12 0 3 36 -1. + <_> + 12 9 3 18 2. + 0 + -0.0450282394886017 + 0.3257930874824524 + -0.1160847991704941 + <_> + <_> + + + <_> + 16 8 1 8 -1. + <_> + 16 10 1 4 2. + 0 + 1.1932160123251379e-004 + -0.2303953021764755 + 0.1732441037893295 + <_> + <_> + + + <_> + 5 9 18 4 -1. + <_> + 5 9 9 2 2. + <_> + 14 11 9 2 2. + 0 + 7.6945088803768158e-003 + 0.0451414398849010 + -0.7242935895919800 + <_> + <_> + + + <_> + 4 2 1 4 -1. + <_> + 4 2 1 2 2. + 1 + -8.0604149843566120e-006 + 0.2110688984394074 + -0.1894055008888245 + <_> + <_> + + + <_> + 15 21 2 8 -1. + <_> + 15 23 2 4 2. + 0 + 1.4271639520302415e-004 + -0.2093152999877930 + 0.1804971992969513 + <_> + <_> + + + <_> + 27 6 5 28 -1. + <_> + 27 20 5 14 2. + 0 + 1.0051379649667069e-004 + -0.1417054980993271 + 0.2442114055156708 + <_> + <_> + + + <_> + 13 5 6 39 -1. + <_> + 15 5 2 39 3. + 0 + 0.0199977196753025 + 0.0523328110575676 + -0.6658095717430115 + <_> + <_> + + + <_> + 15 44 3 1 -1. + <_> + 16 44 1 1 3. + 0 + 6.5777247073128819e-005 + -0.1332021951675415 + 0.2826690077781677 + <_> + <_> + + + <_> + 28 7 4 10 -1. + <_> + 28 7 2 10 2. + 1 + -2.2363390598911792e-004 + 0.1088081970810890 + -0.3215278089046478 + <_> + <_> + + + <_> + 14 7 4 27 -1. + <_> + 15 7 2 27 2. + 0 + 2.1305120026227087e-004 + -0.2744595110416412 + 0.1315920948982239 + <_> + <_> + + + <_> + 16 10 8 5 -1. + <_> + 18 10 4 5 2. + 0 + 9.0748962247744203e-004 + -0.1373354941606522 + 0.2800961136817932 + <_> + <_> + + + <_> + 27 0 4 12 -1. + <_> + 27 0 2 12 2. + 1 + 0.0140150198712945 + 0.0537726990878582 + -0.6541829705238342 + <_> + <_> + + + <_> + 20 6 2 12 -1. + <_> + 20 9 2 6 2. + 0 + -2.1032799850217998e-005 + 0.1904495954513550 + -0.1845842003822327 + <_> + <_> + + + <_> + 11 7 9 18 -1. + <_> + 11 16 9 9 2. + 0 + 2.9602549038827419e-003 + 0.1003030017018318 + -0.3886381089687347 + <_> + <_> + + + <_> + 13 7 7 22 -1. + <_> + 13 18 7 11 2. + 0 + -4.2723170481622219e-003 + -0.1762516051530838 + 0.2256532013416290 + <_> + <_> + + + <_> + 11 10 9 28 -1. + <_> + 11 24 9 14 2. + 0 + -0.0336359106004238 + 0.3505505025386810 + -0.1778679043054581 + <_> + <_> + + + <_> + 8 31 13 4 -1. + <_> + 7 32 13 2 2. + 1 + -6.2371958047151566e-003 + 0.3437801003456116 + -0.1090065985918045 + <_> + <_> + + + <_> + 3 9 14 6 -1. + <_> + 3 11 14 2 3. + 0 + 0.0143058300018311 + 0.0421485118567944 + -0.8363417983055115 + <_> + <_> + + + <_> + 3 11 6 6 -1. + <_> + 5 11 2 6 3. + 0 + -7.3409960605204105e-003 + 0.4996119141578674 + -0.0802872031927109 + <_> + <_> + + + <_> + 8 10 7 2 -1. + <_> + 8 10 7 1 2. + 1 + -1.0542389936745167e-003 + 0.2001926004886627 + -0.2035170048475266 + <_> + <_> + + + <_> + 9 7 9 32 -1. + <_> + 12 7 3 32 3. + 0 + 5.3882119245827198e-003 + -0.2073697000741959 + 0.1914903074502945 + <_> + <_> + + + <_> + 9 0 23 26 -1. + <_> + 9 13 23 13 2. + 0 + -0.0819149911403656 + 0.1172119006514549 + -0.3079966008663178 + <_> + <_> + + + <_> + 14 15 9 22 -1. + <_> + 17 15 3 22 3. + 0 + 2.1687920670956373e-003 + -0.1934496015310288 + 0.1933349072933197 + <_> + <_> + + + <_> + 20 3 6 34 -1. + <_> + 22 3 2 34 3. + 0 + 2.0000250078737736e-003 + -0.1412031054496765 + 0.2738232016563416 + <_> + <_> + + + <_> + 12 24 6 6 -1. + <_> + 15 24 3 6 2. + 0 + -4.8200702294707298e-003 + -0.6858537793159485 + 0.0532982088625431 + <_> + <_> + + + <_> + 10 37 2 2 -1. + <_> + 10 37 1 1 2. + <_> + 11 38 1 1 2. + 0 + 5.4794199968455359e-005 + -0.1266207993030548 + 0.2954821884632111 + <_> + <_> + + + <_> + 11 3 14 18 -1. + <_> + 11 3 7 9 2. + <_> + 18 12 7 9 2. + 0 + 0.0112014701589942 + 0.1130717992782593 + -0.3085114061832428 + -0.9694861769676209 + 23 + -1 + <_> + + <_> + <_> + + + <_> + 15 7 2 30 -1. + <_> + 15 17 2 10 3. + 0 + -0.0121588995680213 + 0.1716108024120331 + -0.3103413879871368 + <_> + <_> + + + <_> + 3 38 27 6 -1. + <_> + 12 40 9 2 9. + 0 + -0.0124384304508567 + 0.1848385930061340 + -0.3088038861751556 + <_> + <_> + + + <_> + 10 3 17 6 -1. + <_> + 10 5 17 2 3. + 0 + -0.0200300104916096 + 0.3873254060745239 + -0.1429381966590881 + <_> + <_> + + + <_> + 9 5 17 8 -1. + <_> + 9 7 17 4 2. + 0 + -0.0171957202255726 + 0.4288637042045593 + -0.1125447005033493 + <_> + <_> + + + <_> + 4 2 19 6 -1. + <_> + 4 4 19 2 3. + 0 + -0.0120658995583653 + 0.3473758101463318 + -0.1668521016836166 + <_> + <_> + + + <_> + 2 16 22 8 -1. + <_> + 2 16 11 4 2. + <_> + 13 20 11 4 2. + 0 + 3.6652639973908663e-003 + -0.1692457050085068 + 0.2344986051321030 + <_> + <_> + + + <_> + 12 17 5 2 -1. + <_> + 12 17 5 1 2. + 1 + 4.4123671250417829e-004 + 0.1293334066867828 + -0.3529058098793030 + <_> + <_> + + + <_> + 13 18 18 2 -1. + <_> + 13 18 18 1 2. + 1 + 1.0714359814301133e-003 + -0.2359987944364548 + 0.1853300034999847 + <_> + <_> + + + <_> + 15 6 9 33 -1. + <_> + 18 17 3 11 9. + 0 + -0.0691857933998108 + 0.1696562021970749 + -0.2471480965614319 + <_> + <_> + + + <_> + 18 20 4 21 -1. + <_> + 19 20 2 21 2. + 0 + -1.6587899881415069e-004 + -0.2169685959815979 + 0.2170408964157105 + <_> + <_> + + + <_> + 21 34 8 6 -1. + <_> + 21 34 8 3 2. + 1 + 0.0129563100636005 + 0.0931500419974327 + -0.4756026864051819 + <_> + <_> + + + <_> + 9 10 10 8 -1. + <_> + 9 14 10 4 2. + 0 + 8.7745260680094361e-004 + -0.1469440013170242 + 0.2930724024772644 + <_> + <_> + + + <_> + 28 10 2 10 -1. + <_> + 28 10 1 10 2. + 1 + -1.3334110553842038e-004 + 0.1215528026223183 + -0.3337495028972626 + <_> + <_> + + + <_> + 10 11 8 14 -1. + <_> + 12 11 4 14 2. + 0 + 2.4040169955696911e-004 + -0.2523705065250397 + 0.1663237959146500 + <_> + <_> + + + <_> + 19 8 3 18 -1. + <_> + 19 17 3 9 2. + 0 + 1.0668949689716101e-003 + 0.1132405996322632 + -0.3790003061294556 + <_> + <_> + + + <_> + 11 2 4 31 -1. + <_> + 12 2 2 31 2. + 0 + 5.7366411201655865e-003 + 0.0429760590195656 + -0.8241596817970276 + <_> + <_> + + + <_> + 15 17 3 9 -1. + <_> + 15 20 3 3 3. + 0 + 2.0818989723920822e-003 + -0.1129266023635864 + 0.4063009917736054 + <_> + <_> + + + <_> + 6 12 4 24 -1. + <_> + 6 18 4 12 2. + 0 + -0.0134975202381611 + -0.4075238108634949 + 0.0941958725452423 + <_> + <_> + + + <_> + 9 34 10 4 -1. + <_> + 8 35 10 2 2. + 1 + -7.2435908950865269e-003 + 0.4733088910579681 + -0.0984209626913071 + <_> + <_> + + + <_> + 9 3 16 18 -1. + <_> + 9 3 8 9 2. + <_> + 17 12 8 9 2. + 0 + -0.0163447596132755 + -0.4721648991107941 + 0.0852129086852074 + <_> + <_> + + + <_> + 11 36 3 3 -1. + <_> + 10 37 3 1 3. + 1 + 1.9972459413111210e-003 + -0.0824345275759697 + 0.5790966749191284 + <_> + <_> + + + <_> + 25 1 2 11 -1. + <_> + 25 1 1 11 2. + 1 + 3.0349718872457743e-003 + 0.1095025017857552 + -0.4258275032043457 + <_> + <_> + + + <_> + 12 0 1 8 -1. + <_> + 12 0 1 4 2. + 1 + -3.9037179667502642e-003 + -0.6313412189483643 + 0.0568262897431850 + <_> + <_> + + + <_> + 29 0 2 10 -1. + <_> + 29 5 2 5 2. + 0 + 2.0907229554723017e-005 + -0.1760821938514710 + 0.2295151948928833 + <_> + <_> + + + <_> + 29 2 3 8 -1. + <_> + 29 6 3 4 2. + 0 + 2.7722110971808434e-003 + 0.0728858187794685 + -0.5522065758705139 + <_> + <_> + + + <_> + 27 20 4 9 -1. + <_> + 27 23 4 3 3. + 0 + -5.5504879128420725e-005 + 0.2079245001077652 + -0.2132809013128281 + <_> + <_> + + + <_> + 8 16 19 12 -1. + <_> + 8 20 19 4 3. + 0 + -7.2265428025275469e-004 + 0.1590195000171661 + -0.2620063126087189 + <_> + <_> + + + <_> + 18 13 4 10 -1. + <_> + 19 14 2 10 2. + 1 + 1.9136610208079219e-003 + -0.0784970223903656 + 0.5074850916862488 + <_> + <_> + + + <_> + 28 3 4 18 -1. + <_> + 29 4 2 18 2. + 1 + -3.4141771029680967e-003 + 0.2902137935161591 + -0.1399246007204056 + <_> + <_> + + + <_> + 14 24 4 13 -1. + <_> + 15 24 2 13 2. + 0 + -3.7384559982456267e-004 + -0.4684726893901825 + 0.0951626971364021 + <_> + <_> + + + <_> + 2 26 21 6 -1. + <_> + 9 28 7 2 9. + 0 + -0.0105797201395035 + 0.1294289976358414 + -0.3047446012496948 + <_> + <_> + + + <_> + 25 7 4 13 -1. + <_> + 26 8 2 13 2. + 1 + 2.0546799059957266e-003 + -0.0878863707184792 + 0.4652847945690155 + <_> + <_> + + + <_> + 18 5 6 24 -1. + <_> + 18 13 6 8 3. + 0 + 7.3390570469200611e-003 + 0.1012896001338959 + -0.3992291986942291 + <_> + <_> + + + <_> + 10 23 4 15 -1. + <_> + 11 23 2 15 2. + 0 + 2.2948970581637695e-005 + -0.2080135047435761 + 0.2017309963703156 + <_> + <_> + + + <_> + 6 41 6 1 -1. + <_> + 6 41 3 1 2. + 1 + 1.4831320149824023e-003 + 0.1211958974599838 + -0.3193506896495819 + <_> + <_> + + + <_> + 11 29 2 2 -1. + <_> + 11 29 1 2 2. + 1 + 1.1815720063168555e-004 + -0.1716165989637375 + 0.2500495016574860 + <_> + <_> + + + <_> + 12 26 3 7 -1. + <_> + 13 26 1 7 3. + 0 + -3.0121929012238979e-004 + -0.4144505858421326 + 0.1081463024020195 + -0.9046329259872437 + 24 + -1 + diff --git a/opencv_app/project/TrafficLightDetection/TrafficLightClassifier.cpp b/opencv_app/project/TrafficLightDetection/TrafficLightClassifier.cpp new file mode 100644 index 00000000..3bb71315 --- /dev/null +++ b/opencv_app/project/TrafficLightDetection/TrafficLightClassifier.cpp @@ -0,0 +1,54 @@ +#include +#include +#include +using namespace std; +using namespace cv; + +int main(void) +{ + CascadeClassifier trafficLightCascader; + string Cascade_name = "TrafficLight.xml"; + + if (!trafficLightCascader.load(Cascade_name)) + { + cout<<"Can't load the face feature data"< trafficLights; + + //离线图片 + ifstream imfile("E://TL//pics.txt"); + //char read_flag[100]; + string read_flag; + + while(getline(imfile, read_flag)) + { + + //离线图片 + //imfile>>read_flag; + + Mat src = imread(read_flag, -1); //-1,原始图片,不改变其深度和通道数 + CvRect AssignRect = Rect(0, 0, src.cols, src.rows/2); + Mat srcImage = src(AssignRect); + + Mat grayImage(srcImage.rows, srcImage.cols, CV_8UC1); + + cvtColor(srcImage, grayImage, CV_BGR2GRAY); + equalizeHist(grayImage, grayImage); //直方图均值化 + + trafficLightCascader.detectMultiScale(grayImage, trafficLights, 1.1, 1, CV_HAAR_SCALE_IMAGE | CV_HAAR_FEATURE_MAX, Size(3, 3)); + //trafficLightCascader.detectMultiScale(grayImage, trafficLights, 1.1, 3, 0, Size(3,3)); + //detectMultiScale()的cvSize参数表示:寻找交通灯的最小区域。设置这个参数过大,会以丢失小物体为代价减少计算量 + + for (int i=0; i + +#define DATA_DIR ".\\dataset\\" +#define IMG_MAX_NUM 20 + + +using namespace cv; +using namespace std; + +int main() +{ + FILE* fp; + FILE* fp_result; + fp = fopen("start.txt", "r"); //读取开始的图片名字,方便从某一图片开始标注 + int start_i = 0; + fscanf(fp, "%d", &start_i); + fclose(fp); + + fp_result = fopen("classify_record.txt", "a+"); //用于记录每张图每个框的标注信息 + + printf("start_i: %d\n", start_i); + + /*循环读取图片来标注*/ + for (int i = start_i; i < IMG_MAX_NUM; i++) + { + stringstream ss1,ss2,ss3; + + ss1 << DATA_DIR <<"data\\"<< i << ".jpg"; + ss3 << i << ".jpg"; + Mat src = imread(ss1.str()); + if (src.empty()) + { + continue; + } + printf("正在操作的图像: %s\n", string(ss1.str()).c_str()); + + imshow("标注", src); + + char c = 0; + c = waitKey(0); + while ( c != '1' && c != '2' && c != '3') + { + c = waitKey(0); + printf("invaid input!\n"); + } + + ss2 << DATA_DIR << c << "\\" << i << ".jpg"; + + char type = c - '0'; + printf("分类为: %d\n", c - '0'); + imwrite(ss2.str(), src); //copy一份到对应类别的文件夹 + fprintf(fp_result, "%s %d\n", string(ss3.str()).c_str(), type); + } + + + fclose(fp_result); + return 0; +} + + +``` +## 目标检测图像标注小工具 + +我们做标注时不仅仅要把我们想要识别的物体用矩形框将其框出来,还需要记录这个框的相关信息,比如这个框的左顶点坐标、宽度高度等(x,y,w,h)。为了能实现这个标注任务,这个标注小工具必须具备框图和自动记录(x,y,w,h)信息的功能。 + +利用opencv我们可以快速实现用矩形框框出对应物体的功能,再加上将每个矩形框的信息有序记录在txt文件的功能,一个用于检测图像标注小工具就算开发好了。 + +```c +#include "opencv2/imgproc.hpp" +#include "opencv2/highgui.hpp" +#include + + +#define DATA_DIR ".\\cut256\\" +#define IM_ROWS 5106 +#define IM_COLS 15106 +#define ROI_SIZE 256 + +using namespace cv; +using namespace std; + +Point ptL, ptR; //鼠标画出矩形框的起点和终点,矩形的左下角和右下角 +Mat imageSource, imageSourceCopy; +FILE* fp_result; + + +struct UserData +{ + Mat src; + vector rect; +}; + + +void OnMouse(int event, int x, int y, int flag, void *dp) +{ + UserData *d = (UserData *)dp; + imageSourceCopy = imageSource.clone(); + + if (event == CV_EVENT_LBUTTONDOWN) //按下鼠标右键,即拖动开始 + { + ptL = Point(x, y); + ptR = Point(x, y); + } + if (flag == CV_EVENT_FLAG_LBUTTON) //拖拽鼠标右键,即拖动进行 + { + ptR = Point(x, y); + imageSourceCopy = imageSource.clone(); + rectangle(imageSourceCopy, ptL, ptR, Scalar(0, 255, 0)); + imshow("标注", imageSourceCopy); + + } + if (event == CV_EVENT_LBUTTONUP) //拖动结束 + { + if (ptL != ptR) + { + rectangle(imageSourceCopy, ptL, ptR, Scalar(0, 255, 0)); + imshow("标注", imageSourceCopy); + + int h = ptR.y - ptL.y; + int w = ptR.x - ptL.x; + + + printf("选择的信息区域是:x:%d y:%d w:%d h:%d\n", ptL.x, ptL.y, w, h); + + d->rect.push_back(Rect(ptL.x, ptL.y, w, h)); + //d->src(imageSourceCopy); + } + } + + //点击右键删除一个矩形 + if (event == CV_EVENT_RBUTTONDOWN) + { + if (d->rect.size() > 0) + { + Rect temp = d->rect.back(); + + printf("删除的信息区域是:x:%d y:%d w:%d h:%d\n", temp.x, temp.y, temp.width, temp.height); + d->rect.pop_back(); + + for (int i = 0; i < d->rect.size(); i++) + { + rectangle(imageSourceCopy, d->rect[i], Scalar(0, 255, 0), 1); + } + + } + } + +} + + +void DrawArea(Mat& src, string img_name, string path_name) +{ + Mat img = src.clone(); + char c = 'x'; + UserData d; + d.src = img.clone(); + while (c != 'n') + { + Mat backup = src.clone(); + imageSource = img.clone(); + + namedWindow("标注", 1); + imshow("标注", imageSource); + setMouseCallback("标注", OnMouse, &d); + + c = waitKey(0); + + if (c == 'a') + { + printf("rect size: %d\n", d.rect.size()); + for (int i = 0; i < d.rect.size(); i++) + { + rectangle(backup, d.rect[i], Scalar(0, 255, 0), 1); + } + + img = backup.clone(); + + } + } + + fprintf(fp_result, "%s\n", img_name.c_str()); + fprintf(fp_result, "%d\n", d.rect.size()); + for (int i = 0; i < d.rect.size(); i++) + { + Rect t = d.rect[i]; + + fprintf(fp_result, "%d %d %d %d\n", t.x, t.y, t.width, t.height); + } + + imwrite(path_name, img); + + +} +int main() +{ + FILE* fp; + fp = fopen("start.txt", "r"); + int start_i = 0; + int start_j = 0; + fscanf(fp, "%d %d", &start_i, &start_j); + fclose(fp); + + fp_result = fopen("record.txt", "a+"); + + printf("start_i: %d, start_j: %d\n", start_i, start_j); + + + /*循环读取图片来标注*/ + for (int i = start_i; i< IM_ROWS / ROI_SIZE + 1; i++) + { + for (int j = start_j; j +#include +#include +#include +using namespace std; + +#define DATA_DIR ".\\cut256\\" + +#define IM_ROWS 5106 +#define IM_COLS 15106 +#define ROI_SIZE 256 +struct UserData +{ + cv::Mat src; + vector pts; +}; + +FILE* fpts_set; + +void on_mouse(int event, int x, int y, int flags, void *dp) +{ + UserData *d = (UserData *)dp; + if (event == CV_EVENT_LBUTTONDOWN) + { + d->pts.push_back(cv::Point(x, y)); + } + if (event == CV_EVENT_RBUTTONDOWN) + { + if (d->pts.size()>0) + d->pts.pop_back(); + } + cv::Mat temp = d->src.clone(); + if (d->pts.size()>2) + { + const cv::Point* ppt[1] = { &d->pts[0] }; + int npt[] = { static_cast(d->pts.size()) }; + cv::fillPoly(temp, ppt, npt, 1, cv::Scalar(0, 0, 255), 16); + + } + for (int i = 0; ipts.size(); i++) + { + cv::circle(temp, d->pts[i], 1, cv::Scalar(0, 0, 255), 1, 16); + } + cv::circle(temp, cv::Point(x, y), 1, cv::Scalar(0, 255, 0), 1, 16); + cv::imshow("2017", temp); + +} + +void WriteTxT(vector& pst) +{ + for (int i = 0; i < pst.size(); i++) + { + fprintf(fpts_set, "%d %d", pst[i].x, pst[i].y); + if (i == pst.size() - 1) + { + fprintf(fpts_set, "\n"); + } + else + { + fprintf(fpts_set, " "); + } + } +} + +int label_img(cv::Mat &src, cv::Mat &mask, string& name) +{ + char c = 'x'; + + vector > poly_point_set; + + while (c != 'n') + { + UserData d; + d.src = src.clone(); + + cv::namedWindow("2017", 1); + cv::setMouseCallback("2017", on_mouse, &d); + cv::imshow("2017", src); + c = cv::waitKey(0); + if (c == 'a') + { + if (d.pts.size()>0) + { + const cv::Point* ppt[1] = { &d.pts[0] }; + int npt[] = { static_cast(d.pts.size()) }; + cv::fillPoly(src, ppt, npt, 1, cv::Scalar(0, 0, 255), 16); + cv::fillPoly(mask, ppt, npt, 1, cv::Scalar(255), 16); + poly_point_set.push_back(d.pts); + } + + + } + } + + fprintf(stdout, "%s %d\n", name.c_str(), poly_point_set.size()); + fprintf(fpts_set, "%s %d\n", name.c_str(), poly_point_set.size()); + + //将点集写入文件 + for (int i = 0; i < poly_point_set.size(); i++) + { + WriteTxT(poly_point_set[i]); + } + + return 0; +} +int main() +{ + FILE* fp; + fp = fopen("start.txt", "r"); + int start_i = 0; + int start_j = 0; + fscanf(fp, "%d %d", &start_i, &start_j); + fclose(fp); + + fpts_set = fopen("semantic_label.txt", "a+"); + + printf("start_i: %d, start_j: %d\n", start_i, start_j); + + for (int i = start_i; i rgb Numpy +img_RGB = img_OpenCV[:, :, ::-1] + +# 显示灰度图 +cv2.imshow("OpenCV logo gray format", gray_image) + +# 保存文件 +cv2.imwrite("./gray", gray_image) + + +# difference = cv2.subtract(bgr_image, temp)# 矩阵相减 cv2.add(image, scalar) 相加 +# b, g, r = cv2.split(difference) # 矩阵通道分割 merge() 合并 +# img_matplotlib = cv2.merge([r, g, b]) # brg 图像 变成 RGB 图像 !!!!!!!! +# assert cv2.countNonZero(b) == 0 and cv2.countNonZero(g) == 0 and cv2.countNonZero(r) == 0 + + +# 等待键盘按键 +cv2.waitKey(0) + +# 销毁显示窗口 +cv2.destroyAllWindows() +``` + + +## 2. 命令行参数解析 摄像头读取 录制视频 +```python +import argparse +import cv2 + +# 时间 ==== +import datetime +import time + +# 解析命令行参数 +parser = argparse.ArgumentParser() + +# 添加key +parser.add_argument("path_image", help="path to input image to be displayed")# 添加 key +parser.add_argument("path_image_output", help="path of the processed image to be saved") +parser.add_argument("index_camera", help="index of the camera to read from", type=int)# 摄像头id +parser.add_argument("ip_url", help="IP URL to connect") # 网络摄像头 +parser.add_argument("video_path", help="path to the video file") # 视频文件 +# https://github.com/PacktPublishing/Mastering-OpenCV-4-with-Python/blob/master/Chapter03/01-chapter-content/read_video_file_all_properties.py + + +args = parser.parse_args()# 解析 +image_input = cv2.imread(args.path_image) +# 解析参数成字典 类型 +arg_dict = vars(parser.parse_args()) +image2 = cv2.imread(arg_dict["path_image"]) + +gray_image = cv2.cvtColor(image_input, cv2.COLOR_BGR2GRAY) +# 保存 +cv2.imwrite(arg_dict["path_image_output"], gray_image) + + +# 打开摄像头 +capture = cv2.VideoCapture(arg_dict["index_camera"]) +# capture = cv2.VideoCapture(arg_dict["ip_url"]) # 打开网络摄像头 +# https://github.com/PacktPublishing/Mastering-OpenCV-4-with-Python/blob/master/Chapter03/01-chapter-content/write_video_file.py # 写视频文件 录制视频 + +# capture = cv2.VideoCapture(arg_dict["video_path"]) # 打开 视频文件 +# https://github.com/PacktPublishing/Mastering-OpenCV-4-with-Python/blob/master/Chapter03/01-chapter-content/read_video_file_backwards.py # 反向播放视频 + + +# 获取参数 +frame_width = capture.get(cv2.CAP_PROP_FRAME_WIDTH) +frame_height = capture.get(cv2.CAP_PROP_FRAME_HEIGHT) +fps = capture.get(cv2.CAP_PROP_FPS) # 帧率 + +# 检测摄像头是否打开 +if capture.isOpened()is False: + print("Error opening the camera") + + +# 读取摄像头 +while capture.isOpened(): + # Capture frame-by-frame from the camera + ret, frame = capture.read() + + if ret is True: + # 开始时间 + processing_start = time.time() + # 显示原图 + cv2.imshow('Input frame from the camera', frame) + + # 转换成灰度图 + gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) + + # 显示 灰度图 + cv2.imshow('Grayscale input camera', gray_frame) + + # c 键 保存图像 + if cv2.waitKey(20) & 0xFF == ord('c'): + frame_name = "camera_frame_{}.png".format(frame_index) + gray_frame_name = "grayscale_camera_frame_{}.png".format(frame_index) + cv2.imwrite(frame_name, frame) + cv2.imwrite(gray_frame_name, gray_frame) + frame_index += 1 + + # 按键检测 关闭 q键 + if cv2.waitKey(20) & 0xFF == ord('q'): + break + + # 结束时间 + processing_end = time.time() + processing_time_frame = processing_end - processing_start #时间差 + print("fps: {}".format(1.0 / processing_time_frame))# 帧率 + + # Break the loop + else: + break + +# Release everything: +capture.release() + +``` + + +## 3. 绘制图形 GUI 鼠标响应 +https://github.com/PacktPublishing/Mastering-OpenCV-4-with-Python/tree/master/Chapter04/01-chapter-content + +```python +# 显示数字时钟 +""" +Example to show how to draw an analog clock OpenCV +""" + +# Import required packages: +import cv2 +import numpy as np +import datetime +import math + + +def array_to_tuple(arr): + return tuple(arr.reshape(1, -1)[0]) + + +# Dictionary containing some colors +colors = {'blue': (255, 0, 0), 'green': (0, 255, 0), 'red': (0, 0, 255), 'yellow': (0, 255, 255), + 'magenta': (255, 0, 255), 'cyan': (255, 255, 0), 'white': (255, 255, 255), 'black': (0, 0, 0), + 'gray': (125, 125, 125), 'rand': np.random.randint(0, high=256, size=(3,)).tolist(), + 'dark_gray': (50, 50, 50), 'light_gray': (220, 220, 220)} + +# We create the canvas to draw: 640 x 640 pixels, 3 channels, uint8 (8-bit unsigned integers) +# We set background to black using np.zeros() +image = np.zeros((640, 640, 3), dtype="uint8") + +# If you want another background color you can do the following: +image[:] = colors['light_gray'] + +# Coordinates to define the origin for the hour markings: +hours_orig = np.array( + [(620, 320), (580, 470), (470, 580), (320, 620), (170, 580), (60, 470), (20, 320), (60, 170), (169, 61), (319, 20), + (469, 60), (579, 169)]) + +# Coordinates to define the destiny for the hour markings: +hours_dest = np.array( + [(600, 320), (563, 460), (460, 562), (320, 600), (180, 563), (78, 460), (40, 320), (77, 180), (179, 78), (319, 40), + (459, 77), (562, 179)]) + +# We draw the hour markings: +for i in range(0, 12): + cv2.line(image, array_to_tuple(hours_orig[i]), array_to_tuple(hours_dest[i]), colors['black'], 3) + +# We draw a big circle, corresponding to the shape of the analog clock +cv2.circle(image, (320, 320), 310, colors['dark_gray'], 8) + +# We draw the rectangle containig the text and the text "Mastering OpenCV 4 with Python": +cv2.rectangle(image, (150, 175), (490, 270), colors['dark_gray'], -1) +cv2.putText(image, "Mastering OpenCV 4", (150, 200), 1, 2, colors['light_gray'], 1, cv2.LINE_AA) +cv2.putText(image, "with Python", (210, 250), 1, 2, colors['light_gray'], 1, cv2.LINE_AA) + +# We make a copy of the image with the "static" information +image_original = image.copy() + +# Now, we draw the "dynamic" information: +while True: + # Get current date: + date_time_now = datetime.datetime.now() + # Get current time from the date: + time_now = date_time_now.time() + # Get current hour-minute-second from the time: + hour = math.fmod(time_now.hour, 12) + minute = time_now.minute + second = time_now.second + + print("hour:'{}' minute:'{}' second: '{}'".format(hour, minute, second)) + + # Get the hour, minute and second angles: + second_angle = math.fmod(second * 6 + 270, 360) + minute_angle = math.fmod(minute * 6 + 270, 360) + hour_angle = math.fmod((hour * 30) + (minute / 2) + 270, 360) + + print("hour_angle:'{}' minute_angle:'{}' second_angle: '{}'".format(hour_angle, minute_angle, second_angle)) + + # Draw the lines corresponding to the hour, minute and second needles + second_x = round(320 + 310 * math.cos(second_angle * 3.14 / 180)) + second_y = round(320 + 310 * math.sin(second_angle * 3.14 / 180)) + cv2.line(image, (320, 320), (second_x, second_y), colors['blue'], 2) + + minute_x = round(320 + 260 * math.cos(minute_angle * 3.14 / 180)) + minute_y = round(320 + 260 * math.sin(minute_angle * 3.14 / 180)) + cv2.line(image, (320, 320), (minute_x, minute_y), colors['blue'], 8) + + hour_x = round(320 + 220 * math.cos(hour_angle * 3.14 / 180)) + hour_y = round(320 + 220 * math.sin(hour_angle * 3.14 / 180)) + cv2.line(image, (320, 320), (hour_x, hour_y), colors['blue'], 10) + + # Finally, a small circle, corresponding to the point where the three needles joint, is drawn: + cv2.circle(image, (320, 320), 10, colors['dark_gray'], -1) + + # Show image: + cv2.imshow("clock", image) + + # We get the image with the static information: + image = image_original.copy() + + # A wait of 500 milliseconds is performed (to see the displayed image): + cv2.waitKey(500) + +``` + + + +## 4. 图像处理 滤波 平滑 位操作 + +```python +image = cv2.imread('lenna.png') +# 高斯核滤波 +image_filtered = cv2.GaussianBlur(image, (3, 3), 0) +# 灰度图 +gray_image = cv2.cvtColor(image_filtered, cv2.COLOR_BGR2GRAY) +# 水平梯度 输出精度 16位 signed integers +gradient_x = cv2.Sobel(gray_image, cv2.CV_16S, 1, 0, 3) +# 垂直梯度 +gradient_y = cv2.Sobel(gray_image, cv2.CV_16S, 0, 1, 3) + +# 转换到 无符号,取绝对值 +abs_gradient_x = cv2.convertScaleAbs(gradient_x) +abs_gradient_y = cv2.convertScaleAbs(gradient_y) +# 叠加 +sobel_image = cv2.addWeighted(abs_gradient_x, 0.5, abs_gradient_y, 0.5, 0) + + +# 中值滤波===== +img_gray = cv2.medianBlur(img_gray, 5) +# 拉普拉斯变换 检测边缘==== +edges = cv2.Laplacian(img_gray, cv2.CV_8U, ksize=5) +# 阈值二值化==== +ret, thresholded = cv2.threshold(edges, 70, 255, cv2.THRESH_BINARY_INV) + +# 双边滤波 +filtered = cv2.bilateralFilter(img, 10, 250, 250) +# https://github.com/PacktPublishing/Mastering-OpenCV-4-with-Python/blob/master/Chapter05/01-chapter-content/cartoonizing.py # 图片卡通 化 +# 各种颜色空间 +# https://github.com/PacktPublishing/Mastering-OpenCV-4-with-Python/blob/master/Chapter05/01-chapter-content/color_map_all.py + +# 位操作======================掩码========= +# Create the first image: +img_1 = np.zeros((300, 300), dtype="uint8") +cv2.rectangle(img_1, (10, 10), (110, 110), (255, 255, 255), -1) +cv2.circle(img_1, (200, 200), 50, (255, 255, 255), -1) + +# Create the second image: +img_2 = np.zeros((300, 300), dtype="uint8") +cv2.rectangle(img_2, (50, 50), (150, 150), (255, 255, 255), -1) +cv2.circle(img_2, (225, 200), 50, (255, 255, 255), -1) + +# Bitwise OR 位或 +bitwise_or = cv2.bitwise_or(img_1, img_2) + +# Bitwise AND 位与 +bitwise_and = cv2.bitwise_and(img_1, img_2) + +# Bitwise XOR 位异或 +bitwise_xor = cv2.bitwise_xor(img_1, img_2) + +# Bitwise NOT 位 非操作 +bitwise_not_1 = cv2.bitwise_not(img_1) + +# Bitwise NOT +bitwise_not_2 = cv2.bitwise_not(img_2) + +# 腐蚀膨胀 开闭 区域操作 +https://github.com/PacktPublishing/Mastering-OpenCV-4-with-Python/blob/master/Chapter05/01-chapter-content/morphological_operations.py + +``` + + + +## 5. 颜色直方图 + +```python +histr = [] +histr.append(cv2.calcHist([img], [0], None, [256], [0, 256])) +histr.append(cv2.calcHist([img], [1], None, [256], [0, 256])) +histr.append(cv2.calcHist([img], [2], None, [256], [0, 256])) +# https://github.com/PacktPublishing/Mastering-OpenCV-4-with-Python/tree/master/Chapter06/01-chapter-content + + +# 直方图模板匹配 分类器 +https://github.com/PacktPublishing/OpenCV-4-for-Secret-Agents-Second-Edition/blob/master/Chapter002/HistogramClassifier.py + +``` + + + +## 6.阈值处理 + +```python +# 自适应阈值 +thresh1 = cv2.adaptiveThreshold(gray_image, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2) +thresh2 = cv2.adaptiveThreshold(gray_image, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 31, 3) +thresh3 = cv2.adaptiveThreshold(gray_image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2) +thresh4 = cv2.adaptiveThreshold(gray_image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 31, 3) +# https://github.com/PacktPublishing/Mastering-OpenCV-4-with-Python/tree/master/Chapter07/01-chapter-content +``` + + + +## 7.边缘轮廓区域 + +```python +# https://github.com/PacktPublishing/Mastering-OpenCV-4-with-Python/tree/master/Chapter08/01-chapter-content + +``` + + + +## 8. 相机 aruco 校正 +```python +# 相机 aruco 码 校正 +https://github.com/PacktPublishing/Mastering-OpenCV-4-with-Python/blob/master/Chapter09/01-chapter-content/aruco_camera_calibration.py + +# aruco 码识别 增强现实 +# https://github.com/PacktPublishing/Mastering-OpenCV-4-with-Python/blob/master/Chapter09/01-chapter-content/aruco_detect_markers_augmented_reality.py +# https://blog.csdn.net/ZJU_fish1996/article/details/72312514?fps=1&locationNum=7 +``` + + +## 9. 特征检测 + +```python +# orb 特征点 ===================== +# Load test image: +image = cv2.imread('opencv_logo_with_text.png') + +# Initiate ORB detector: +orb = cv2.ORB_create() + +# Detect the keypoints using ORB: +keypoints = orb.detect(image, None) + +# Compute the descriptors of the detected keypoints: +keypoints, descriptors = orb.compute(image, keypoints) + +# Print one ORB descriptor: +print("First extracted descriptor: {}".format(descriptors[0])) + +# Draw detected keypoints: +image_keypoints = cv2.drawKeypoints(image, keypoints, None, color=(255, 0, 255), flags=0) + +# 检测 + 描述子 +# https://github.com/PacktPublishing/Mastering-OpenCV-4-with-Python/blob/master/Chapter09/01-chapter-content/feature_matching.py + +# Detect the keypoints and compute the descriptors with ORB: +keypoints_1, descriptors_1 = orb.detectAndCompute(image_query, None) +keypoints_2, descriptors_2 = orb.detectAndCompute(image_scene, None) +# 特征匹配 +bf_matcher = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True) +bf_matches = bf_matcher.match(descriptors_1, descriptors_2) +# Sort the matches in the order of their distance: +bf_matches = sorted(bf_matches, key=lambda x: x.distance) + +# 特征检测模板匹配物体识别 +# https://github.com/PacktPublishing/Mastering-OpenCV-4-with-Python/blob/master/Chapter09/01-chapter-content/feature_matching_object_recognition.py + +# 二维码扫描 +https://github.com/PacktPublishing/Mastering-OpenCV-4-with-Python/blob/master/Chapter09/01-chapter-content/qr_code_scanner.py + + +# 级联回归 人脸 人眼检测 + 卡通眼睛 +# https://github.com/PacktPublishing/Mastering-OpenCV-4-with-Python/blob/master/Chapter09/01-chapter-content/snapchat_augmeted_reality_glasses.py + +``` + + + + + +```python + + +``` + + + + + +```python + + +``` + + + + + +```python + + +``` + + + + + +```python + + +``` + + + + + +```python + + +``` + + + + + +```python + + +``` + + + + +```python + + +``` + + + +```python + + +``` + + + + +```python + + +``` + + + + + +```python + + +``` + + + + + +```python + + +``` + + + + + +```python + + +``` + + + + + +```python + + +``` + + + + + +```python + + +``` + + + + +```python + + +``` + + + + +```python + + +``` + + + + + +```python + + +``` + + + + + +```python + + +``` + + + + + +```python + + +``` + + + + + +```python + + +``` + + + + + +```python + + +``` + + + + + +```python + + +``` + + + + +```python + + +``` diff --git a/opencv_app/readme.md b/opencv_app/readme.md index 9e7f4eab..7010b708 100644 --- a/opencv_app/readme.md +++ b/opencv_app/readme.md @@ -1,4 +1,11 @@ -# opencv 学习 +# opencv 学习 图像处理等 +[简单易用的图像解码库 stb_image](https://github.com/Ewenwan/stb) + +[linux android window 下的jpeg解码库 libjpeg-turbo](https://blog.csdn.net/gdp12315_gu/article/details/45061947) + +[Hands-On-Algorithms-for-Computer-Vision 代码](https://github.com/PacktPublishing/Hands-On-Algorithms-for-Computer-Vision) + +[OpenCV 3 Computer Vision Application Programming Cookbook, Third Edition](https://github.com/PacktPublishing/OpenCV3-Computer-Vision-Application-Programming-Cookbook-Third-Edition) [计算机视觉OpenCV实现 csdn专栏](https://blog.csdn.net/column/details/computer-vision.html?&page=3) [机器视觉与计算机视觉](https://www.cnblogs.com/ironstark/category/745953.html) @@ -34,6 +41,13 @@ ## window下安装 + 下载地址 https://sourceforge.net/projects/opencvlibrary/files/opencv-win/ + + python 下 opencv安装 https://www.cnblogs.com/ncuhwxiong/p/7439604.html + 安装 Numpy https://www.lfd.uci.edu/~gohlke/pythonlibs/#numpy + 安装 opencv https://www.lfd.uci.edu/~gohlke/pythonlibs/#opencv + 使用 pip install 安装whl + 1、系统环境变量设置 动态链接库配置 计算机 -> 右键属性 ->高级系统设置 -> 高级标签 -> 最下边 环境变量 diff --git a/robot/Human_robot/readme.md b/robot/Human_robot/readme.md index 85130c96..d97c9c8a 100644 --- a/robot/Human_robot/readme.md +++ b/robot/Human_robot/readme.md @@ -6,6 +6,8 @@ [上交大博士 机器人 机械臂 ros ai](https://mp.weixin.qq.com/mp/homepage?__biz=MzA5MDE2MjQ0OQ==&hid=1&sn=47d7dfc323ce159a87d68d3e6d7fa09c&scene=18&devicetype=android-25&version=26070336&lang=zh_CN&nettype=WIFI&ascene=7&session_us=gh_e4a5e3dc2cde&pass_ticket=GUYqMrcaykeEbRgrCw0aeD%2BfAzY39PVt%2Bi56mOUARZhCrsvWuLlkpUmDb3YAV5LN&wx_header=1&scene=1) +[机器人手眼标定](https://github.com/Ewenwan/RoboCamCal) + [课程分享 | 机器视觉与物体抓取 古月居 ](https://mp.weixin.qq.com/s?__biz=MzIyMzkxODg0Mw==&mid=2247484445&idx=1&sn=8f10fb4ee78da414588ffabd3eb721a6&chksm=e817ab89df60229f5888a2ec660649d81f371f16f7eff60b982e78fea0a6fe1c0762bc433e15&mpshare=1&scene=1&srcid=1023JPEqq835Iu6CamiVpO2R&pass_ticket=GUYqMrcaykeEbRgrCw0aeD%2BfAzY39PVt%2Bi56mOUARZhCrsvWuLlkpUmDb3YAV5LN#rd) diff --git a/robot/Localization/readme.md b/robot/Localization/readme.md index efbe9dd4..da3fdf2c 100644 --- a/robot/Localization/readme.md +++ b/robot/Localization/readme.md @@ -13,10 +13,13 @@ [机器人学 —— 机器人感知(Kalman Filter)](https://www.cnblogs.com/ironstark/p/5537219.html) +[EKF-SLAM 算法实现,以ArUco码为路标](https://github.com/Ewenwan/aruco_ekf_slam) + # 3. 粒子滤波定位 连续状态 多峰值数据 [机器人学 —— 机器人感知(Location) 粒子滤波器 ](https://www.cnblogs.com/ironstark/p/5570071.html) +[[PR-2] PF 粒子滤波/蒙特卡罗定位](https://github.com/Ewenwan/particle_filter_localization) # 一. 贝叶斯概率滤波 蒙特卡洛滤波 diff --git a/robot/Search/BFS-DFS.md b/robot/Search/BFS-DFS.md new file mode 100644 index 00000000..03b679da --- /dev/null +++ b/robot/Search/BFS-DFS.md @@ -0,0 +1,429 @@ +# BFS-DFS 广度和深度优先搜索 + +## BFS 宽度优先搜索算法(又称广度优先搜索) +* [示例1. 赛码网小赛旅游](#示例1-赛码网小赛旅游) + +* [示例2. 走迷宫](#示例2-走迷宫) + +* [示例3. hero--拯救公主](#示例3-hero--拯救公主) + + + +  宽度优先搜索算法(又称广度优先搜索)是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。 + +  广度优先搜索是一种分层的查找过程,每向前走一步可能访问一批顶点,不像深度优先搜索那样有回退的情况,因此它不是一个递归的算法,为了实现逐层的访问,算法必须借助一个先进先出的辅助**队列**并且以非递归的形式来实现。 + +**算法的基本思路:** + +  我们采用示例图来说明这个过程,在搜索的过程中,初始所有节点是白色(代表了所有点都还没开始搜索),把起点V0标志成灰色(表示即将辐射V0),下一步搜索的时候,我们把所有的灰色节点访问一次,然后将其变成黑色(表示已经被辐射过了),进而再将他们所能到达的节点标志成灰色(因为那些节点是下一步搜索的目标点了),当访问到V1节点的时候,它的下一个节点应该是V0和V4,但是V0已经在前面被染成黑色了,所以不会将它染灰色。这样持续下去,直到目标节点V6被染灰色,说明了下一步就到终点了,没必要再搜索(染色)其他节点了,此时可以结束搜索了,整个搜索就结束了。然后根据搜索过程,反过来把最短路径找出来,图中把最终路径上的节点标志成绿色。 + +

初始全部都是白色(未访问

+

即将搜索起点

+

已搜索V0,即将搜索V1、V2、V3

+

……终点V6被染灰色,终止

+

找到最短路径

+ +**广度优先搜索流程图** + + + + +**1. 无向图的广度优先搜索** + + + +``` +第1步:访问A。 +第2步:依次访问C,D,F。 + 在访问了A之后,接下来访问A的邻接点。前面已经说过,在本文实现中,顶点ABCDEFG按照顺序存储的,C在"D和F"的前面,因此,先访问C。再访问完C之后,再依次访问D,F。 +第3步:依次访问B,G。 + 在第2步访问完C,D,F之后,再依次访问它们的邻接点。首先访问C的邻接点B,再访问F的邻接点G。 +第4步:访问E。 + 在第3步访问完B,G之后,再依次访问它们的邻接点。只有G有邻接点E,因此访问G的邻接点E。 + +因此访问顺序是:A -> C -> D -> F -> B -> G -> E +``` + +**2. 有向图的广度优先搜索** + + + +``` +第1步:访问A。 +第2步:访问B。 +第3步:依次访问C,E,F。 + 在访问了B之后,接下来访问B的出边的另一个顶点,即C,E,F。前面已经说过,在本文实现中,顶点ABCDEFG按照顺序存储的,因此会先访问C,再依次访问E,F。 +第4步:依次访问D,G。 + 在访问完C,E,F之后,再依次访问它们的出边的另一个顶点。还是按照C,E,F的顺序访问,C的已经全部访问过了,那么就只剩下E,F;先访问E的邻接点D,再访问F的邻接点G。 + +因此访问顺序是:A -> B -> C -> E -> F -> D -> G +``` + +----------------------------- + +### 示例1. [赛码网:小赛旅游](http://exercise.acmcoder.com/online/online_judge_ques?ques_id=2267&konwledgeId=139) + +**题目描述** + +小赛很想到外面的世界看看,于是收拾行装准备旅行。背了一个大竹筐,竹筐里装满了路上吃的,这些吃的够它走N公里。为了规划路线,它查看了地图,沿途中有若干个村庄,在这些村庄它都可以补充食物。但每次补充食物都需要花费时间,在它竹筐的食物足够可以走到下一个村庄的时候它就不用补充,这样背起来不累而且不花费时间。地图上可以看到村庄之间的距离,现在它要规划一下它的路线,确定在哪些村庄补充食物可以使沿途补充食物的次数最少。你能帮帮小赛吗? +输入描述: +``` +第一行有两个数字,第一个数字为竹筐装满可以走的公里数,即N值;第二个数字为起点到终点之间的村庄个数。 +第二行为起点和村庄、村庄之间、村庄和终点之间的距离。且范围不能超过一个int型表达的范围。 + 示例: + 7 4 + 5 6 3 2 2 +```` +输出描述: +``` +程序输出为至少需要补充食物的次数。 +示例: +2 +``` + +```python +''' +判断每段距离与装行李的重量N的大小,当dis[i]= dis[i+1]即食物完全满足两段路的需求, + 将N-dis[i]重新赋给N继续走下一段路; +否则就没走一段路到达村庄后补给食物即装满N。 +''' +num = list(map(int, raw_input().split())) +dis = list(map(int, raw_input().split())) +N = num[0] +m = num[1] +count = 0 +for i in range(m): + if dis[i] > num[0]: + break + elif N - dis[i] >= dis[i+1]: + N = N - dis[i] + else: + N = num[0] + count += 1 +print count +``` + + +### 示例2. 走迷宫 + +https://github.com/ShaoQiBNU/mazes_BFS + +https://github.com/BrickXu/subway + +**问题描述** + +输入一组10 x 10的数据,由#和.组成的迷宫,其中#代表墙,.代表通路,入口在第一行第二列,出口在最后一行第九列,从任意一个.都能一步走到上下左右四个方向的.,请求出从入口到出口最短需要几步? +输入示例: +``` +#.######## #.######## +#........# #........# +#........# ########.# +#........# #........# +#........# #.######## +#........# #........# +#........# ########.# +#........# #........# +#........# #.######.# +########.# ########.# +结果为:16 结果为: 30 + +``` + +```python +# 因为题意是使用最少的步数走出迷宫,所要可以使用广度优先遍历的方式,每处理完一层说明走了一步,最先到达出口使用的步数最少。 + +import numpy as np +def bfs(N,maps,start,end): + """ + 1:已经访问;0: 每访问 + :param N: 矩阵大小 + :param maps: 矩阵 + :param start: 开始点 + :param end: 结束点 + :return: 步数 + """ + # 上下左右四个方向的增量 + dx = [1,-1,0,0] + dy = [0,0,1,-1] + + # 用于存放节点 + nodes = [] + # 开始的节点(x坐标,y坐标,步数) + nodes.append((0,1,0)) + + # 节点访问列表—记录节点是否被访问 + visitNodes = np.array([[0] * N] * N) + visitNodes[0][1] = 1 + + # bfs过程 + while len(nodes): + # 上下左右四个方向遍历 + for i in range(4): + # 从节点列表输出一个节点 + node = nodes[0] + # 上下左右四个方向遍历 + x = node[0] + dx[i] + y = node[1] + dy[i] + # 步数 + step = node[2] + # 判断是否到达终点 + if x ==9 and y == 8: + return step+1 + # 判断节点是否符合条件 + if x>=1 and x<=9 and y>=1 and y<=9 and visitNodes[x][y] == 0 and maps[x][y] == 1: + # 将节点压入节点列表nodes,说明进入下一层,step+1 + nodes.append((x,y,step+1)) + # 访问过该节点 + visitNodes[x][y] = 1 + # 从节点列表移除上一层的节点 + del nodes[0] + # 没有路径无法走出时,返回0 + return 0 + + + +if __name__ == '__main__': + maps1 = np.array([[0, 2, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 1, 1, 1, 1, 1, 0] + , [0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 1, 1, 1, 1, 1, 1, 1, 1, 0] + , [0, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 1, 1, 1, 1, 1, 0] + , [0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 1, 1, 1, 1, 1, 1, 1, 1, 0] + , [0, 1, 0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0, 3, 0]]) + maps2 = np.array([[0, 2, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 1, 1, 1, 1, 1, 0] + , [0, 1, 1, 1, 1, 1, 1, 1, 1, 0], [0, 1, 1, 1, 1, 1, 1, 1, 1, 0] + , [0, 1, 1, 1, 1, 1, 1, 1, 1, 0], [0, 1, 1, 1, 1, 1, 1, 1, 1, 0] + , [0, 1, 1, 1, 1, 1, 1, 1, 1, 0], [0, 1, 1, 1, 1, 1, 1, 1, 1, 0] + , [0, 1, 1, 1, 1, 1, 1, 1, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0, 3, 0]]) + + res = bfs(10,maps2,2,3) + print(res) + +``` + +### 示例3. [hero | 拯救公主](https://www.nowcoder.com/practice/661b4d5797f04b13af291befe051d5e9?tpId=3&&tqId=10875&rp=2&ru=/activity/oj&qru=/ta/hackathon/question-ranking) + +**题目描述** +500年前,nowcoder是我国最卓越的剑客。他英俊潇洒,而且机智过人^_^。 突然有一天,nowcoder 心爱的公主被魔王困在了一个巨大的迷宫中。nowcoder 听说这个消息已经是两天以后了,他知道公主在迷宫中还能坚持T天,他急忙赶到迷宫,开始到处寻找公主的下落。 时间一点一点的过去,nowcoder 还是无法找到公主。最后当他找到公主的时候,美丽的公主已经死了。从此nowcoder 郁郁寡欢,茶饭不思,一年后追随公主而去了。T_T 500年后的今天,nowcoder 托梦给你,希望你帮他判断一下当年他是否有机会在给定的时间内找到公主。 他会为你提供迷宫的地图以及所剩的时间T。请你判断他是否能救出心爱的公主。 +输入描述: +``` +每组测试数据以三个整数N,M,T(00)开头,分别代表迷宫的长和高,以及公主能坚持的天数。 +紧接着有M行,N列字符,由".","*","P","S"组成。其中 +"." 代表能够行走的空地。 +"*" 代表墙壁,redraiment不能从此通过。 +"P" 是公主所在的位置。 +"S" 是redraiment的起始位置。 +每个时间段里redraiment只能选择“上、下、左、右”任意一方向走一步。 +输入以0 0 0结束 +示例: +4 4 10 +.... +.... +.... +S**P +0 0 0 +``` +输出描述: +``` +如果能在规定时间内救出公主输出“YES”,否则输出“NO”。 +示例: +YES +``` + +```python +def bfs(maps, n, m, t): + start = () + end = () + for i in range(0, m): + for j in range(0, n): + if maps[i][j] == 'S': + start = (i, j) + if maps[i][j] == 'P': + end = (i, j) + if len(start) == 0 or len(end)==0: + return 'NO' + + dx = [1, -1, 0, 0] + dy = [0, 0, 1, -1] + nodes_cur = [] + nodes_cur.append(start) + nodes_next = [] + node_visit = [[0 for _ in range(n)] for _ in range(m) ] + node_visit[start[0]][start[1]] = 1 + while len(nodes_cur) != 0: + for i in range(0, 4): + node = nodes_cur[0] + x = node[0] + dx[i] + y = node[1] + dy[i] + if x == end[0] and y == end[1] : + return 'YES' + if x >= 0 and x < m and y >= 0 and y < n and node_visit[x][y] == 0 and maps[x][y] == '.': + nodes_next.append((x, y)) + node_visit[x][y] = 1 + del (nodes_cur[0]) + if len(nodes_cur) == 0: + t = t - 1 + if t < 0: + return 'NO' + else: + nodes_cur = nodes_next.copy() + nodes_next = [] + return 'NO' +if __name__ == '__main__': + maps = [] + s=input() + if s == '0 0 0': + print('NO') + else: + n,m,t = map(int,s.split()) + while 1: + s = input() + if s == '0 0 0': + break + else: + maps.append(list(s)) + res = bfs(maps, n, m, t) + print (res ) + +``` + + +## 深度优先搜索 + +  简要来说dfs是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次。深度优先搜索的缺点也出来了:**难以寻找最优解**,仅仅只能寻找有解。其优点就是**内存消耗小**。 + +算法思想: + +  假设初始状态是图中所有顶点均未被访问,则从某个顶点v出发,首先访问该顶点,然后依次从它的各个未被访问的邻接点出发深度优先搜索遍历图,直至图中所有和v有路径相通的顶点都被访问到。 若此时尚有其他顶点未被访问到,则另选一个未被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。 +显然,深度优先搜索是一个递归的过程。 + +**1. 无向图的深度优先搜索** + + + +对上面的图进行深度优先遍历,从顶点A开始。 + +``` +第1步:访问A。 +第2步:访问(A的邻接点)C。 + 在第1步访问A之后,接下来应该访问的是A的邻接点,即"C,D,F"中的一个。但在本文的实现中,顶点ABCDEFG是按照顺序存储,C在"D和F"的前面,因此,先访问C。 +第3步:访问(C的邻接点)B。 + 在第2步访问C之后,接下来应该访问C的邻接点,即"B和D"中一个(A已经被访问过,就不算在内)。而由于B在D之前,先访问B。 +第4步:访问(C的邻接点)D。 + 在第3步访问了C的邻接点B之后,B没有未被访问的邻接点;因此,返回到访问C的另一个邻接点D。 +第5步:访问(A的邻接点)F。 + 前面已经访问了A,并且访问完了"A的邻接点B的所有邻接点(包括递归的邻接点在内)";因此,此时返回到访问A的另一个邻接点F。 +第6步:访问(F的邻接点)G。 +第7步:访问(G的邻接点)E。 + +因此访问顺序是:A -> C -> B -> D -> F -> G -> E +``` + +**2. 有向图的深度优先搜索** + + +对上面的图进行深度优先遍历,从顶点A开始。 + +``` +第1步:访问A。 +第2步:访问B。 + 在访问了A之后,接下来应该访问的是A的出边的另一个顶点,即顶点B。 +第3步:访问C。 + 在访问了B之后,接下来应该访问的是B的出边的另一个顶点,即顶点C,E,F。在本文实现的图中,顶点ABCDEFG按照顺序存储,因此先访问C。 +第4步:访问E。 + 接下来访问C的出边的另一个顶点,即顶点E。 +第5步:访问D。 + 接下来访问E的出边的另一个顶点,即顶点B,D。顶点B已经被访问过,因此访问顶点D。 +第6步:访问F。 + 接下应该回溯"访问A的出边的另一个顶点F"。 +第7步:访问G。 + +因此访问顺序是:A -> B -> C -> E -> D -> F -> G +``` + +### 示例1. 城堡问题 + +**问题描述:** + +``` + 1 2 3 4 5 6 7 + ############################# + 1 # | # | # | | # + #####---#####---#---#####---# + 2 # # | # # # # # + #---#####---#####---#####---# + 3 # | | # # # # # + #---#########---#####---#---# + 4 # # | | | | # # + ############################# + (图 1) + + # = Wall + | = No wall + - = No wall + +图1是一个城堡的地形图。请你编写一个程序,计算城堡一共有多少房间,最大的房间有多大。城堡被分割成mn(m≤50,n≤50)个方块,每个方块可以有0~4面墙。 +Input程序从标准输入设备读入数据。第一行是两个整数,分别是南北向、东西向的方块数。在接下来的输入行里,每个方块用一个数字(0≤p≤50)描述。用一个数字表示方块周围的墙,1表示西墙,2表示北墙,4表示东墙,8表示南墙。每个方块用代表其周围墙的数字之和表示。城堡的内墙被计算两次,方块(1,1)的南墙同时也是方块(2,1)的北墙。输入的数据保证城堡至少有两个房间。Output城堡的房间数、城堡中最大房间所包括的方块数。结果显示在标准输出设备上。 +Sample Input: +4 7 +11 6 11 6 3 10 6 +7 9 6 13 5 15 5 +1 10 12 7 13 7 5 +13 11 10 8 10 12 13 +Sample Output +5 +9 +``` + + + + + + +```python +rows, cols = map(int, input().split()) +rooms = [] +for i in range(rows): + rooms.append(list(map(int, input().split()))) + +# 同一房间有相同的color值 +color = [[0] * cols for _ in range(rows)] +roomNum = 0 # 房间数量 +maxRoomArea = 0 # 房间的方块数 + +def DFS(i,j): + global roomNum + global roomArea + if color[i][j]!=0: + return + roomArea += 1 + color[i][j] = roomNum + # 向西走 + if rooms[i][j] & 1 == 0: + DFS(i, j - 1) + # 向北走 + if rooms[i][j] & 2 == 0: + DFS(i - 1, j) + # 向东走 + if rooms[i][j] & 4 == 0: + DFS(i, j + 1) + # 向南走 + if rooms[i][j] & 8 == 0: + DFS(i + 1, j) + +for i in range(rows): + for j in range(cols): + if color[i][j] == 0: + roomNum += 1 + roomArea = 0 + DFS(i,j) + maxRoomArea = max(roomArea,maxRoomArea) +print('房间数量:',roomNum) +print('最大房间的方块数:',maxRoomArea) +print(color) + +#output +房间数量: 5 +最大房间的方块数: 9 +[[1, 1, 2, 2, 3, 3, 3], [1, 1, 1, 2, 3, 4, 3], [1, 1, 1, 5, 3, 5, 3], [1, 5, 5, 5, 5, 5, 3]] +``` + diff --git "a/robot/Search/Dijkstra\347\256\227\346\263\225\345\222\214Floyd\347\256\227\346\263\225-A-star\347\256\227\346\263\225.md" "b/robot/Search/Dijkstra\347\256\227\346\263\225\345\222\214Floyd\347\256\227\346\263\225-A-star\347\256\227\346\263\225.md" new file mode 100644 index 00000000..693b76ef --- /dev/null +++ "b/robot/Search/Dijkstra\347\256\227\346\263\225\345\222\214Floyd\347\256\227\346\263\225-A-star\347\256\227\346\263\225.md" @@ -0,0 +1,494 @@ +Dijkstra算法\Floyd算法\A*算法 +====================== + +# 一. 最短路径问题介绍 + +> 从图中的某个顶点出发到达另外一个顶点的所经过的边的权重和最小的一条路径,称为最短路径。解决最短路径问题的算法有Dijkstra算法和Floyd算法。 + +# 二. Dijkstra算法 + +## (一) 基本思想 + +> Dijkstra算法(单源点路径算法,要求:图中不存在负权值边),Dijkstra算法使用了广度优先搜索解决赋权有向图或者无向图的单源最短路径问题,算法最终得到一个最短路径树。 Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低。 + +## (二)算法流程 + +> 1. 设置两个集合S和V。其中,S是已求出最短路径的顶点,V是没有求出最短路径的顶点,初始状态时,S中只有节点0———即起点,V中是节点1-n。设置最短路径数组dist[n+1],dist代表起点0到节点1-n的最短距离,初始状态时,dist[i]为起点0到节点i的距离,当起点0与节点i有边连接时,dist[i]=边的权值,当起点0与节点i没有边连接时,dist[i]=无穷大。 + +> 2. 从V中寻找与S(S中最后一个节点)距离最短的节点k,将其加入S中,同时,从V中移除k + +> 3. 以k为中间点,更新dist中各节点j的距离。如果: 起点0—>j(经过k)的距离 < 起点0—>j(不经过k)的距离即dist[j],则dist[j]= 0—>j(经过k)的距离 = 0->k的距离即dist[k] + k->j的距离( 的权值 ) + +> 重复步骤2和3,直到所有节点都在S中。 + +## (三) 图解过程 + +> 求从A到F的最短路径,设置集合S、V和dist,并初始化,如图1所示: + +![image](https://github.com/ShaoQiBNU/The-shortest-path/blob/master/images/1.png) + +> 遍历集合V中与A直接相邻的顶点,找出当前与A距离最短的顶点。发现: A-->B 6 A-->C 3,于是将C加入S,并将C从V中移除。以C为中间点,更新dist中各节点的距离如下: + +```python +节点 经过C的距离 不经过C的距离 dist + B 3+2=5 6 5 + C - - 3 + D 3+3=6 ∞ 6 + E 3+4=7 ∞ 7 + F ∞ ∞ ∞ +``` + +![image](https://github.com/ShaoQiBNU/The-shortest-path/blob/master/images/2.png) + +> 遍历集合V中与C直接相邻的顶点,找出当前与C距离最短的顶点。发现: C-->B 2 C-->D 3 C-->E 4,于是将B加入S,并将B从V中移除。以B为中间点,更新dist中各节点的距离如下: +```python +节点 经过B的距离 不经过B的距离 dist + B - - 5 + C - - 3 + D 6+5=11 6 6 + E ∞ 7 7 + F ∞ ∞ ∞ +``` + +![image](https://github.com/ShaoQiBNU/The-shortest-path/blob/master/images/3.png) + +> 遍历集合V中与B直接相邻的顶点,找出当前与B距离最短的顶点。发现: B-->D 5 ,于是将D加入S,并将D从V中移除。以D为中间点,更新dist中各节点的距离如下: +```python +节点 经过D的距离 不经过D的距离 dist + B - - 5 + C - - 3 + D - - 6 + E 6+2=8 7 7 + F 6+3=9 ∞ 9 +``` + +![image](https://github.com/ShaoQiBNU/The-shortest-path/blob/master/images/4.png) + + +> 遍历集合V中与D直接相邻的顶点,找出当前与D距离最短的顶点。发现: D-->E 2 D-->F 3,于是将E加入S,并将E从V中移除。以E为中间点,更新dist中各节点的距离如下: +```python +节点 经过E的距离 不经过E的距离 dist + B - - 5 + C - - 3 + D - - 6 + E - - 7 + F 7+5=12 9 9 +``` + +![image](https://github.com/ShaoQiBNU/The-shortest-path/blob/master/images/5.png) + +> 遍历集合V中与E直接相邻的顶点,找出当前与E距离最短的顶点。发现: E-->F 5,于是将F加入S,并将F从V中移除。以F为中间点,更新dist中各节点的距离如下: +```python +节点 经过E的距离 不经过E的距离 dist + B - - 5 + C - - 3 + D - - 6 + E - - 7 + F - - 9 +``` + +![image](https://github.com/ShaoQiBNU/The-shortest-path/blob/master/images/6.png) + +## (四) python实现(有向图) + +```python +def minDist(mdist, visit, V): + minVal = float('inf') + minInd = -1 + for i in range(V): + if (not visit[i]) and mdist[i] < minVal : + minInd = i + minVal = mdist[i] + return minInd + +def Dijkstra(graph, V, startP,endP): + # 初始化 mdist + mdist=[float('inf') for _ in range(V)] + # 被访问的点 + visit = [False for _ in range(V)] + mdist[startP-1] = 0.0 # 起始点设距离为0 + + # V个顶点需要做V-1次循环 + for i in range(V-1): + # 更新每次起点到下一点的位置 + u = minDist(mdist, visit, V) + visit[u] = True # 位置被访问 + # 循环遍历所以顶点 + for v in range(V): + if (not visit[v]) and graph[u][v]!=float('inf') and mdist[u] + graph[u][v] < mdist[v]: + # 更新mdist + mdist[v] = mdist[u] + graph[u][v] + + # 返回起始点到其他所有点的最近距离,到终点的距离 + return mdist,mdist[endP-1] + +if __name__ == '__main__': + V = int(input("Enter number of vertices: ")) + + graph = [[float('inf') for i in range(V)] for j in range(V)] + + for i in range(V): + graph[i][i] = 0.0 + + graph[0][1] = 6 + graph[0][2] = 3 + graph[1][2] = 2 + graph[1][3] = 5 + graph[2][3] = 3 + graph[2][4] = 4 + graph[3][4] = 2 + graph[3][5] = 3 + graph[4][5] = 5 + + startP = int(input("起点:")) + endP = int(input("终点:")) + print(Dijkstra(graph, V, startP,endP)) + + +#output: +Enter number of vertices: 6 +起点:1 +终点:5 +([0.0, 6.0, 3.0, 6.0, 7.0, 9.0], 7.0) +``` + + +# 三. Floyd算法 + +## (一) 算法原理 + +> Floyd算法是一个经典的**动态规划算法**。用通俗的语言来描述的话,首先我们的目标是寻找从点i到点j的最短路径。从动态规划的角度看问题,我们需要为这个目标重新做一个诠释(这个诠释正是动态规划最富创造力的精华所在),从任意节点i到任意节点j的最短路径不外乎2种可能,1是直接从i到j,2是从i经过若干个节点k到j。所以,我们假设Dis(i,j)为节点u到节点v的最短路径的距离,对于每一个节点k,我们检查Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立,如果成立,证明从i到k再到j的路径比i直接到j的路径短,我们便设置Dis(i,j) = Dis(i,k) + Dis(k,j),状态转移方程如下:map[i,j]=min{map[i,k]+map[k,j],map[i,j]},这样一来,当我们遍历完所有节点k,Dis(i,j)中记录的便是i到j的最短路径的距离。 + +## (二) 算法描述 + +> 设置矩阵map和path,map为邻接矩阵,path为路径矩阵,初始状态时,当i和j之间有边时,map[i][j]=权重,否则map[i][j]=∞;path矩阵初始状态为i和j可直达,path[i][j]=j。 + +> 对每一对顶点i和j,看看是否存在k,使得 map[i][k] + map[k][j] < map[i][j],如果有,则更新map[i][j];同时更新路径矩阵path[i][j]=path[i][k]。 + +## (三) 图解过程 + +> 初始化map和path,如图所示 + +![image](https://github.com/ShaoQiBNU/The-shortest-path/blob/master/images/7.png) + +> 以A为中间节点,更新map和path,此时没有更新项。以B为中间节点,更新map和path + +![image](https://github.com/ShaoQiBNU/The-shortest-path/blob/master/images/8.png) + +> 以C为中间节点,更新map和path + +![image](https://github.com/ShaoQiBNU/The-shortest-path/blob/master/images/9.png) + +> 以D为中间节点,更新map和path + +![image](https://github.com/ShaoQiBNU/The-shortest-path/blob/master/images/10.png) + +> 以E为中间节点,更新map和path,此时没有更新项。以F为中间节点,更新map和path,此时没有更新项。 + +![image](https://github.com/ShaoQiBNU/The-shortest-path/blob/master/images/11.png) + +## (四) python代码实现(无向图) + +```python +def floyd(arr,n,startP,endP): + # 中间节点k + for k in range(n): + # 起点i + for i in range(n): + # 终点j + for j in range(n): + # 更新距离 + if arr[i][j]>(arr[i][k]+arr[k][j]) and i !=j: + arr[i][j] = arr[i][k] + arr[k][j] + #path[i][j] = j + return arr[startP-1][endP-1],arr + +if __name__ == '__main__': + n = 6 + arr = [[float('inf')] * n for _ in range(n)] + arr[0][1] = 6 + arr[0][2] = 3 + arr[1][2] = 2 + arr[1][3] = 5 + arr[2][3] = 3 + arr[2][4] = 4 + arr[3][4] = 2 + arr[3][5] = 3 + arr[4][5] = 5 + + for i in range(n): + arr[i][i] = 0.0 + for j in range(n): + if arr[i][j] != 'inf': + arr[j][i] = arr[i][j] + print(floyd(arr,n,3,3)) + +#output +(9, +[[0.0, 5, 3, 6, 7, 9], + [5, 0.0, 2, 5, 6, 8], + [3, 2, 0.0, 3, 4, 6], + [6, 5, 3, 0.0, 2, 3], + [7, 6, 4, 2, 0.0, 5], + [9, 8, 6, 3, 5, 0.0]]) + +``` + +# 四. A*算法(A star 算法) + +https://www.cnblogs.com/zhoug2020/p/3468167.html + +http://www.cppblog.com/mythit/archive/2009/04/19/80492.aspx + + +```python +# -*- coding: utf-8 -*- +import math + +# 地图 +tm = ['##########', + '#........#', + '#S...#...#', + '#....#...#', + '#..###....', + '####...E..', + '..........'] + +# 因为python里string不能直接改变某一元素,所以用test_map来存储搜索时的地图 +test_map = [] + + +######################################################### +class Node_Elem: + """ + 开放列表和关闭列表的元素类型,parent用来在成功的时候回溯路径 + """ + + def __init__(self, parent, x, y, dist): + self.parent = parent + self.x = x + self.y = y + self.dist = dist + + +class A_Star: + """ + A星算法实现类 + """ + + # 注意w,h两个参数,如果你修改了地图,需要传入一个正确值或者修改这里的默认参数 + def __init__(self, s_x, s_y, e_x, e_y, w=10, h=7): + # 开始点坐标(s_x,s_y) + self.s_x = s_x + self.s_y = s_y + # 结束点坐标(e_x,e_y) + self.e_x = e_x + self.e_y = e_y + + self.width = w # 矩阵宽度 + self.height = h # 矩阵高度 + + self.open = [] + self.close = [] + self.path = [] + + # 查找路径的入口函数 + def find_path(self): + # 构建开始节点 + p = Node_Elem(None, self.s_x, self.s_y, 0.0) + while True: + # 扩展F值最小的节点 + self.extend_round(p) + # 如果开放列表为空,则不存在路径,返回 + if not self.open: + return + # 获取F值最小的节点 + idx, p = self.get_best() + # 找到路径,生成路径,返回 + if self.is_target(p): + self.make_path(p) + return + # 把此节点压入关闭列表,并从开放列表里删除 + self.close.append(p) + del self.open[idx] + + def make_path(self, p): + # 从结束点回溯到开始点,开始点的parent == None + while p: + self.path.append((p.x, p.y)) + p = p.parent + + def is_target(self, i): + return i.x == self.e_x and i.y == self.e_y + + def get_best(self): + best = None + bv = 1000000 # 如果你修改的地图很大,可能需要修改这个值 + bi = -1 + for idx, i in enumerate(self.open): + value = self.get_dist(i) # 获取F值 + if value < bv: # 比以前的更好,即F值更小 + best = i + bv = value + bi = idx + return bi, best + + def get_dist(self, i): + # F = G + H + # G 为已经走过的路径长度, H为估计还要走多远 + # 这个公式就是A*算法的精华了。 + return i.dist + math.sqrt( + (self.e_x - i.x) ** 2 + + (self.e_y - i.y) ** 2) * 1.2 + + def extend_round(self, p): + # 可以从8个方向走 + # xs = (-1, 0, 1, -1, 1, -1, 0, 1) + # ys = (-1, -1, -1, 0, 0, 1, 1, 1) + # 只能走上下左右四个方向 + xs = (0, -1, 1, 0) + ys = (-1, 0, 0, 1) + for x, y in zip(xs, ys): + new_x, new_y = x + p.x, y + p.y + # 无效或者不可行走区域,则勿略 + if not self.is_valid_coord(new_x, new_y): + continue + # 构造新的节点 + node = Node_Elem(p, new_x, new_y, p.dist + self.get_cost( + p.x, p.y, new_x, new_y)) + # 新节点在关闭列表,则忽略 + if self.node_in_close(node): + continue + i = self.node_in_open(node) + if i != -1: + # 新节点在开放列表 + if self.open[i].dist > node.dist: + # 现在的路径到比以前到这个节点的路径更好~ + # 则使用现在的路径 + self.open[i].parent = p + self.open[i].dist = node.dist + continue + self.open.append(node) + + def get_cost(self, x1, y1, x2, y2): + """ + 上下左右直走,代价为1.0,斜走,代价为1.4 + """ + if x1 == x2 or y1 == y2: + return 1.0 + return 1.4 + + def node_in_close(self, node): + for i in self.close: + if node.x == i.x and node.y == i.y: + return True + return False + + def node_in_open(self, node): + for i, n in enumerate(self.open): + if node.x == n.x and node.y == n.y: + return i + return -1 + + def is_valid_coord(self, x, y): + if x < 0 or x >= self.width or y < 0 or y >= self.height: + return False + return test_map[y][x] != '#' + + def get_searched(self): + l = [] + for i in self.open: + l.append((i.x, i.y)) + for i in self.close: + l.append((i.x, i.y)) + return l + + +######################################################### +def print_test_map(): + """ + 打印搜索后的地图 + """ + for line in test_map: + print(''.join(line)) + + +def get_start_XY(): + return get_symbol_XY('S') + + +def get_end_XY(): + return get_symbol_XY('E') + + +def get_symbol_XY(s): + for y, line in enumerate(test_map): + try: + x = line.index(s) + except: + continue + else: + break + return x, y + + +######################################################### +def mark_path(l): + mark_symbol(l, '*') + + +def mark_searched(l): + mark_symbol(l, ' ') + + +def mark_symbol(l, s): + for x, y in l: + test_map[y][x] = s + + +def mark_start_end(s_x, s_y, e_x, e_y): + test_map[s_y][s_x] = 'S' + test_map[e_y][e_x] = 'E' + + +def tm_to_test_map(): + for line in tm: + test_map.append(list(line)) + + +def find_path(): + s_x, s_y = get_start_XY() + e_x, e_y = get_end_XY() + a_star = A_Star(s_x, s_y, e_x, e_y) + a_star.find_path() + searched = a_star.get_searched() + path = a_star.path + # 标记已搜索区域 + mark_searched(searched) + # 标记路径 + mark_path(path) + print("path length is %d" % (len(path))) + print("searched squares count is %d" % (len(searched))) + # 标记开始、结束点 + mark_start_end(s_x, s_y, e_x, e_y) + + +if __name__ == "__main__": + # 把字符串转成列表 + tm_to_test_map() + find_path() + print_test_map() + + +#output: +path length is 12 +searched squares count is 26 +########## +# *** .# +#S***#* .# +# #* .# +# ###** . +####.. E.. +.......... + +``` diff --git a/robot/Search/VLN/readme.md b/robot/Search/VLN/readme.md new file mode 100644 index 00000000..f5e9264b --- /dev/null +++ b/robot/Search/VLN/readme.md @@ -0,0 +1,31 @@ +# 视觉语言导航 vision-language navigation + +视觉语言导航(vision-language navigation, VLN)任务指的是引导智能体或机器人在真实三维场景中能理解自然语言命令并准确执行。结合下面这张图再形象、通俗一点解释:假如智能体接收到“向右转,径直走向厨房,然后左转,经过一张桌子后进入走廊...”等一系列语言命令,它需要分析指令中的物体和动作指令,在只能看到一部分场景内容的情况下,脑补整个全局图,并正确执行命令。所以这是一个结合 NLP 和 CV 两大领域,一项非常有挑战性的任务。 + + +# 难点 + +虽然我们理解这项任务好像不是很难,但是放到 AI 智能体上并不像我们理解起来那么容易。对 AI 智能体来说,这项任务通常存在三大难点: + +难点一:跨模态的基标对准(cross-modal grounding);简单解释就是将NLP 的指令与 CV 场景相对应。 + +难点二:不适定反馈(ill-posed feedback);就是通常一句话里面包含多个指令,但并不是每个指令都会进行反馈,只有最终完成任务才有反馈,所以难以判断智能体是否完全按照指令完成任务。 + +难点三:泛化能力问题;由于环境差异大,VLN 的模型难以泛化。 + +[Reinforced Cross-Modal Matching and Self-Supervised Imitation Learning +for Vision-Language Navigation +](https://arxiv.org/pdf/1811.10092.pdf) + +## 1、RCM(Reinforced Cross-Modal Matching)强化型跨模态匹配模型 + 用强化学习方法将局部和全局的场景联系起来。 + RCM 模型主要由两个模块构成:推理导航器和匹配度评估器。 + + 如图所示,通过训练其中绿色的导航器,让它学会理解局部的跨模态场景,推断潜在的指令,并生成一系列动作序列。 + 另外,论文还设置了匹配度评估器(Matching Critic)和循环重建奖励机制, + 用于评价原始指令与导航器生成的轨迹之间的对齐情况,帮助智能体理解语言输入,并且惩罚不符合语言指令的轨迹。 + +## 2、SIL(Self-supervised Imitation Learning)自监督模仿学习 方法 + +其目的是让智能体能够自主的探索未知的环境。其具体做法是,对于一个从未见过的语言指令和目标位置,导航器会得到一组可能的轨迹并将其中最优的轨迹(采用匹配度评估器)保存到缓冲区中,然后匹配度评估器会使用之前介绍的循环重建奖励机制来评估轨迹,SIL方法可以与多种学习方法想结合,通过模仿自己之前的最佳表现来得到更优的策略。 + diff --git a/robot/Search/readme.md b/robot/Search/readme.md index acee9f23..cb7a5a37 100644 --- a/robot/Search/readme.md +++ b/robot/Search/readme.md @@ -1,6 +1,86 @@ -# 路径规划 +# 规划 motion planning trajectory planning ![](https://images2015.cnblogs.com/blog/710098/201604/710098-20160417134850410-1505250729.png) + 机器人技术的一个基本需求是拥有将人类任务的 高级规范 转换 为 如何移动 的 低级描述的算法。 + + 运动规划 和 轨迹规划 + + 机器人运动规划通常忽略动力学和其他差异约束,主要关注 移动目标 所需的平移和旋转。 + 然而,最近的工作确实考虑了其他方面,例如不确定性,差异约束,建模误差和最优性。 + + 轨迹规划通常指的是从机器人运动规划算法中获取解决方案并确定如何以尊重机器人的机械限制的方式移动解决方案的问题。 + + A. 运动规划 motion planning + 在连续状态空间中进行规划”Planning in Continuous State Spaces + + 1. 几何表示和转换 Geometric Representations and Transformations + 给出了表达运动规划问题的重要背景。 + 如何构建几何模型,其余部分说明了如何转换它们。 + + 2. 配置空间 Configuration Space + 介绍拓扑中的概念,并使用它们来表示配置空间,即运动规划中出现的状态空间。 + + 3.基于采样的运动规划Sampling-Based Motion Planning + 近年来在文献中占主导地位的运动规划算法,并已应用于机器人内外的领域。 + 如果您了解配置空间代表连续状态空间的基本思想,那么大多数概念都应该是可以理解的。 + 除了运动规划和机器人技术之外,它们甚至适用于出现连续状态空间的其他问题。 + + 4. 组合运动规划Combinatorial Motion Planning + 有时称为精确算法,因为它们构建离散表示而不会丢失任何信息。 + 它们是完整的,这意味着如果存在,它们必须找到解决方案;否则,它们会报告失败。 + 基于抽样的算法在实践中更有用,但它们只能实现较弱的完整性概念。 + + 5. 基本运动规划的扩展 Extensions of Basic Motion Planning + 封闭运动链的规划; + + 6. 反馈运动规划 Feedback Motion Planning + 一个过渡性章节,将 反馈 引入 运动规划问题,但仍未引入 差异约束 + 侧重于计算开环规划,这意味着规划执行期间可能发生的任何错误都会被忽略 + 使用反馈产生闭环规划,该规划在执行期间响应不可预测的事件。 + + B.决策理论规划Decision-Theoretic Planning + 在不确定性下进行规划Planning Under Uncertainty。 + 大部分涉及离散状态空间discrete state spaces, + 但是,有些部分涵盖了连续空间的扩展; + 1. 基本决策理论Basic Decision Theory + 主要思想是为面临其他决策者干预的决策者设计最佳决策。 + 其他人可能是游戏中真正的对手,也可能是虚构的,以模拟不确定性model uncertainties. + 侧重于一步做出决定,并为第三部分提供构建模块,因为在不确定性下的计划可被视为多步决策 multi-step decision making。 + + 2. 顺序决策理论Sequential Decision Theory + 通过将一系列基本决策问题链接在一起来扩展它们。 + 动态编程Dynamic programming 概念在这里变得很重要。 + 假设当前状态始终是已知的。存在的所有不确定性都与预测未来状态有关,而不是测量当前状态。 + + 3. 传感器和信息空间Sensors and Information Spaces + 一个框架,用于在执行期间当前状态未知时进行规划。 + 关于状态的信息是从传感器观察 和 先前应用的动作的记忆中获得的。 + 信息空间服务类似检测不确定性问题的目的,因为配置空间具有运动规划。 + + 4. 感知不确定性下的规划Planning Under Sensing Uncertainty + 介绍了涉及感知不确定性的几个规划问题和算法。 + 这包括定位localization,地图构建 map building,pursuit-evasion跟踪? 和 操作 等问题。 + 所有这些问题都是在信息空间规划的思想下统一起来的. + + C. 差异约束下的规划Planning Under Differential Constraints + 这里,在运动规划中出现的连续状态空间上可能存在全局(障碍)和局部(差分)约束。 + 还考虑动态系统,其产生包括位置和速度信息的状态空间(这与控制理论中的状态空间或物理和微分方程中的相空间的概念一致)。 + 1. 差分模型Differential Models + 介绍涉及差异约束的众多模型, + 包括车轮滚动产生的约束 以及 机械系统 动力学 产生的约束。 + + 2. 差分约束下的基于抽样的规划 Sampling-Based Planning Under Differential Constraints + 所有方法都是基于采样的,因为在差分约束的情况下,组合技术很少能实现。 + + 3. 系统理论和分析技术System Theory and Analytical Techniques + 概述了主要在控制理论文献中开发的概念和工具, + 通常在差分约束下开发规划算法时提供重要的见解或组成部分。 + + + + + + [Moving AI Lab](https://movingai.com/) [A* and D* c++代码](https://github.com/Ewenwan/Path-Planning) diff --git a/robot/Speech/readme.md b/robot/Speech/readme.md new file mode 100644 index 00000000..b13fc192 --- /dev/null +++ b/robot/Speech/readme.md @@ -0,0 +1,3 @@ +# 语音 语言 说话 理解 + +[Speech Automatic Speech Recognition,(ASR) 语言识别](https://github.com/Ewenwan/MVision/tree/master/Speech) diff --git a/robot/Vision/readme.md b/robot/Vision/readme.md index a847322a..2b08b410 100644 --- a/robot/Vision/readme.md +++ b/robot/Vision/readme.md @@ -15,4 +15,4 @@ [机器人学 —— 机器人视觉(Bundle Adjustment) 机器人视觉学中,最顶尖的方法 基于非线性优化的相机位姿估计 雅克比矩阵 ](https://www.cnblogs.com/ironstark/p/5493030.html) -[]() +[OCR字符识别 ](https://github.com/Ewenwan/MVision/tree/master/CNN/CTC) diff --git a/robot/pdf/AutomatedPlanningandActing.pdf b/robot/pdf/AutomatedPlanningandActing.pdf new file mode 100644 index 00000000..b10df33c Binary files /dev/null and b/robot/pdf/AutomatedPlanningandActing.pdf differ diff --git "a/robot/pdf/\350\267\257\345\276\204\350\247\204\345\210\222PP.pdf" "b/robot/pdf/\350\267\257\345\276\204\350\247\204\345\210\222PP.pdf" new file mode 100644 index 00000000..30dfac83 Binary files /dev/null and "b/robot/pdf/\350\267\257\345\276\204\350\247\204\345\210\222PP.pdf" differ diff --git a/robot/readme.md b/robot/readme.md index 0752be98..d5efb0b2 100644 --- a/robot/readme.md +++ b/robot/readme.md @@ -1,14 +1,51 @@ # 机器人 +[第十四届全国大学生智能汽车竞赛室外光电竞速创意赛,ART-Racecar ros 激光雷达+IMU建图导航](https://github.com/Ewenwan/racecar) + +[移动机器人 VREP下仿真 ros控制](https://github.com/Ewenwan/Virtual-Robot-Challenge) [机器人环境软件安装脚本 ceres tensorflow ros caffe vrep eigen cudnn and cuda ](https://github.com/Ewenwan/robotics_setup) +[webots 便携式机器人仿真平台](https://github.com/Ewenwan/webots) + +[V-Rep、Open HRP、Gazebo、Webots这四种机器人仿真软件各自有何特点和优缺点?](https://www.zhihu.com/question/41611869/answer/124462692) + + Webots 貌似没有V-REP易用度高(仅仅是第一感觉),但是功能上应该至少跟V-REP相当甚至更强, + 感觉上Webots跟仿真交互的编程方式更紧密和灵活。 + 开源免费之后的Webots在License上比V-REP更宽松. + + Gazebo相比前两者还是差了些. + OpenHRP主要是做humanoid仿真的. + Gazebo在学习ROS的时候可能会用到,比如跑一跑Turtlebo的仿真,对于学习还是很有帮助的。 + VREP对用户友好很多,文档齐全,EDU版本也没有功能限制,还是跨平台的,所以初学者容易上手很多。 + # 以优达学城 机器人人工智能课程为起点 逐渐丰富内容 +[ probabilistic robotics 概率机器人编程练习题 matlab](https://github.com/Ewenwan/probabilistic_robotics) + +[ros下 基于激光雷达的 移动机器人小车 代码](https://github.com/Ewenwan/ddl_0725) + +[ros下 基于激光雷达的 动态环境下的 导航 路径规划 避障](https://github.com/Ewenwan/dynamic_robot_localization) + +[路径跟踪 c++实现 ](https://github.com/Ewenwan/pathtracer) ## 其他参考课程 [CSE 571: Robotics](https://courses.cs.washington.edu/courses/cse571/16au/) +[汉堡大学 移动机器人 Introduction to Mobile Robotics + Kinematics + Sensors + Vehicle localization + Map building + SLAM + Path planning + Exploration of unknown terrain + ](http://ais.informatik.uni-freiburg.de/teaching/ss17/robotics/) + +[弗莱堡课程Robot Mapping - WS 2013/14](http://ais.informatik.uni-freiburg.de/teaching/ws13/mapping/) + +[ Occupancy Grid Mapping 占用栅格地图构建算法实现《概率机器人》第9章](https://github.com/Ewenwan/occ_grid_mapping) + [CSE598C Vision-Based Tracking 课程 滤波+跟踪 ](http://101.96.10.63/www.cse.psu.edu/~rtc12/CSE598C/) [粒子滤波 A Tutorial on Particle Filters for Online Nonlinear/Non-Gaussian Bayesian Tracking](http://101.96.10.63/www.cse.psu.edu/~rtc12/CSE598C/arulampalamTutorialPF.pdf) @@ -20,32 +57,51 @@ [树莓派+Arduino+TensorFlow:搭建图像识别小车](https://github.com/Ewenwan/rpi) + + +[高程制图-粗糙地形导航 ](https://github.com/Ewenwan/elevation_mapping) + +[网格地图——移动机器人地图的通用栅格地图库 ](https://github.com/Ewenwan/grid_map) + +[自由步态——腿式机器人多功能控制的体系结构 ](https://github.com/Ewenwan/free_gait) + +[机器人运动学与动力学](https://github.com/Ewenwan/kindr) + +[ROS wrappers for kindr 定制的ros系统](https://github.com/Ewenwan/kindr_ros) + +[粗糙地形导航的建图 移动 估计](https://github.com/Ewenwan/traversability_estimation) + +[一种高度移动和动态的四足机器人 ](https://www.research-collection.ethz.ch/bitstream/handle/20.500.11850/118642/eth-49454-01.pdf?sequence=1) + +[]() + # Robotics 须知  相关参考 Relevant Awesome Lists ---------------------- - [ahundt/awesome-robotics](https://github.com/ahundt/awesome-robotics) -- [Kiloreaux/awesome-robotics](https://github.com/Kiloreux/awesome-robotics) - Learn about Robotics. -- [Robotics Libraries 库](https://github.com/jslee02/awesome-robotics-libraries) - Another list of awesome robotics libraries. -- [Computer Vision 计算机视觉](https://github.com/jbhuang0604/awesome-computer-vision) + +- [Kiloreaux/awesome-robotics 收集了大量机器人入门的资料,包含课程、电子书、软件、期刊、行业竞赛和开源库等等](https://github.com/Kiloreux/awesome-robotics) - Learn about Robotics. +- [Robotics Libraries 列举了大量非常棒的机器人开源库和软件,并标出了开源库的受欢迎程。](https://github.com/jslee02/awesome-robotics-libraries) - Another list of awesome robotics libraries. +- [Computer Vision 计算机视觉相关的课程、电子书、论文、软件、数据库、教程、资源以及博客等。](https://github.com/jbhuang0604/awesome-computer-vision) - [Deep Learning 深度学习](https://github.com/ChristosChristofidis/awesome-deep-learning) - Neural networks. - - [TensorFlow](https://github.com/jtoy/awesome-tensorflow) - Library for machine intelligence. - - [Papers](https://github.com/terryum/awesome-deep-learning-papers) - The most cited deep learning papers. + - [TensorFlow 教程、模型、库、视频、论文、博客](https://github.com/jtoy/awesome-tensorflow) - Library for machine intelligence. + - [Papers引用次数最多的深度学习论文](https://github.com/terryum/awesome-deep-learning-papers) - The most cited deep learning papers. - [Deep Vision 深度学习计算机视觉](https://github.com/kjw0612/awesome-deep-vision) - Deep learning for computer vision - [Data Visualization 数据可视化](https://github.com/fasouto/awesome-dataviz) - See what your robot is doing with any programming language. -Simulators 仿真器 +Simulators 仿真器 模拟器 ---------- - [V-REP](coppeliarobotics.com/index.html) - Create, Simulate, any Robot. -- [Microsoft Airsim](https://github.com/Microsoft/AirSim) - Open source simulator based on Unreal Engine for autonomous vehicles from Microsoft AI & Research. -- [Bullet Physics SDK](https://github.com/bulletphysics/bullet3) - Real-time collision detection and multi-physics simulation for VR, games, visual effects, robotics, machine learning etc. Also see [pybullet](https://pybullet.org). +- [Microsoft Airsim 微软开源的一款基于虚幻引擎的模拟器,用于促进自动驾驶技术的研究,为无人驾驶提供真实的模拟环境、动力等等](https://github.com/Microsoft/AirSim) - Open source simulator based on Unreal Engine for autonomous vehicles from Microsoft AI & Research. +- [Bullet Physics SDK 实时碰撞检测和多物理环境模拟,用于虚拟现实的多物理场模拟、适用于VR、游戏、视觉效果、机器人技术、机器学习等 ](https://github.com/bulletphysics/bullet3) - Real-time collision detection and multi-physics simulation for VR, games, visual effects, robotics, machine learning etc. Also see [pybullet](https://pybullet.org). 可视化Visualization, Video, Display, and Rendering ----------------------- - - [Pangolin 可视化](https://github.com/stevenlovegrove/Pangolin) - A lightweight portable rapid development library for managing OpenGL display / interaction and abstracting video input. + - [Pangolin 可视化,一种轻量级的便携式快速开发库,用于管理OpenGL显示/交互和提取视频输入](https://github.com/stevenlovegrove/Pangolin) - A lightweight portable rapid development library for managing OpenGL display / interaction and abstracting video input. - [PlotJuggler](https://github.com/facontidavide/PlotJuggler) - Quickly plot and re-plot data on the fly! Includes optional ROS integration. - [Data Visualization](https://github.com/fasouto/awesome-dataviz) - A list of awesome data visualization tools. @@ -54,37 +110,37 @@ Simulators 仿真器 ### TensorFlow related -- [Keras](keras.io) - Deep Learning library for Python. Convnets, recurrent neural networks, and more. Runs on TensorFlow or Theano. -- [keras-contrib](https://github.com/farizrahman4u/keras-contrib) - Keras community contributions. +- [Keras 深度学习库,包含卷积神经网络,循环神经网络等,使用TensorFlow或者Theano框架。](keras.io) - Deep Learning library for Python. Convnets, recurrent neural networks, and more. Runs on TensorFlow or Theano. +- [keras-contrib 社区贡献](https://github.com/farizrahman4u/keras-contrib) - Keras community contributions. - [TensorFlow](tensorflow.org) - An open-source software library for Machine Intelligence. -- [recurrentshop](https://github.com/datalogai/recurrentshop) - Framework for building complex recurrent neural networks with Keras. -- [tensorpack](https://github.com/ppwwyyxx/tensorpack) - Neural Network Toolbox on TensorFlow. -- [tensorlayer](https://github.com/zsdonghao/tensorlayer) - Deep Learning and Reinforcement Learning Library for Researchers and Engineers. -- [TensorFlow-Examples](https://github.com/aymericdamien/TensorFlow-Examples) - TensorFlow Tutorial and Examples for beginners. -- [hyperas](https://github.com/maxpumperla/hyperas) - Keras + Hyperopt: A very simple wrapper for convenient hyperparameter optimization. -- [elephas](https://github.com/maxpumperla/elephas) - Distributed Deep learning with Keras & Spark -- [PipelineAI](https://github.com/fluxcapacitor/pipeline) - End-to-End ML and AI Platform for Real-time Spark and Tensorflow Data Pipelines. -- [sonnet](https://github.com/deepmind/sonnet) - Google Deepmind APIs on top of TensorFlow. +- [recurrentshop 使用Keras构建复杂循环神经网络的框架](https://github.com/datalogai/recurrentshop) - Framework for building complex recurrent neural networks with Keras. +- [tensorpack 基于TensorFlow的神经网络工具箱](https://github.com/ppwwyyxx/tensorpack) - Neural Network Toolbox on TensorFlow. +- [tensorlayer 适用于研究人员和工程师的深度学习与增强学习库 ](https://github.com/zsdonghao/tensorlayer) - Deep Learning and Reinforcement Learning Library for Researchers and Engineers. +- [TensorFlow-Examples 为初学者提供的TensorFlow手册与实例 ](https://github.com/aymericdamien/TensorFlow-Examples) - TensorFlow Tutorial and Examples for beginners. +- [hyperas 方便超参数优化,封装简单](https://github.com/maxpumperla/hyperas) - Keras + Hyperopt: A very simple wrapper for convenient hyperparameter optimization. +- [elephas 使用Keras & Spark进行分布式深度学习 ](https://github.com/maxpumperla/elephas) - Distributed Deep learning with Keras & Spark +- [PipelineAI 端到端机器学习与人工智能平台,实时的Spark与Tensorflow数据通道 ](https://github.com/fluxcapacitor/pipeline) - End-to-End ML and AI Platform for Real-time Spark and Tensorflow Data Pipelines. +- [sonnet 基于TensorFlow的Google Deepmind 应用程序接口,用以构建复杂的神经网络。 ](https://github.com/deepmind/sonnet) - Google Deepmind APIs on top of TensorFlow. - [visipedia/tfrecords](https://github.com/visipedia/tfrecords) - Demonstrates the use of TensorFlow's TFRecord data format. #### 图像分割 Image Segmentation -- [tf-image-segmentation](https://github.com/warmspringwinds/tf-image-segmentation) - Image Segmentation framework based on Tensorflow and TF-Slim library. +- [tf-image-segmentation 基于Tensorflow 和TF-Slim 库的图像分割框架](https://github.com/warmspringwinds/tf-image-segmentation) - Image Segmentation framework based on Tensorflow and TF-Slim library. - [Keras-FCN](https://github.com/aurora95/Keras-FCN) 日志和消息 Logging and Messaging --------------------- -- [spdlog](https://github.com/gabime/spdlog) - Super fast C++ logging library. -- [lcm](https://github.com/lcm-proj/lcm) - Lightweight Communications and Marshalling, message passing and data marshalling for real-time systems where high-bandwidth and low latency are critical. +- [spdlog 超快的C++日志库](https://github.com/gabime/spdlog) - Super fast C++ logging library. +- [lcm 用于高带宽和低延迟的实时系统,实现轻量级通信和编组、消息传递和数据编组](https://github.com/lcm-proj/lcm) - Lightweight Communications and Marshalling, message passing and data marshalling for real-time systems where high-bandwidth and low latency are critical. 跟踪 Tracking -------- -- [simtrack](https://github.com/karlpauwels/simtrack) - A simulation-based framework for tracking. -- [ar_track_alvar](https://github.com/sniekum/ar_track_alvar) - AR tag tracking library for ROS. -- [artoolkit5](https://github.com/artoolkit/artoolkit5) - Augmented Reality Toolkit, which has excellent AR tag tracking software. +- [simtrack 一种基于仿真的跟踪框架](https://github.com/karlpauwels/simtrack) - A simulation-based framework for tracking. +- [ar_track_alvar 用于ROS的AR标记跟踪库](https://github.com/sniekum/ar_track_alvar) - AR tag tracking library for ROS. +- [artoolkit5 增强现实工具包,具有优秀的AR标签跟踪软件](https://github.com/artoolkit/artoolkit5) - Augmented Reality Toolkit, which has excellent AR tag tracking software. 机器人操作系统 Robot Operating System (ROS) ---------------------------- @@ -96,73 +152,76 @@ Simulators 仿真器 正逆运动学 动力学 带约束最优化 Kinematics, Dynamics, Constrained Optimization ---------------------------------------------- -- [jrl-umi3218/Tasks](https://github.com/jrl-umi3218/Tasks) - Tasks is library for real time control of robots and kinematic trees using constrained optimization. -- [jrl-umi3218/RBDyn](https://github.com/jrl-umi3218/RBDyn) - RBDyn provides a set of classes and functions to model the dynamics of rigid body systems. -- [ceres-solver](https://github.com/ceres-solver/ceres-solver) - Solve Non-linear Least Squares problems with bounds constraints and general unconstrained optimization problems. Used in production at Google since 2010. -- [orocos_kinematics_dynamics](https://github.com/orocos/orocos_kinematics_dynamics) - Orocos Kinematics and Dynamics C++ library. -- [flexible-collsion-library](https://github.com/flexible-collision-library/fcl) - Performs three types of proximity queries on a pair of geometric models composed of triangles, integrated with ROS. -- [robot_calibration](https://github.com/mikeferguson/robot_calibration) - generic robot kinematics calibration for ROS - +- [jrl-umi3218/Tasks 使用了约束优化的机器人实时控制与运动学 库](https://github.com/jrl-umi3218/Tasks) - Tasks is library for real time control of robots and kinematic trees using constrained optimization. +- [jrl-umi3218/RBDyn 提供一组用于刚体系统动力学建模的类和函数](https://github.com/jrl-umi3218/RBDyn) - RBDyn provides a set of classes and functions to model the dynamics of rigid body systems. +- [ceres-solver 求解有界约束和一般无约束优化问题的非线性最小二乘问题 ](https://github.com/ceres-solver/ceres-solver) - Solve Non-linear Least Squares problems with bounds constraints and general unconstrained optimization problems. Used in production at Google since 2010. +- [orocos_kinematics_dynamics Orocos运动学和动力学的C++库 ](https://github.com/orocos/orocos_kinematics_dynamics) - Orocos Kinematics and Dynamics C++ library. +- [flexible-collsion-library 在一对由三角形组成的几何模型执行三类临近查找,集成在ROS中](https://github.com/flexible-collision-library/fcl) - Performs three types of proximity queries on a pair of geometric models composed of triangles, integrated with ROS. +- [robot_calibration 用于ROS的通用机器人运动学标定](https://github.com/mikeferguson/robot_calibration) - generic robot kinematics calibration for ROS +- [Kindr - Kinematics and Dynamics for Robotics 运动学和动力学](https://github.com/ethz-asl/kindr) - [Kindr ROS](https://github.com/ethz-asl/kindr_ros) 校准 Calibration ----------- -- [handeye-calib-camodocal](https://github.com/jhu-lcsr/handeye_calib_camodocal) - generic robot hand-eye calibration. -- [robot_calibration](https://github.com/mikeferguson/robot_calibration) - generic robot kinematics calibration for ROS -- [kalibr](https://github.com/ethz-asl/kalibr) - camera and imu calibration for ROS +- [handeye-calib-camodocal 通用的机器人手眼标定](https://github.com/jhu-lcsr/handeye_calib_camodocal) - generic robot hand-eye calibration. +- [robot_calibration 用于ROS的通用的机器人运动学标定](https://github.com/mikeferguson/robot_calibration) - generic robot kinematics calibration for ROS +- [kalibr用于ROS的摄像机和IMU标定 ](https://github.com/ethz-asl/kalibr) - camera and imu calibration for ROS 增强学习 Reinforcement Learning ---------------------- - [TensorForce](https://github.com/reinforceio/tensorforce) - A TensorFlow library for applied reinforcement learning -- [gqcnn](https://github.com/BerkeleyAutomation/gqcnn) - [Grasp Quality Convolutional Neural Networks (GQ-CNNs)](https://berkeleyautomation.github.io/gqcnn/info/info.html) for grasp planning using training datasets from the [Dexterity Network (Dex-Net)](https://berkeleyautomation.github.io/dex-net) -- [Guided Policy Search](https://github.com/cbfinn/gps) - Guided policy search (gps) algorithm and LQG-based trajectory optimization, meant to help others understand, reuse, and build upon existing work. +- [gqcnn 抓取规划](https://github.com/BerkeleyAutomation/gqcnn) - [Grasp Quality Convolutional Neural Networks (GQ-CNNs)](https://berkeleyautomation.github.io/gqcnn/info/info.html) for grasp planning using training datasets from the [Dexterity Network (Dex-Net)](https://berkeleyautomation.github.io/dex-net) +- [Guided Policy Search 引导策略搜索(GPS)算法和基于线性二次高斯控制的轨迹优化,旨在帮助其他人在对已有工作理解、重用和构建。](https://github.com/cbfinn/gps) - Guided policy search (gps) algorithm and LQG-based trajectory optimization, meant to help others understand, reuse, and build upon existing work. 传感器 设备 机械臂驱动 Drivers for Sensors, Devices and Arms ------------------------------------- -- [libfreenect2](https://github.com/OpenKinect/libfreenect2) - Open source drivers for the Kinect for Windows v2 and Xbox One devices. -- [iai_kinect2](https://github.com/code-iai/iai_kinect2) - Tools for using the Kinect One (Kinect v2) in ROS. -- [grl](https://github.com/ahundt/grl) - Generic Robotics Library: Cross platform drivers for Kuka iiwa and Atracsys FusionTrack with optional v-rep and ros drivers. Also has cross platform Hand Eye Calibration and Tool Tip Calibration. +- [libfreenect2 Windows Kinect V2与Xbox One设备开源驱动](https://github.com/OpenKinect/libfreenect2) - Open source drivers for the Kinect for Windows v2 and Xbox One devices. +- [iai_kinect2 在ROS中使用Kinect One (Kinect v2)的工具 ](https://github.com/code-iai/iai_kinect2) - Tools for using the Kinect One (Kinect v2) in ROS. +- [grl 通用机器人技术库:用于Kuka iiwa和Atracsys FusionTrack跨平台驱动程序,具有可选的v-rep和ros驱动;同时也有跨平台手眼标定与工具提示标定。](https://github.com/ahundt/grl) - Generic Robotics Library: Cross platform drivers for Kuka iiwa and Atracsys FusionTrack with optional v-rep and ros drivers. Also has cross platform Hand Eye Calibration and Tool Tip Calibration. 数据集 Datasets -------- -- [pascal voc 2012](http://host.robots.ox.ac.uk/pascal/VOC/voc2012/) - The classic reference image segmentation dataset. -- [openimages](https://github.com/openimages/dataset/) - Huge imagenet style dataset by Google. -- [COCO](mscoco.org) - Objects with segmentation, keypoints, and links to many other external datasets. -- [cocostuff](https://github.com/nightrome/cocostuff) - COCO additional full scene segmentation including backgrounds and annotator. -- [Google Brain Robot Data](https://sites.google.com/site/brainrobotdata/home) - Robotics datasets including grasping, pushing, and pouring. -- [Materials in Context](http://opensurfaces.cs.cornell.edu/publications/minc/) - Materials Dataset with real world images in 23 categories. -- [Dex-Net 2.0](http://bair.berkeley.edu/blog/2017/06/27/dexnet-2.0/) - 6.7 million pairs of synthetic point clouds and grasps with robustness labels. - -#### Dataset Collection +- [pascal voc 2012 经典的参考图像分割/目标检测 数据库](http://host.robots.ox.ac.uk/pascal/VOC/voc2012/) - The classic reference image segmentation dataset. +- [openimages Google庞大的ImageNet风格数据库](https://github.com/openimages/dataset/) - Huge imagenet style dataset by Google. +- [COCO 目标分割、关键点和许多其他外部数据库的链接](mscoco.org) - Objects with segmentation, keypoints, and links to many other external datasets. +- [cocostuff COCO附加的全场景分割,包括背景和注释](https://github.com/nightrome/cocostuff) - COCO additional full scene segmentation including backgrounds and annotator. +- [Google Brain Robot Data 谷歌 大脑包含抓取、推和浇注的机器人数据库 ](https://sites.google.com/site/brainrobotdata/home) - Robotics datasets including grasping, pushing, and pouring. +- [Materials in Context 23类真实图像的材料数据库](http://opensurfaces.cs.cornell.edu/publications/minc/) - Materials Dataset with real world images in 23 categories. +- [Dex-Net 2.0 670万对合成点云和具有鲁棒性标签的抓取 ](http://bair.berkeley.edu/blog/2017/06/27/dexnet-2.0/) - 6.7 million pairs of synthetic point clouds and grasps with robustness labels. -- [cocostuff](https://github.com/nightrome/cocostuff) - COCO additional full scene segmentation including backgrounds and annotator. +#### Dataset Collection 数据收集 + +- [cocostuff 670万对合成点云和具有鲁棒性标签的抓取 ](https://github.com/nightrome/cocostuff) - COCO additional full scene segmentation including backgrounds and annotator. 线性代数 几何学 Linear Algebra & Geometry ------------------------- -- [Eigen](eigen.tuxfamily.org) - Eigen is a C++ template library for linear algebra: matrices, vectors, numerical solvers, and related algorithms. -- [Boost.QVM](https://github.com/boostorg/qvm) - Quaternions, Vectors, Matrices library for Boost. -- [Boost.Geometry](https://github.com/boostorg/geometry/) - Boost.Geometry contains instantiable geometry classes, but library users can also use their own. -- [SpaceVecAlg](https://github.com/jrl-umi3218/SpaceVecAlg) - Implementation of spatial vector algebra for 3D geometry with the Eigen3 linear algebra library. -- [Sophus](https://github.com/strasdat/Sophus) - C++ implementation of Lie Groups which are for 3D Geometry, using Eigen. +- [Eigen 线性代数C++模板库,包含矩阵、向量、数值求解和相关算法](eigen.tuxfamily.org) - Eigen is a C++ template library for linear algebra: matrices, vectors, numerical solvers, and related algorithms. +- [Boost.QVM 用于Boost的四元数、向量、矩阵库](https://github.com/boostorg/qvm) - Quaternions, Vectors, Matrices library for Boost. +- [Boost.Geometry 包含可实例化的几何类,但是库用户也可以使用自定义的类](https://github.com/boostorg/geometry/) - Boost.Geometry contains instantiable geometry classes, but library users can also use their own. +- [SpaceVecAlg 实现三维几何的空间向量代数,使用了Eigen3 线性代数库](https://github.com/jrl-umi3218/SpaceVecAlg) - Implementation of spatial vector algebra for 3D geometry with the Eigen3 linear algebra library. +- [Sophus (用于三维几何)的C++实现,使用了Eigen 李代数库](https://github.com/strasdat/Sophus) - C++ implementation of Lie Groups which are for 3D Geometry, using Eigen. 点云 Point Clouds ------------ -- [libpointmatcher](https://github.com/ethz-asl/libpointmatcher) - An "Iterative Closest Point" library robotics and 2-D/3-D mapping. -- [Point Cloud Library (pcl)](https://github.com/PointCloudLibrary/pcl) - The Point Cloud Library (PCL) is a standalone, large scale, open project for 2D/3D image and point cloud processing. +- [libpointmatcher 一个“迭代最近点”的机器人库和二维/三维映射](https://github.com/ethz-asl/libpointmatcher) - An "Iterative Closest Point" library robotics and 2-D/3-D mapping. +- [Point Cloud Library (pcl)点云库(PCL)是一个独立的、大规模的、开放式的二维/三维图像和点云处理项目。 ](https://github.com/PointCloudLibrary/pcl) - The Point Cloud Library (PCL) is a standalone, large scale, open project for 2D/3D image and point cloud processing. 同时定位与建图 Simultaneous Localization and Mapping (SLAM) -------------------------------------------- -- [ElasticFusion](https://github.com/mp3guy/ElasticFusion) - Real-time dense visual SLAM system. -- [co-fusion](https://github.com/martinruenz/co-fusion) - Real-time Segmentation, Tracking and Fusion of Multiple Objects. Extends ElasticFusion. -- [Google Cartographer](https://github.com/googlecartographer/cartographer/) - Cartographer is a system that provides real-time simultaneous localization and mapping (SLAM) in 2D and 3D across multiple platforms and sensor configurations. -- [OctoMap](https://github.com/OctoMap/octomap) - An Efficient Probabilistic 3D Mapping Framework Based on Octrees. Contains the main OctoMap library, the viewer octovis, and dynamicEDT3D. -- [ORB_SLAM2](https://github.com/raulmur/ORB_SLAM2) - Real-Time SLAM for Monocular, Stereo and RGB-D Cameras, with Loop Detection and Relocalization Capabilities. +- [ElasticFusion 实时的密集视觉SLAM系统](https://github.com/mp3guy/ElasticFusion) - Real-time dense visual SLAM system. +- [co-fusion 多目标实时分割、跟踪和融合,ElasticFusion的扩展](https://github.com/martinruenz/co-fusion) - Real-time Segmentation, Tracking and Fusion of Multiple Objects. Extends ElasticFusion. +- [Google Cartographer 提供了实时的二维和三维SLAM系统,可以跨多个平台和传感器配置](https://github.com/googlecartographer/cartographer/) - Cartographer is a system that provides real-time simultaneous localization and mapping (SLAM) in 2D and 3D across multiple platforms and sensor configurations. +- [OctoMap 一个有效的基于概率三维映射框架,包含主要的OctoMap库, viewer octovis以及动态EDT3D. ](https://github.com/OctoMap/octomap) - An Efficient Probabilistic 3D Mapping Framework Based on Octrees. Contains the main OctoMap library, the viewer octovis, and dynamicEDT3D. +- [ORB_SLAM2 实时SLAM,用于单眼、立体、RGB-D相机,包含循环检测与重定位功能 ](https://github.com/raulmur/ORB_SLAM2) - Real-Time SLAM for Monocular, Stereo and RGB-D Cameras, with Loop Detection and Relocalization Capabilities. +- [栅格地图 移动机器人导航 Grid Map – Universal grid map library for mobile robotic mapping](https://github.com/ethz-asl/grid_map) + + diff --git a/stereo/RGBD/readme.md b/stereo/RGBD/readme.md index 961c2167..7117d805 100644 --- a/stereo/RGBD/readme.md +++ b/stereo/RGBD/readme.md @@ -83,5 +83,115 @@ 畸变参数: -0.40128 0.407587 0.000954767 0.000714202 0.114102 0.0422759 0.11784 0.370694 -0.0115273 0.00464497 -0.00642652 0.00200558 + +# 主动立体双目算法的框架 +https://blog.csdn.net/u013626386/article/details/79892149 + step1. 双目设备的标定; + step2. 双目设备的校准; + step3. 双目立体匹配算法; + step4. 视差数据的去噪与空洞修复 + step5. 视差数据映射到三维深度值 + 如果涉及到输出显示 RGB point cloud,需要另外结合1颗RGB彩色摄像头, + 标定位置关系后可以将点云数据的RGB值一一对应上,用作3D彩色显示, + step6. RGB与点云数据的配准与对齐。 + + +# 视差图空洞修复算法 + // https://blog.csdn.net/u013626386/article/details/54860969 + holefilling算法流程 + Input:disp –待修复视差图Output:dstDisp -修复后视差图 + Step1.找到disp中未计算深度的空点,空点集合设为Ω; + Step2.遍历每一空点Ω(e),根据其邻域信息δ(e)判断其是否处于空洞中, + 如果δ(e)内包含一半以上的深度有效像素(validPixel),则认为其为空洞点; + Step3.使用方形滤波器对空洞点进行填补,利益滤波器与有效像素的加权值补充空洞点处深度值,得到dstDisp; + + Step4.根据设定的迭代次数(iteration)来,置disp =dstDisp,并重复上述步骤, + 直至迭代完成,输出结果修复后的dstDisp,并据此生成深度数据。 + + 滤波器及权重设置: + 采用类似高斯权重设置的方法设置该滤波器权重,离目标像素越远的有效像素, + 对该空洞点视差值填补的贡献越小。 + filterSize滤波器大小选择: + 滤波器目前可选取5x5, 7x7, 9x9, 11x11. + + validPixel有效像素点数选择: + 例如:使用5x5的滤波器时,需要对空点周边的24个像素值进行深度有效像素点数量的判断, + 通常认为,空洞点周边应被有效点所环绕,所以此时有效像素点数至少设置为滤波器包含像素一半以上才合理, + 可设置为validPixel =12;使用其他size滤波器时,有效像素点数设置也应大于滤波器包含像素一半。 + + iteration迭代次数选择 + 针对不同的滤波器大小,收敛至较好效果时的迭代次数不一样,需要根据具体场景分析设定。 +```c +void holefilling(Mat _dispSrc, Mat* _dispDst) +{ + int64 t = getTickCount(); + if (CV_8UC1 != _dispSrc.type()) + { + _dispSrc.convertTo(_dispSrc, CV_8UC1); + } + Mat dispBw; + threshold(_dispSrc, dispBw, dispMin, 255, THRESH_BINARY); + dispBw.convetTo(dispBw, CV_32F, 1.0/255); + Mat dispValid; + _dispSrc.convertTo(dispValid, CV_32F); + int margin = filterSize/2; + Mat dispFilt = _dispSrc; + + for (int i = margin; i < dispBw.rows; i++) + { + for (int j = margin; j < dispBw.cols; j++) + { + if (0 == dispBw.at(i, j)) + { + Mat filtMat = dispBw(Range(i - margin, i + margin + 1), Range(j - margin, j + margin + 1)); + Scalar s = sum(filtMat); + if (s[0] > validPixel) +       { + Mat tmpWeight; +         multiply(filtMat, domainFilter, tmpWeight); +         Scalar s1 = sum(tmpWeight); +         Mat valid = dispValid(Range(i - margin, i + margin + 1), Range(j - margin, j + margin + 1)); +         Mat final; +         multiply(tmpWeight, valid, final); +         Scalar s2 = sum(final); +         dispFilt.at(i, j) = (unsigned char)(s2[0] / s1[0]); +       } + } + else + { + dispFilt.at(i, j) = (unsigned char)(dispValid.at(i, j)); + } + } + } + *dispDst = dispFilt; + t = getTickCount() - t; + printf("Time Elapsed t : %fms\n", t1*1000/getTickFrequency); +} + +``` + +# 视差图去噪 +```c +static int depthDenoise(Mat _dispSrc, Mat* _dispDenoise) +{ + Mat contourBw; + threshold(_dispSrc, contourBw, dispMin, 255, THRESH_BINARY); + vector> contours; + findContours(contourBw, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); + double minArea = 10000*scale; + for (int i = contours.size() - 1; i >= 0; i--) + { + double area = countourArea(contours[i]); + if (area < minArea) + { + contours.erase(contours.begin() + i); + } + } + Mat contourDisp(_dispSrc.size(), CV_8UC1, Scalar(0)); + drawContours(contourDisp, contours, Scalar(1), -1); + multiply(_dispSrc, contourDisp, *_dispDenoise); + return 0; +} +``` diff --git a/stereo/readme.md b/stereo/readme.md index fc1ed7ba..0aecbffe 100644 --- a/stereo/readme.md +++ b/stereo/readme.md @@ -64,6 +64,9 @@ [双目障碍物检测](https://github.com/Ewenwan/homemade_stereo_obstacle_detection) +[深度学习双目匹配 DispNet]() + + ## 可以建立 相机坐标系下的 点云 ## 如需建立 世界坐标系下的点云 需要跟踪 每一帧图像的位姿变化 既需要配合 视觉里程计来使用 [viso2](http://wiki.ros.org/viso2) diff --git a/stereo/stereo/readme.md b/stereo/stereo/readme.md index 4b3864be..89f7b113 100644 --- a/stereo/stereo/readme.md +++ b/stereo/stereo/readme.md @@ -1,13 +1,13 @@ # 双目相机 算法 -[ ADCensus, SGBM, BM算法参考](https://github.com/DLuensch/StereoVision-ADCensus) +[双目立体视觉算法 ADCensus, SGBM, BM算法参考](https://github.com/DLuensch/StereoVision-ADCensus) [ELAS论文解析](https://www.cnblogs.com/sinbad360/p/6883623.html) [ELAS代码](https://github.com/Ewenwan/ELAS) [棋盘格](https://github.com/DLuensch/StereoVision-ADCensus/tree/master/Documents/chessboards) +[双目视差图 精细化调整算法](https://github.com/Ewenwan/FDR) [DynamicStereo 算法较多 参考](https://github.com/Ewenwan/DynamicStereo) - [双目算法、光流算法、分层深度图估计算法 ](https://github.com/Ewenwan/ParallelFusion) ## 双目相机 矫正 diff --git "a/stereo/\345\217\214\347\233\256\347\253\213\344\275\223\345\214\271\351\205\215.md" "b/stereo/\345\217\214\347\233\256\347\253\213\344\275\223\345\214\271\351\205\215.md" new file mode 100644 index 00000000..756ac85a --- /dev/null +++ "b/stereo/\345\217\214\347\233\256\347\253\213\344\275\223\345\214\271\351\205\215.md" @@ -0,0 +1,336 @@ +# 立体视觉 stereo correspondence(双目立体匹配) +[参考](https://www.xuebuyuan.com/1541954.html) + + 立体视觉是计算机视觉领域的一个重要课题,它的目的在于重构场景的三维几何信息。 + 立体视觉的研究具有重要的应用价值,其应用包括移动机器人的自主导航系统, + 航空及遥感测量,工业自动化系统等。 + + +# 1. 引言 + + 一般而言,立体视觉的研究有如下三类方法: + (1) 直接利用测距器(如激光测距仪)获得程距(range data)信息,建立三维描述的方法; + (2) 仅利用一幅图象所提供的信息推断三维形状的方法; + (3) 利用不同视点上的,也许是不同时间拍摄的,两幅或更多幅图象提供的信息重构三维结构的方法。 + + + 第一类方法,也就是程距法 (range data method),根据已知的深度图, + 用数值逼近的方法重建表面信息,根据模型建立场景中的物体描述,实现图象理解功能。 + 这是一种主动方式的立体视觉方法,其深度图是由测距器(range + finders)获得的,如结构光(structured light)、激光测距器(laser range finders) + 等其他主动传感技术 (active sensing techniques)。 + 这类方法适用于严格控制下的环境(tightly controlled domains),如工业自动化的应用方面。 + + + 第二类方法,依据光学成象的透视原理及统计假设,根据场景中灰度变化导出物体轮廓及表面,由影到形(shape + from shading),从而推断场景中的物体。线条图的理解就是这样的一个典型问题, + 曾经引起了普遍的重视而成为计算机视觉研究领域的一个焦点,由此产生了各种各样的线条标注法。 + 这种方法的结果是定性的,不能确定位置等定量信息,该方法由于受到单一图象所能提供信息的局限性,存在难以克服的困难。 + + + + 第三类方法,利用多幅图象来恢复三维信息的方法,它是被动方式的。 + 根据图象获取方式的区别又可以划分成普通立体视觉和通常所称的光流(optical + flow)两大类。普通立体视觉研究的是由两摄像机同时拍摄下的两幅图象, + 而光流法中研究的是单个摄像机沿任一轨道运动时顺序拍下的两幅或更多幅图象。 + 前者可以看作后者的一个特例,它们具有相同的几何构形,研究方法具有共同点。 + 双目立体视觉是它的一个特例。 + + +# 立体视觉的研究由如下几部分组成: + +## (1) 图象获取 (image acquisition) + + + 用作立体视觉研究的图象的获取方法是多种多样的, + 在时间、视点、方向上有很大的变动范围,直接受所应用领域的影响。 + 立体视觉的研究主要集中在三个应用领域中,即自动测绘中的航空图片的解释, + 自主车的导引及避障,人类立体视觉的功能模拟。不同的应用领域涉及不同类的景物, + 就场景特征的区别来分, + 可以划分成两大类, + 一类是含有文明特征(cultural features)的景物,如建筑、道路等; + 另一类是含有自然特征的景物和表面(natural objects and surfaces), + 如山、水、平原及树木等。不同类的景物的图象处理方法大不相同,各有其特殊性。 + + + + 总之,与图象获取相关的主要因素可归纳如下: + (a) 场景领域 (scene domain), + (b) 计时 (timing), + (c) 时间(照明和阴影)(time of day (lighting and presence ofshadows)), + (d) 成像形态(包括特殊的遮盖)(photometry (including special coverage)), + (e) 分辨率 (resolution), + (f) 视野 (field of view), + (g) 摄像机的相对位置 (relative camera positioning). + + + + 场景的复杂程度受如下因素的影响: + (a) 遮掩 (occlusion), + (b) 人工物体(直的边界,平的表面) (man-made objects (straight edge, flat surfaces)), + (c) 均匀的纹理区域 (smoothly textured areas), + (d) 含有重复结构的区域 (areas containing repetitive structure)。 + + +## (2) 摄像机模型 (camera modeling) + + 摄像机模型就是对立体摄像机组的重要的几何与物理特征的表示形式, + 它作为一个计算模型,根据对应点的视差信息,用于计算对应点所代表的空间点的位置。 + 摄像机模型除了提供图象上对应点空间与实际场景空间之间的映射关系外, + 还可以用于约束寻找对应点时的搜索空间,从而降低匹配算法的复杂性,减小误匹配率。 + + +## (3) 特征抽取 (feature acquisition), + 几乎是同一灰度的没有特征的区域是难以找到可靠匹配的, + 因而,绝大部分计算机视觉中的工作都包括某种形式的特征抽取过程, + 而且特征抽取的具体形式与匹配策略紧密相关。 + 在立体视觉的研究中,特征抽取过程就是提取匹配基元的过程。 + + +## (4) 图象匹配 (image matching), + 图象匹配是立体视觉系统的核心,是建立图象间的对应从而计算视差的过程,是极为重要的。 + + +## (5) 深度计算 (distance(depth) determination), + 立体视觉的关键在于图象匹配,一旦精确的对应点建立起来,距离的计算相对而言只是一个简单的三角计算而已。 + 然而,深度计算过程也遇到了显著的困难,尤其是当对应点具有某种程度的非精确性或不可靠性时。 + 粗略地说,距离计算的误差与匹配的偏差成正比,而与摄像机组的基线长成反比. + 加大基线长可以减少误差,但是这又增大了视差范围和待匹配特征间的差别,从而使匹配问题复杂化了。 + 为了解决这一问题出现了各种匹配策略,如由粗到精策略,松驰法等。 + + 在很多情况下,匹配精度通常是一个象素。但是,实际上区域相关法和特征匹配法都可以获得更好的精度。 + 区域相关法要达到半个象素的精度需要对相关面进行内插。尽管有些特征抽取方法可以得到比一个象素精度更好的特征, + 但这直接依赖于所使用的算子类型,不存在普遍可用的方法。 + + 另一种提高精度的方法是采用一个象素精度的算法,但是利用多幅图象的匹配, + 通过多组匹配的统计平均结果获得较高精度的估计。 + 每组匹配结果对于最后深度估计的贡献可以根据该匹配结果的可靠性或精度加权处理。 + + 总之,提高深度计算精度的途径有三条,各自涉及了一些附加的计算量: + (a) 半象素精度估计 (subpixel estimation), + (b) 加长基线长 (increased stereo baseline), + (c) 几幅图的统计平均 (statistical averaging over several views)。 + + +## (6) 内插 (interpolation). + 在立体视觉的应用领域中,一般都需要一个稠密的深度图。 + 基于特征匹配的算法得到的仅是一个稀疏而且分布并不均匀的深度图。 + 在这种意义下,基于区域相关匹配的算法更适合于获得稠密的深度图, + 但是该方法在那些几乎没有信息(灰度均匀)的区域上的匹配往往不可靠。 + 因此,两类方法都离不开某种意义的内插过程。最为直接的将稀疏深度图内插成 + 稠密的深度图的方法是将稀疏深度图看作为连续深度图的一个采样, + 用一般的内插方法(如样条逼近)来近似该连续深度图。当稀疏深度图足以反映深度的重要变化时, + 该方法可能是合适的。如起伏地貌的航空立体照片的处理中用这种方式的内插也许是比较合适的。 + 但是这种方法在许多应用领域中,尤其是在有遮掩边界的图象的领域中,就不适用了。 + + Grimson 指出可匹配特征的遗漏程度反映了待内插表面变化程度的相应限度, + 在这种基础上,他提出了一个内插过程[2]。换一角度来看,根据单幅图象的“由影到形”的技术, + 用已经匹配上的特征来建立轮廓条件和光滑的交接表面可以确保内插的有效性。 + 这些方法结合起来,可以使内插过程达到合乎要求的目标。 + 内插的另一种途径是在已有的几何模型与稀疏深度图之间建立映射关系,这是模型匹配过程。 + 一般而言,要进行模型匹配,预先应将稀疏深度图进行聚类,形成若干子集,各自相应于一种特殊结构。 + 然后找每一类的最佳对应模型,该模型为这种特殊结构(物体)提供参数和内插函数。 + 如Gennery用这种方法来发现立体对图片中的椭园结构,Moravec 用于为自主车探测地面。 + + +# 2. 双目立体视觉(Binocular Stereo Vision) +## 2.1 双目立体视觉模型 + 双目立体视觉理论建立在对人类视觉系统研究的基础上,通过双目立体图象的处理, + 获取场景的三维信息,其结果表现为深度图,再经过进一步处理就可得到三维空间中的景物, + 实现二维图象到三维空间的重构。 + Marr-Poggio-Grimson + 最早提出并实现了一种基于人类视觉系统的计算视觉模型及算法。 + 双目立体视觉系统中,获取深度信息的方法比其它方式(如由影到形方法)较为直接, + 它是被动方式的,因而较主动方式(如程距法)适用面宽,这是它的突出特点。 + 双目立体视觉系统中, + + 深度信息的获得是分如下两步进行的: + (1) 在双目立体图象间建立点点对应, + (2) 根据对应点的视差计算出深度。 + 第一部分,也就是对应点问题,是双目立体视觉的关键; 第二部分是摄像机模型问题。 + 双目立体视觉模型中,双摄像机彼此参数一致,光轴平行且垂直于基线, + 构成一共极性 (epipolar) 结构,这样做是为了缩小对应的搜索空间, + 只有水平方向的视差,简化了对应过程,如下图所示。 + +  + + 如上图所示,设空间一点P(X,Y,Z)在两个平行放置的完全相同的摄象机中像点分别是(x1,y1). + (x2,y2),则在知道基线长B和焦距f的情况下,可以计算出深度 + 这是双目立体视觉的基本原理,即根据视差来恢复立体信息。 + + +## 2.2 匹配基元 + 匹配基元是指匹配算法的最小匹配对象,它是由特征抽取算法产生的。 + 在建立立体视觉系统时,必须根据环境的特点和应用的领域选择适当的匹配基元。 + + 匹配基元可以是: + (1) 过零点 (zero-crossings), + (2) 边界与线片段 (edge and line fragments), + (3) 线性特征 (linear features), + (4) 边缘轮廓 (object boundaries), + (5) 兴趣算子抽取的特征点(如角点等) + + 基元作为匹配算法处理的基本单位,是局部特征,应包含以下一些信息: + (1) 维量(点、线、边界等) (dimensionality), + (2) 尺度(空间频度,长短、大小、方向等)(size (spatial frequency)), + (3) 亮度(对比度) (contrast), + (4) 语义量 (semantic content), + (5) 稠密度 (density of occurrence), + (6) 简单可量度的分布特征 (easily measurable attributes), + (7) 唯一性/突出性 (uniqueness/distinguishability) + + +## 2.3 匹配算法 + 匹配算法就是在两幅图象的匹配基元之间建立对应关系的过程,它是双目立体视觉系统的关键。 + 实际上,任何计算机视觉系统中都包含一个作为其核心的匹配算法,因而对于匹配算法的研究是极为重要的。 + 为了比较全面地考察匹配算法,这里不妨将双目立体视觉的匹配算法扩展到更一般的情况来分析: + 假设给定两幅同一环境的图象,这两幅图象可能由于摄取的时间、方位或方式的不同而有差别, + 如双目立体视觉系统所摄取的两幅图象、地图与遥感或航测图象等,如何找到彼此对应的部分? + + 对于这个问题,一般有两种考虑途径: + + (1) 灰度分布的相关性, + (2) 特征分布的相似性。 + + 因而就有两类算法: + (1) 基于灰度的算法 (intensity based), + (2) 基于特征的算法 (feature based)。 + + 如果按照控制策略分,有如下几种: + (1) 粗到精多层次结构 (coarse-to-fine,hierarchical), + (2) 引入约束条件的松驰法 (constraints, relaxation), + (3) 多级表示的决策结构 (multilevel representation)。 + + +### 2.3.1 基于灰度的匹配算法 + 基于灰度的算法是指图象处理中所称的区域相关方法 (area-correlation technique), + 它是解决对应问题的一个最直观最简单的方法。在一幅图象中以一点为中心选定一区域(窗口), + 在另一幅图象中寻找与该区域相关系数最大的区域,把该找到的区域的中心认为是原来那区域中心的对应点。 + 这里所说的图象包括经过某种特殊处理如Gauss滤波后的图象。 + 这种算法计算量大,但可以得到整幅图象的视差图。该算法对噪音很敏感,考虑到计算量, + 窗口不宜开得过大,因而可能匹配的选择较大,误对应可能性大,不适于灰度分布均匀的图象, + 较适于灰度分布很复杂的图象,如自然景物等。采用该方法的关键在于排除或减轻噪音的影响。 + 通常采用多层次相关对应及多幅图象的统计平均处理方式来实现。 + 如 D. B. Gennery [2]采用九幅图象多级处理方式来实现对应求解。 + + +### 2.3.2 基于特征的匹配算法 + 鉴于灰度区域相关方法的局限性,现在大部分研究集中在这方面。 + 在许多环境(如有线条轮廓特征可寻的人工环境 (man-made structured world))中, + 图象的特征是很有规律地分布的,反映了场景的核心,数量少, + 处理方便。基于特征的匹配算法特别适用于特殊的比较简单的环境如室内环境,具有速度快、精度高的特点, + 但对于自然环境,由于缺少显著的主导特征,该方法也遇到了很大困难。 + 基于特征的双目立体视觉的对应算法,通过建立所选基元的对应关系,旨在获取一稀疏深度图, + 如果需要再经过内插等方法可以得到整幅深度图。这一类算法因各自采用的匹配基元不同而相异。 + 概括而言,该类匹配算法都是建立在匹配基元之间的相似性度量基础上的。 + 这种相似性度量被称为亲合性 (affinity)[2], 它是以匹配基元的各项参数信息为依据的局部特征相似程度的度量。 + 这种度量方法与摄像机模型相结合,可以大大减小匹配时的搜索空间。 + 由于仅利用亲合性建立匹配是模糊的,可能匹配的空间仍旧很大(多对一的), + 因此有必要引入其它约束条件及控制策略来限制搜索空间,减小模糊程度。 + 匹配算法中常引入的两种约束条件及控制策略是: + + (1) 共极性 (epipolar) (双目立体视觉模型特点), + + (2) 连续性 (continuity), + (3) 分层次的匹配策略(即由粗到精策略)(hierarchical (e.g.,coarse-fine) matching strategy)。 + 这种引入约束的方法实际上是将有关环境模型的知识融于算法之中。 + + 这种算法的具体实现,可以采用概率度量、松驰法迭代或者聚类等模式识别算法来实现。 + 作为最后结果的1-1 对应,可以利用启发式搜索方法从已经大大减小了的搜索空间中获得。 + 这部分可望能利用现代 AI 研究的许多手段如专家系统等研究方法, + 作为承上启下,建立更高层次描述的先导。 + + 可以从以下几个角度来比较各种匹配算法, + (1) 精度 (accuracy), + (2) 可靠性(排除总体分类误差的程度)(reliability), + (3) 通用性(适于不同场景的能力)(available of performance models), + (4) 预见性 (predictability), + (5) 复杂性(设备及计算量的代价)(complexity (cost implementation, + computational requirements))。 + + + + 立体视觉的匹配算法有: + (1) Marr-Poggio-Grimson算法,以过零点为基元,采用由粗到精的控制策略, + 用精度较低层次的匹配来限定精度较高层次匹配的搜索空间, + 最后利用连续性约束通过迭代方式实现匹配过程。处理对象是自然景物的双目立体图象。 + (2) R. Nevatia-G.Medioni算法,以线片段 (segments) 为基元, + 以最小差别视差 (minimum differential disparity) 为基准,建立匹配过程。 + 该基准实际上是连续性约束的一种表现形式, + 在对应线片段各自邻域内存在的对应线片段的视差与其视差相近。处理对象是人工环境的双目立体图象。 + (3) R. Y. Wong算法,旨在建立两类图象的对应关系,如航空照片、遥感图象与灰度图象之间的对应关系。 + 以边界特征(edge feature)为依据采用顺序的 (sequential)、 + 多层次结构 (hierarchical structure)的搜索策略实现匹配过程。 + (4) K. Price-R. Reddy算法,依据场景的线条特征模型,将自顶向下(人工智能) + (top-down (artificial intelligence))与自底向上(模式识别)(bottom-up (pattern recognition)) + 两种控制策略有效地结合起来,采用广义的相关方法进行匹配,旨在建立形态差别较大的两幅图象 + (一幅是参照图或参考模型,另一幅是待对应的图象)的对应关系。如机场模型与机场的航空照片之间的对应关系。 + (5) C. S. Clark-A. L. Luck-C. A. McNary算法,抽取线条轮廓特征建立模型,在模型间建立对应。 + 适于存在较大差别的图象的匹配。 + (6) K. E. Price算法,用于在图象间建立区域对应。该算法利用区域间的相互关系, + 以松驰法为基本思想实现了多层次表示结构下的匹配过程。 + 突出特点是匹配算法考虑了图象本身区域间的相互关系(如包含、子部分等)的匹配, + 具有类似于某种语义网络式的启发性。 + (7) R. Horaud-T. Skorads算法,以线条特征为匹配基元,每个线条特征不仅含有其本身的端点坐标及方向矢量信息, + 而且含有它同那些与其相邻的线条特征之间存在的相对位置及结构关系的信息。 + 这些特征将每幅图象表示成为一个关系图,根据该关系图对于每个线条特征确定它在另一幅图象中的可能对应集合, + 以每组对应为一结点构造对应图,依据关系图的相容性通过利益函数(benefit function)确定最佳对应。 + 它处理的对象是室内环境的双目立体图象。 + (8) W. Hoff-N. Ahuja算法,以过零点为最小特征,将特征匹配、轮廓检测以及表面内插这三个过程结合在一起, + 采用基于多层表示的由粗到精的控制策略,根据对于表面的光滑性约束重构三维表面。 + 这是一种与传统方法大不相同的算法,适合于有纹理特征的环境如工作台上的物品, + 不适合于稀疏特征环境如室内环境。另外 S. I. Olsen提出的算法与此相似, + 它将表面的重构过程(reconstruction process)结合在对应匹配过程中, + 基于多重属性用松弛法进行匹配,逐步提高重构的视差表面与实际的视差数据的一致性。 + + +## 2.4 双目立体视觉系统 + 双目立体视觉经过几十年的研究已经取得了显著了成果,出现了各种专门的硬件设计和视频速率(实时)的立体视觉系统, + 在理论和技术方面都比较成熟了。但是,从普遍的意义来讲,由于很难彻底地解决对应点问题, + 具体的立体视觉系统一般都是有针对性的、不是普遍适用的,还无法与人类的双目视觉系统相媲美。 + + 下图是SRI的集成在电路板上的双目立体视觉系统。CMU设计了Stereo Machine, 可以实时地获取深度信息。 + + 立体摄象机校准 Stereo Camera Calibration + 三维视觉 + Milan Sonka, 3D Vision + 集成在电路板上的立体摄象机对SRI Stereo Engine, Stereo head onboard + 立体几何模型 SRI Stereo Geometry + 双目立体视觉Introduction to Stereo Imaging -- Theory + +# 3. 结构光方法(Structured Light) + 将平面光束照射在物体上可以形成光带,光带的偏转数据反映了物体表面的三维形状信息, + 用这种方法可以精确地获取物体的三维信息。借助于一组平行的平面光, + 或将物体置于专门的旋转工作台上通过一束平面光, + 都可以利用偏转数据直接地计算出深度信息,称这种方法为结构光方法。 + 结构光方法适合于限制条件下,局部范围内需要精确测量的情况,用于不规则表面的三维建模。 + 结构光方法在工业上有重要的应用,例如从传送带上检测工件,工件的逆工程(Reverse engineering); + 在图形建模方面也有重要的应用,如人体建模,包括头部等躯体模型,雕塑造型的数字化。实际上它是三维扫描仪的基本原理。 + 如下图所示的装置,就是结构光方法的典型事例。 + + 详细可见:Our Active Stereo Vision System + + +# 4. 激光雷达与程距数据(Range Data)处理 + 激光雷达(Laser range finder)与结构光方法不同,它直接利用激光光速扫描物体, + 通过测量光束从发出到反射回来的时间差来计算深度信息。 + 它提供的数据是深度图,称为程距数据(Range data)。 + 激光雷达可以用于比较大范围的测量,如移动机器人可以用激光雷达信息来建立环境内模型,以实现自主导航、躲避障碍等功能。 + 程距数据实际上就是深度图象,结构光方法和激光雷达得到的数据最后都是深度信息。 + 程距数据处理主要是表面拟合,恢复物体的表面结构。 + + +5. 视觉临场感系统 + 临场感(Telepresence)技术是新一代遥操作(Teleoperation)系统的重要组成部分。 + 顾名思义,它的目的就是使人从远地遥控操作时具有在现场处实地操作式的身临其境的感觉。 + 在理想情况下,这些感觉应该包括人的各种感官所能感受到的感觉, + 如视觉、听觉、触觉、味觉、体位觉、力感等。 + 临场感系统因其面对的任务不同,所需的现场信息有所区别,其中,视觉通常是最重要的信息之一, + 其次才是听觉、触觉等。目前,临场感技术主要涉及视觉和听觉。 + 临场感遥操作系统的主要优点是:将人与机器人有机地结合起来,能够恰到好处地发挥出各自的特长。 + 机器代替人去危险或人不可能到达的区域去工作,而人的判断能力和决策水平又明显地提高了系统的整体智能水平。 + 如下图所示,室外车辆上的立体摄象机将视频信号传回基地端, + 操作员通过立体眼睛观察环行屏幕,仿佛他亲自在车上一样能够具有身临其境的感觉。 + + + diff --git a/vSLAM/LoopClosing/readme.md b/vSLAM/LoopClosing/readme.md new file mode 100644 index 00000000..b25437eb --- /dev/null +++ b/vSLAM/LoopClosing/readme.md @@ -0,0 +1,41 @@ +# LoopClosing 闭环检测 + +## 1 视觉信息 闭环检测 + +[LoopClosing闭环检测](http://frc.ri.cmu.edu/~kaess/vslam_cvpr14/media/VSLAM-Tutorial-CVPR14-A23-LoopClosing.pdf) + +[DBoW2 二进制字符串特征 词袋模型](https://github.com/dorian3d/DBoW2) + +[DBoW3 二进制、浮点型特征 词袋模型](https://github.com/Ewenwan/DBow3) + +[FBOW AVX,SSE and MMX指令集优化的 DBoW2 DBoW3](https://github.com/rmsalinas/fbow) + +[haloc 图像特征哈希表示 图像与图像匹配](https://github.com/srv/libhaloc) + + +## 2 雷达激光数据闭环检测 + +[Deformation Loop Closure sample code to enable non-rigid alignment of point clouds.](https://github.com/Ewenwan/DeformationLoopClosure) + +[laser_loop_closure](https://github.com/Ewenwan/laser_loop_closure) + +[laserScan_Similarity](https://github.com/zc-tx/laserScan_Similarity) + +[]() + +[]() + +[]() + +## 3 视觉闭环 结合 激光闭环 + + +[]() + +[]() + +[]() + +[]()laserScan_Similarity + + diff --git a/vSLAM/VIO/VINS-Mono/readme.md b/vSLAM/VIO/VINS-Mono/readme.md index 18873a7d..43dd2f14 100644 --- a/vSLAM/VIO/VINS-Mono/readme.md +++ b/vSLAM/VIO/VINS-Mono/readme.md @@ -15,8 +15,17 @@ [VINS-Mobile MacOS](https://github.com/Ewenwan/VINS-Mobile) +[代码注释](https://github.com/Ewenwan/VINS-Mono-code-annotation) + ![](https://pic3.zhimg.com/80/v2-145f576a58d1123a9faa1d265af40522_hd.png) + +![](https://images2018.cnblogs.com/blog/699318/201804/699318-20180414235214918-500793897.png) + +[VINS-Mono代码注释以及公式推导](https://github.com/Ewenwan/VINS-Mono-code-annotation) + +[VINS-Mono代码注释,仅供学习](https://github.com/Ewenwan/VINS-Mono-Learning) + ### Feature tracker 特征跟踪 这部分代码在feature_tracker包下面,主要是接收图像topic, 使用KLT光流算法跟踪特征点,同时保持每一帧图像有最少的(100-300)个特征点。 diff --git a/vSLAM/VIO/msckf/readme.md b/vSLAM/VIO/msckf/readme.md index 48d75124..e385e28b 100644 --- a/vSLAM/VIO/msckf/readme.md +++ b/vSLAM/VIO/msckf/readme.md @@ -5,6 +5,9 @@ [论文 MSCKF 2.0 : High-Precision, Consistent EKF-based Visual-Inertial Odometry](http://intra.ece.ucr.edu/~mourikis/papers/Li2013IJRR.pdf) +[双目MSCKF视觉惯性里程计](https://github.com/Ewenwan/msckf_vio) + + # 紧耦合 紧耦合方式使用 IMU 完成视觉 VO 中的运动估计 , IMU 在图像帧间的积分的误差比较小 , IMU的数据可用于预测帧间运动 , diff --git a/vSLAM/VIO/readme.md b/vSLAM/VIO/readme.md index c14ba5f8..fda816c0 100644 --- a/vSLAM/VIO/readme.md +++ b/vSLAM/VIO/readme.md @@ -12,6 +12,10 @@ [视觉惯性单目SLAM知识 ](https://blog.csdn.net/myarrow/article/details/54694472) +[VINS-Mono代码注释以及公式推导](https://github.com/Ewenwan/VINS-Mono-code-annotation) + +[VINS-Mono代码注释,仅供学习](https://github.com/Ewenwan/VINS-Mono-Learning) + IO和之前的几种SLAM最大的不同在于两点: 首先,VIO在硬件上需要传感器的融合,包括相机和六轴陀螺仪, 相机产生图片, @@ -104,6 +108,26 @@ [四元数AHRS姿态解算和IMU姿态解算分析](http://www.bspilot.com/?p=121) +[IMU代码参考](https://github.com/Ewenwan/IMUProject) + +[鲁棒陀螺仪双积分](https://github.com/Ewenwan/ridi_imu) + + IMU预积分技术最早由T Lupton于12年提出 http://www.sohu.com/a/242760307_715754 + +[Visual-Inertial-Aided Navigation for High-Dynamic Motion in Built Environments Without Initial Conditions]( https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=6092505) + + C Forster于15年[2][3][4]将其进一步拓展到李代数上,形成了一套优雅的理论体系。 + https://arxiv.org/pdf/1512.02363v1.pdf + http://rpg.ifi.uzh.ch/docs/RSS15_Forster.pdf + http://rpg.ifi.uzh.ch/docs/RSS15_Forster_Supplementary.pdf + + Forster将IMU预积分在开源因子图优化库GTSAM中进行了实现,并完成了和其另一大作SVO的组合。 + https://bitbucket.org/gtborg/gtsam + https://github.com/Ewenwan/gtsam-1 + + 这套理论目前已经被广泛的应用在基于Bundle Adjustment优化框架的Visual Inertial Odometry中。 + 其中包括VI-ORBSLAM,港科大VINS,浙大ICE-BA等。 + # 难点 复杂性主要来源于 IMU测量 加速度 和 角速度 这两个量的事实,所以不得不引入运动学计算。 diff --git a/vSLAM/VS_SLAM/readme.md b/vSLAM/VS_SLAM/readme.md index 524ac724..b6e3f6c5 100644 --- a/vSLAM/VS_SLAM/readme.md +++ b/vSLAM/VS_SLAM/readme.md @@ -1,5 +1,129 @@ # 深度学习结合SLAM 研究现状总结 +[参考 技术刘](http://www.liuxiao.org/2018/08/semantic-slam-%E6%96%87%E7%AB%A0%E6%94%B6%E9%9B%86/) + +[语义 SLAM 中的概率数据融合 ](https://www.cis.upenn.edu/~kostas/mypub.dir/bowman17icra.pdf) + +[语义SLAM的概率数据关联 解析(一)简介](https://zhuanlan.zhihu.com/p/39849427) + +[上面的论文——融合传统CPM分割语义信息](http://www.liuxiao.org/wp-content/uploads/2018/08/Probabilistic-Data-Association-for-Semantic-SLAM.pdf) + + 期望最大化(EM) 估计来把语义 SLAM 转换成概率问题,优化目标仍然是熟悉的重投影误差。 + 这篇文章只用了 DPM 这种传统方法做检测没有用流行的深度学习的检测网络依然取得了一定的效果。 + 当然其文章中有很多比较强的假设,比如物体的三维中心投影过来应该是接近检测网络的中心, + 这一假设实际中并不容易满足。 + +[融合语义分割信息 Visual Semantic Odometry ](http://www.liuxiao.org/wp-content/uploads/2018/08/VSO-Visual-Semantic-Odometry.pdf) + + 既然检测可以融合,把分割结果融合当然是再自然不过的想法,而且直观看来分割有更加细粒度的对物体的划分 + 对于 SLAM 这种需要精确几何约束的问题是更加合适的。 + ETH 的这篇文章紧随其后投到了今年的 ECCV 2018。 + 这篇文章依然使用 EM 估计,在上一篇的基础上 + + 使用 距离变换将分割结果的边缘作为约束, + 同时依然利用投影误差构造约束条件。 + + 在 ORB SLAM2 和 PhotoBundle 上做了验证取得了一定效果。这篇文章引入 距离变换 的思路比较直观, + 很多人可能都能想到,不过能够做 work 以及做了很多细节上的尝试,依然是非常不容易的。 + 但仍然存在一个问题是,分割的边缘并不代表是物体几何上的边缘, + 不同的视角这一分割边缘也是不停变化的,因此这一假设也不是非常合理。 + + 总目标函数 = 基本的里程计目标函数: + cet*语义匹配目标函数 + + 基本的里程计目标函数: 位置i下观测到路标点j的 光度差异(直接法)或者几何差异(间接法,直接法) + + 语义匹配目标函数: 我们要衡量该姿态的相机观测得到的语义分类和地图的语义关系能多好地匹配。 + 匹配方式则是将地图的点,按照当前相机的姿态,投影到成像平面中(类似BA,只是BA比较的是RGB而已)。 + 对应成像平面的位置如果分类就是地图中点的分类,那就概率取高,那么如果不是呢,按照距离 给定得分 + + 判断投影过来的点与正确分类的距离,于是建了这么一张 + 距离变换 图(Distance transform ,DT变换图。)来表示,不用再挨个遍历去算。 + 而概率与距离的关系是用高斯分布建模。 + + 这篇文章主要利用语义约束解决(减少)SLAM在重建过程中由于误差累积造成的drift问题。 + 对于自动驾驶场景来说,由于直线道路比较多,所以更明显的改善表现在translational error上, + 对于rotational error的改善则比较有限。 + + 在视觉里程计中,有两种方法来减少drift:一种是使用图像间的短期(short-term) + 的correspondences在连续帧的图像中建立约束,进而纠正drift; + 另一种则是通过回环检测(loop closure)在间隔较长的帧中建立长期(long-term)的约束。 + 而VSO则通过利用语义约束对于点的中期(medium-term)的连续跟踪进行drift校正。 + + + +[双目语义3D物体跟踪 ](http://www.liuxiao.org/wp-content/uploads/2018/08/Stereo-Vision-based-Semantic-3D-Object-and-Ego-motion-Tracking-for-Autonomous-Driving.pdf) + + 港科大沈邵劼老师团队的最新文章,他们的 VINS 在 VIO 领域具有很不错的开创性成果。 + 现在他们切入自动驾驶领域做了这篇双目语义3D物体跟踪的工作,效果还是很不错的。 + 在沈老师看来,SLAM 是一个多传感器融合的框架,RGB、激光、语义、IMU、 + 码盘等等都是不同的观测,所以只要是解决关于定位的问题,SLAM 的框架都是一样适用的。 + 在这篇文章中,他们将不同物体看成不同的 Map,一边重建一边跟踪。 + 使用的跟踪方法仍然是传统的 Local Feature,而 VIO 作为世界坐标系的运动估计。 + 语义融合方面,他们构造了4个优化项. + + 思想和 mask-fuscision 类似,就是把 不同的物体当作 地图对象来进行跟踪和重建。!!!!! + + + +# 动态 语义 SLAM相关论文 + +[DynaSLAM: Tracking, Mapping and Inpainting in Dynamic Scenes MASK-RCNN语义分割 和多视角集合判断动态点 剔除 动态关键点](https://arxiv.org/pdf/1806.05620.pdf) + +[DynSLAM, Robust Dense Mapping for Large-Scale Dynamic Environments 语义分割&光流 ](http://www.cvlibs.net/publications/Barsan2018ICRA.pdf ) + +[DS-SLAM:A Semantic Visual SLAM towards Dynamic Environments 语义分割 & 运动一致性检测 & octomap](https://arxiv.org/pdf/1809.08379.pdf) + +[语义概率数据融合 语义slam](https://www.cis.upenn.edu/~kostas/mypub.dir/bowman17icra.pdf) +[博客解析](https://blog.csdn.net/crazydogg/article/details/82670046) + +[VSO: Visual Semantic Odometry 语义概率数据融合 ](https://demuc.de/papers/lianos2018vso.pdf) +[知乎论文解析](https://zhuanlan.zhihu.com/p/45689132) + +# 数学描述 + 路标点集合 L = {Lm} m=[1:M] + 传感器姿态序列 X = {xt} t=[1:T] + 传感器测量值 Z = {zk} k=[1:K] + + 数据关联 D = {(ak, bk)} k=[1:K] + 意义是 地zk次测量下 姿态 x_ak 和 路标点 L_bk 相关联 + 普通硬决策方法: + 先求得一个准确的 关联D D <---arg max log p(D|X,L,Z) + 取对数,仍然是正相关,[0,1] ---->映射到 [-无穷大,0] + 在使用这个关联D 来最大化 Z 得到最优 的 X,L + X,L <------ arg max p(Z|X,L,D) + 软决策,考虑不确定性:关联D 是由多种状态 叠加而成,是一个叠加状态,薛定鄂的猫 + 首先考虑所有 可能的 数据关联 D + 计算其数据分布 获得每一种关联 (ak, bk) 对应的概率 wij + 在多种数据关联下 最大化 Z + X,L <------ arg max sum(sum( wij * log p(zk|ak, bk))) + + + + +[参考](https://www.cnblogs.com/luyb/p/9430488.html) + + 这个问题的关键在于, + 一幅图像中可能检测出数个相同类别的目标物体, + 如何能够正确地将其对应于地图数据中已有的该类别的3D物体。 + + 下面列出几种有用的因素。 + + 较为准确的先验估计(姿态),比如通过IMU、GPS、里程计等。 + 能够得到VO和目标的准确位置,比如双目、深度摄像头、结合激光等。 + 地图中有很多(局部)唯一确定的路标物体。 + 考虑所有可能的数据关联。 + + 利用第一点,我们能够使用一些简单的方法建立数据关联,但此时仍需考虑错误关联的影响。 + + 利用第二点,我们能够准确地重建出语义目标的几何特性(空间位置、朝向等)。 + X-View: Graph-Based Semantic Multi-View Localization这篇文章将多帧的语义目标位置组合成图, + 利用图匹配算法求解相机在全局地图中的位置(只定位不建图)。 + + 利用第三点,我们能够方便地确定关联关系。比如,行车道上的交通指示牌结合文字OCR识别, + 能够唯一确定该路牌的位置,相当于一个全局观测。比如,考虑到交通指示牌相互之间的间距很大, + 在局部唯一,因此结合GPS和指示牌即可唯一确定该指示牌的位置。根据Mobileye的REM的专利描述,它们可能利用了该类信息。 + + [室内场景数据集 InteriorNet: Mega-scale Multi-sensor Photo-realistic Indoor Scenes Dataset](https://interiornet.org/) [多场景 数据集1 ](https://projects.asl.ethz.ch/datasets/doku.php?id=weedmap:remotesensing2018weedmap) @@ -8,6 +132,49 @@ [CMU 视觉定位数据集](http://www.europe.naverlabs.com/Research/Computer-Vision/Proxy-Virtual-Worlds) + + +# 基于视觉的 语义定位和建图 + + + 目标定义: + 位置 position + 方向 orientation 表面法线 surface normal 线方向 line direction + 类别 category + 大小 size + 编号 id + 连接关系 空间spatial、时间time + 建图 mapping: + 目标检测 : 基于关键帧 、 基于cnn + 目标跟踪 : 光流、关键帧上的 2d-2d跟踪、地图中的3d-3d跟踪 + 目标重建 : 2d检测框 计算3d目标点云、中心点、方向、尺寸、多帧匹配融合、3d目标连接关系 + 地图融合 : icp配准融合。。。 + 地图应用 : + 定位 localization: + 地图加载 : 3d语义目标、关键帧 、匹配的3dobjects + 新关键帧 目标检测 : + 目标级别的数据关联 : 先验值、概率分布、空间分布、icp + 跟踪: 2d 物体跟踪,pnp(2d-3d) 更新 和 添加新的目标 + 重定位: 关键帧选择 点/线特征、词带表示向量 物体分布图 数据关联后 全局优化 + 多传感器融合 + + +# 项目的一般思路。 +[参考](https://www.cnblogs.com/luyb/p/9124950.html) + + 1. 前期调研。 + 分析项目的产品化需求,输入输出,软硬件平台,以及相关(开源)算法的初步测试和分析。 + 2. 算法架构设计。 + 根据调研结果,大致确定算法模块的功能和具体实现方法。 + 3. 迭代开发。 + 开发过程中必然会碰到很多预料之外的问题。 + 如果有备案,那么尝试备案方案。如果遇到了原理性的问题,那么要修正和扩展架构。 + 3. 技术储备。 + 开发过程中要时刻注重新技术和新方法的储备。 + + + + ## 1. 用深度学习方法替换传统slam中的一个/几个模块: 特征提取,特征匹配,提高特征点稳定性,提取点线面等不同层级的特征点。 深度估计 diff --git a/vSLAM/ch9 project/readme.md b/vSLAM/ch9 project/readme.md new file mode 100644 index 00000000..a9a022d6 --- /dev/null +++ b/vSLAM/ch9 project/readme.md @@ -0,0 +1,94 @@ +# 工程结构 + 1. /bin 存放可执行的二进制文件 + 2. /include/myslam 存放slam工程模块的头文件,只要是.h 引用头文件时时 + 需写 include "myslam/xxx.h"不容易和其他库混淆 + 3. /src 存放源代码文件 主要是.cpp文件 + 4. /test 存放测试用的文件 也是 .cpp文件 + 5. /lib 存放编译好的库文件 + 6. /config 存放配置文件 + 7. /cmake_modules 存放第三方库的cmake文件 例如使用g2o eigen库时 + + +# 数据对象结构 + 0.1版本 类 + Frame 帧 Frame::Ptr frame + Camera 相机模型 Camera::Ptr camera_ + MapPoint 特征点/路标点 MapPoint::Ptr map_point + Map 管理特征点 保存所有的特征点/路标 和关键帧 + Config 提供配置参数 + + + +# CMakeLists.txt 编译文件 + CMAKE_MINIMUM_REQUIRED( VERSION 2.8 ) # 设定版本 + PROJECT( slam ) # 设定工程名 + SET( CMAKE_CXX_COMPILER "g++") # 设定编译器 + + # 设定 可执行 二进制文件 的目录========= + # 二进制就是可以直接运行的程序 + SET( EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) + + # 设定存放 编译出来 的库文件的目录===== + # 库文件呢,就是为这些二进制提供函数的啦 + SET( LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib) + # 并且把该目录设为 连接目录 + LINK_DIRECTORIES( ${PROJECT_SOURCE_DIR}/lib) + + # 设定头文件目录 + INCLUDE_DIRECTORIES( ${PROJECT_SOURCE_DIR}/include) + + # 增加子文件夹,也就是进入 源代码 文件夹继续构建 + ADD_SUBDIRECTORY( ${PROJECT_SOURCE_DIR}/src) + + # 增加一个可执行的二进制 + ADD_EXECUTABLE( main main.cpp ) + + +# 2d 点转 3d点 +```c + +// 定义点云类型 +typedef pcl::PointXYZRGBA PointT; # 点类型 +typedef pcl::PointCloud PointCloud; # 点云类型 + +// 相机内参 +const double camera_factor = 1000; // 深度值放大倍数 +const double camera_cx = 325.5; +const double camera_cy = 253.5; +const double camera_fx = 518.0; +const double camera_fy = 519.0; + + // 点云变量 + // 使用智能指针,创建一个空点云。这种指针用完会自动释放。 + PointCloud::Ptr cloud ( new PointCloud ); + // 遍历深度图 + for (int m = 0; m < depth.rows; m++) + for (int n=0; n < depth.cols; n++) + { + // 获取深度图中(m,n)处的值 + ushort d = depth.ptr(m)[n]; + // d 可能没有值,若如此,跳过此点 + if (d == 0) + continue; + // d 存在值,则向点云增加一个点 + PointT p; + + // 计算这个点的空间坐标 + p.z = double(d) / camera_factor; + p.x = (n - camera_cx) * p.z / camera_fx; + p.y = (m - camera_cy) * p.z / camera_fy; + + // 从rgb图像中获取它的颜色 + // rgb是三通道的BGR格式图,所以按下面的顺序获取颜色 + p.b = rgb.ptr(m)[n*3]; + p.g = rgb.ptr(m)[n*3+1]; + p.r = rgb.ptr(m)[n*3+2]; + + // 把p加入到点云中 + cloud->points.push_back( p ); + } + + + + +``` diff --git "a/vSLAM/ch9 project/\345\267\245\347\250\213\347\273\223\346\236\204.txt" "b/vSLAM/ch9 project/\345\267\245\347\250\213\347\273\223\346\236\204.txt" deleted file mode 100644 index c3bdbb34..00000000 --- "a/vSLAM/ch9 project/\345\267\245\347\250\213\347\273\223\346\236\204.txt" +++ /dev/null @@ -1,22 +0,0 @@ -1. /bin 存放可执行的二进制文件 -2. /include/myslam 存放slam工程模块的头文件,只要是.h 引用头文件时时 - 需写 include "myslam/xxx.h"不容易和其他库混淆 -3. /src 存放源代码文件 主要是.cpp文件 -4. /test 存放测试用的文件 也是 .cpp文件 -5. /lib 存放编译好的库文件 -6. /config 存放配置文件 -7. /cmake_modules 存放第三方库的cmake文件 例如使用g2o eigen库时 - - - -0.1版本 类 -Frame 帧 Frame::Ptr frame -Camera 相机模型 Camera::Ptr camera_ -MapPoint 特征点/路标点 MapPoint::Ptr map_point -Map 管理特征点 保存所有的特征点/路标 和关键帧 -Config 提供配置参数 - - - - - diff --git "a/vSLAM/ch9 project/\345\267\245\347\250\213\347\273\223\346\236\204.txt~" "b/vSLAM/ch9 project/\345\267\245\347\250\213\347\273\223\346\236\204.txt~" deleted file mode 100644 index 3cf9d2cd..00000000 --- "a/vSLAM/ch9 project/\345\267\245\347\250\213\347\273\223\346\236\204.txt~" +++ /dev/null @@ -1,22 +0,0 @@ -1. /bin 存放可执行的二进制文件 -2. /include/myslam 存放slam工程模块的头文件,只要是.h 引用头文件时时 - 需写 include "myslam/xxx.h"不容易和其他库混淆 -3. /src 存放源代码文件 主要是.cpp文件 -4. /test 存放测试用的文件 也是 .cpp文件 -5. /lib 存放编译好的库文件 -6. /config 存放配置文件 -7. /cmake_modules 存放第三方库的cmake文件 例如使用g2o eigen库时 - - - -0.1版本 类 -Frame 帧 -Camera 相机模型 -MapPoint 特征点/路标点 -Map 管理特征点 -Config 提供配置参数 - - - - - diff --git a/vSLAM/ch9project/orb-slam2.md b/vSLAM/ch9project/orb-slam2.md new file mode 100644 index 00000000..000fef92 --- /dev/null +++ b/vSLAM/ch9project/orb-slam2.md @@ -0,0 +1,696 @@ + + +# 1、ORBSLAM2 + ORBSLAM2在Ubuntu14.04上详细配置流程 + http://blog.csdn.net/zzlyw/article/details/54730830 + +## 1 安装必要工具 + 首先,有两个工具是需要提前安装的。即cmake和git。 + sudo apt-get install cmake + sudo apt-get install git + +## 2 安装Pangolin,用于可视化和用户接口 + Pangolin: https://github.com/stevenlovegrove/Pangolin + 官方样例demo https://github.com/stevenlovegrove/Pangolin/tree/master/examples + 安装文件夹内 + Pangolin函数的使用: + http://docs.ros.org/fuerte/api/pangolin_wrapper/html/namespacepangolin.html + + 是一款开源的OPENGL显示库,可以用来视频显示、而且开发容易。 + 是对OpenGL进行封装的轻量级的OpenGL输入/输出和视频显示的库。 + 可以用于3D视觉和3D导航的视觉图,可以输入各种类型的视频、并且可以保留视频和输入数据用于debug。 + + 安装依赖项: + http://www.cnblogs.com/liufuqiang/p/5618335.html Pangolin安装问题 + Glew: + sudo apt-get install libglew-dev + CMake: + sudo apt-get install cmake + Boost: + sudo apt-get install libboost-dev libboost-thread-dev libboost-filesystem-dev + Python2 / Python3: + sudo apt-get install libpython2.7-dev + sudo apt-get install build-essential + + 先转到一个要存储Pangolin的路径下,例如~/Documents,然后 + git clone https://github.com/stevenlovegrove/Pangolin.git + cd Pangolin + mkdir build + cd build + cmake .. + make -j + sudo make install + + + + +## 3 安装OpenCV + + 最低的OpenCV版本为2.4.3,建议采用OpenCV 2.4.11或者OpenCV 3.2.0。从OpenCV官网下载OpenCV2.4.11。然后安装依赖项: + + sudo apt-get install libgtk2.0-dev + sudo apt-get install pkg-config + + 将下载的OpenCV解压到自己的指定目录,然后cd到OpenCV的目录下。 + cd ~/Downloads/opencv-2.4.11 + mkdir release + cd release + cmake -D CMAKE_BUILD_TYPE=RELEASE -DCMAKE_INSTALL_PREFIX=/usr/local .. + make + sudo make install + + +## 4 安装Eigen3 + + 最低要求版本为3.1.0。在http://eigen.tuxfamily.org 下载Eigen3的最新版本, + 一般是一个压缩文件,下载后解压,然后cd到Eigen3的根目录下。 + + mkdir build + cd build + cmake .. + make + sudo make install + + +## 5 安装ORBSLAM2 + + 先转到自己打算存储ORBSLAM2工程的路径,然后执行下列命令 + git clone https://github.com/raulmur/ORB_SLAM2.git oRB_SLAM2 + cd ORB_SLAM2 + 修改编译 线程数(不然编译时可能会卡住): + vim build.sh + 最后 make -j >>> make -j4 + + sudo chmod 777 build.sh + ./build.sh + + + 之后会在lib文件夹下生成libORB_SLAM2.so, + 并且在Examples文件夹下生成 + mono_tum,mono_kitti, mono_euroc in Examples/Monocular 单目 , + rgbd_tum in Examples/Monocular RGB-D, + stereo_kitti 和 stereo_euroc in Examples/Stereo 双目立体。 + + +## 数据集: + KITTI dataset 对于 单目 stereo 或者 双目 monocular + http://www.cvlibs.net/datasets/kitti/eval_odometry.php + + EuRoC dataset 对于 单目 stereo 或者 双目 monocular + http://projects.asl.ethz.ch/datasets/doku.php?id=kmavvisualinertialdatasets + + TUM dataset 对于 RGB-D 或者 单目monocular + https://vision.in.tum.de/data/datasets/rgbd-dataset + + +## 论文: +ORB-SLAM: +[Monocular] Raúl Mur-Artal, J. M. M. Montiel and Juan D. Tardós. ORB-SLAM: A Versatile and Accurate Monocular SLAM System. +IEEE Transactions on Robotics, vol. 31, no. 5, pp. 1147-1163, 2015. (2015 IEEE Transactions on Robotics Best Paper Award). +http://webdiis.unizar.es/%7Eraulmur/MurMontielTardosTRO15.pdf + +ORB-SLAM2: +[Stereo and RGB-D] Raúl Mur-Artal and Juan D. Tardós. ORB-SLAM2: an Open-Source SLAM System for Monocular, Stereo and RGB-D Cameras. +IEEE Transactions on Robotics, vol. 33, no. 5, pp. 1255-1262, 2017. +https://128.84.21.199/pdf/1610.06475.pdf + +词袋模型: +[DBoW2 Place Recognizer] Dorian Gálvez-López and Juan D. Tardós. Bags of Binary Words for Fast Place Recognition in Image Sequences. +IEEE Transactions on Robotics, vol. 28, no. 5, pp. 1188-1197, 2012. +http://doriangalvez.com/papers/GalvezTRO12.pdf + + +## 单目测试 + 在http://vision.in.tum.de/data/datasets/rgbd-dataset/download下载一个序列,并解压。 + 转到ORBSLAM2文件夹下,执行下面的命令。 + 根据下载的视频序列freiburg1, freiburg2 和 freiburg3将TUMX.yaml分别转换为对应的 TUM1.yaml 或 TUM2.yaml 或 TUM3.yaml + (相机参数文件)。 + 将PATH_TO_SEQUENCE_FOLDER 更改为解压的视频序列文件夹。 + ./Examples/Monocular/mono_tum Vocabulary/ORBvoc.txt Examples/Monocular/TUMX.yaml PATH_TO_SEQUENCE_FOLDER + 解压的视频序列文件夹 + +## 双目测试 + 在 http://projects.asl.ethz.ch/datasets/doku.php?id=kmavvisualinertialdatasets 下载一个序列 Vicon Room 1 02 大小1.2GB + ./Examples/Stereo/stereo_euroc Vocabulary/ORBvoc.txt Examples/Stereo/EuRoC.yaml PATH_TO_SEQUENCE/cam0/data PATH_TO_SEQUENCE/cam1/data Examples/Stereo/EuRoC_TimeStamps/SEQUENCE.txt + + +################################### +# 词带 + + orb词带txt载入太慢,看到有人转换为binary,速度超快,试了下,确实快. +链接:https://github.com/raulmur/ORB_SLAM2/pull/21/commits/4122702ced85b20bd458d0e74624b9610c19f8cc +Vocabulary/ORBvoc.txt >>> Vocabulary/ORBvoc.bin +################################################################ + +# CMakeLists.txt + 最后添加 + ## .txt >>> .bin 文件转换 + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/tools) + add_executable(bin_vocabulary + tools/bin_vocabulary.cc) + target_link_libraries(bin_vocabulary ${PROJECT_NAME}) + +# build.sh 转换 .txt >>> .bin + 最后添加 + cd .. + echo "Converting vocabulary to binary" + ./tools/bin_vocabulary + +#### 新建转换文件 + tools/bin_vocabulary.cc + + #include + #include "ORBVocabulary.h" + using namespace std; + + bool load_as_text(ORB_SLAM2::ORBVocabulary* voc, const std::string infile) { + clock_t tStart = clock(); + bool res = voc->loadFromTextFile(infile); + printf("Loading fom text: %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); + return res; + } + + void load_as_xml(ORB_SLAM2::ORBVocabulary* voc, const std::string infile) { + clock_t tStart = clock(); + voc->load(infile); + printf("Loading fom xml: %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); + } + + void load_as_binary(ORB_SLAM2::ORBVocabulary* voc, const std::string infile) { + clock_t tStart = clock(); + voc->loadFromBinaryFile(infile); + printf("Loading fom binary: %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); + } + + void save_as_xml(ORB_SLAM2::ORBVocabulary* voc, const std::string outfile) { + clock_t tStart = clock(); + voc->save(outfile); + printf("Saving as xml: %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); + } + + void save_as_text(ORB_SLAM2::ORBVocabulary* voc, const std::string outfile) { + clock_t tStart = clock(); + voc->saveToTextFile(outfile); + printf("Saving as text: %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); + } + + void save_as_binary(ORB_SLAM2::ORBVocabulary* voc, const std::string outfile) { + clock_t tStart = clock(); + voc->saveToBinaryFile(outfile); + printf("Saving as binary: %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); + } + + int main(int argc, char **argv) { + cout << "BoW load/save benchmark" << endl; + ORB_SLAM2::ORBVocabulary* voc = new ORB_SLAM2::ORBVocabulary(); + + load_as_text(voc, "Vocabulary/ORBvoc.txt"); + save_as_binary(voc, "Vocabulary/ORBvoc.bin"); + + return 0; + } + + 修改读入文件: + Thirdparty/DBoW2/DBoW2/TemplatedVocabulary.h + line 248 + 添加 + // WYW ADD 2017.11.4 + /** + * Loads the vocabulary from a Binary file + * @param filename + */ + bool loadFromBinaryFile(const std::string &filename); + + /** + * Saves the vocabulary into a Binary file + * @param filename + */ + void saveToBinaryFile(const std::string &filename) const; + + + line 1460 + // WYW ADD 2017.11.4 读取二进制 词带 + // -------------------------------------------------------------------------- + template + bool TemplatedVocabulary::loadFromBinaryFile(const std::string &filename) { + fstream f; + f.open(filename.c_str(), ios_base::in|ios::binary); + unsigned int nb_nodes, size_node; + f.read((char*)&nb_nodes, sizeof(nb_nodes)); + f.read((char*)&size_node, sizeof(size_node)); + f.read((char*)&m_k, sizeof(m_k)); + f.read((char*)&m_L, sizeof(m_L)); + f.read((char*)&m_scoring, sizeof(m_scoring)); + f.read((char*)&m_weighting, sizeof(m_weighting)); + createScoringObject(); + + m_words.clear(); + m_words.reserve(pow((double)m_k, (double)m_L + 1)); + m_nodes.clear(); + m_nodes.resize(nb_nodes+1); + m_nodes[0].id = 0; + char buf[size_node]; int nid = 1; + while (!f.eof()) { + f.read(buf, size_node); + m_nodes[nid].id = nid; + // FIXME + const int* ptr=(int*)buf; + m_nodes[nid].parent = *ptr; + //m_nodes[nid].parent = *(const int*)buf; + m_nodes[m_nodes[nid].parent].children.push_back(nid); + m_nodes[nid].descriptor = cv::Mat(1, F::L, CV_8U); + memcpy(m_nodes[nid].descriptor.data, buf+4, F::L); + m_nodes[nid].weight = *(float*)(buf+4+F::L); + if (buf[8+F::L]) { // is leaf + int wid = m_words.size(); + m_words.resize(wid+1); + m_nodes[nid].word_id = wid; + m_words[wid] = &m_nodes[nid]; + } + else + m_nodes[nid].children.reserve(m_k); + nid+=1; + } + f.close(); + return true; + } + + // -------------------------------------------------------------------------- + template + void TemplatedVocabulary::saveToBinaryFile(const std::string &filename) const { + fstream f; + f.open(filename.c_str(), ios_base::out|ios::binary); + unsigned int nb_nodes = m_nodes.size(); + float _weight; + unsigned int size_node = sizeof(m_nodes[0].parent) + F::L*sizeof(char) + sizeof(_weight) + sizeof(bool); + f.write((char*)&nb_nodes, sizeof(nb_nodes)); + f.write((char*)&size_node, sizeof(size_node)); + f.write((char*)&m_k, sizeof(m_k)); + f.write((char*)&m_L, sizeof(m_L)); + f.write((char*)&m_scoring, sizeof(m_scoring)); + f.write((char*)&m_weighting, sizeof(m_weighting)); + for(size_t i=1; i + bool has_suffix(const std::string &str, const std::string &suffix) { + std::size_t index = str.find(suffix, str.size() - suffix.size()); + return (index != std::string::npos); + } + + line 68 + /////// //////////////////////////////////// + //// wyw 修改 2017.11.4 + clock_t tStart = clock(); + mpVocabulary = new ORBVocabulary(); + //bool bVocLoad = mpVocabulary->loadFromTextFile(strVocFile); + bool bVocLoad = false; // chose loading method based on file extension + if (has_suffix(strVocFile, ".txt")) + bVocLoad = mpVocabulary->loadFromTextFile(strVocFile);//txt格式打开 + else + bVocLoad = mpVocabulary->loadFromBinaryFile(strVocFile);//bin格式打开 + + if(!bVocLoad) + { + cerr << "Wrong path to vocabulary. " << endl; + cerr << "Failed to open at: " << strVocFile << endl; + exit(-1); + } + //cout << "Vocabulary loaded!" << endl << endl; + printf("Vocabulary loaded in %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);//显示文件载入时间 + + + + + 单目SLAM: + 例如,我自己的电脑上,该命令变为: + ./Examples/Monocular/mono_tum Vocabulary/ORBvoc.txt Examples/Monocular/TUM1.yaml /home/ewenwan/ewenwan/learn/vSLAM/test/vSLAM/ch9project/date/rgbd_dataset_freiburg1_xyz + + 载入二进制词带 + ./Examples/Monocular/mono_tum Vocabulary/ORBvoc.bin Examples/Monocular/TUM1.yaml /home/ewenwan/ewenwan/learn/vSLAM/test/vSLAM/ch9project/date/rgbd_dataset_freiburg1_xyz + + + + 双目测试 + ./Examples/Stereo/stereo_euroc Vocabulary/ORBvoc.txt Examples/Stereo/EuRoC.yaml /home/ewenwan/ewenwan/learn/vSLAM/test/vSLAM/ch9project/date/ /cam0/data /home/ewenwan/ewenwan/learn/vSLAM/test/vSLAM/ch9project/date/ /cam1/data Examples/Stereo/EuRoC_TimeStamps/V102.txt + 载入二进制词带 + ./Examples/Stereo/stereo_euroc Vocabulary/ORBvoc.bin Examples/Stereo/EuRoC.yaml /home/ewenwan/ewenwan/learn/vSLAM/test/vSLAM/ch9project/date/ /cam0/data /home/ewenwan/ewenwan/learn/vSLAM/test/vSLAM/ch9project/date/ /cam1/data Examples/Stereo/EuRoC_TimeStamps/V102.txt + + + ros下的工程: + http://blog.csdn.net/sinat_31802439/article/details/52331465 添加稠密地图 + https://pan.baidu.com/s/1miDA952 + + + manifest.xml >>>> package.xml + + + + ros_orb #####包名 + 0.0.1 #####版本 + ORB_SLAM2#####工程描述 + EWenWan ####作者 + Raul Mur-Artal##### 维护 + GPLv3 ####开源协议 + + catkin #### 编译工具以来 + + roscpp #### 编译依赖 + pcl + tf + sensor_msgs + image_transport + message_filters + cv_bridge + cmake_modules + + roscpp #### 运行依赖 + pcl + tf + sensor_msgs + image_transport + message_filters + cv_bridge + + + + + 编译信息文件 + CMakeLists.txt + + cmake_minimum_required(VERSION 2.8.3) ### cmake版本限制 + + project(ros_orb)##工程名 + find_package(catkin REQUIRED COMPONENTS###依赖包 + roscpp + sensor_msgs + image_transport + message_filters + cv_bridge + cmake_modules) + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -O3 -march=native ") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -O3 -march=native") + + ### ORB_SLAM2的路径 + set(CODE_SOURCE_DIR /home/ewenwan/ewenwan/learn/vSLAM/test/vSLAM/ch9project/oRB_SLAM2/Examples/ROS/ORB_SLAM2) + + # Check C++11 or C++0x support + include(CheckCXXCompilerFlag) + CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) + CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) + if(COMPILER_SUPPORTS_CXX11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + add_definitions(-DCOMPILEDWITHC11) + message(STATUS "Using flag -std=c++11.") + elseif(COMPILER_SUPPORTS_CXX0X) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") + add_definitions(-DCOMPILEDWITHC0X) + message(STATUS "Using flag -std=c++0x.") + else() + message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") + endif() + + + LIST(APPEND CMAKE_MODULE_PATH ${CODE_SOURCE_DIR}/../../../cmake_modules)## ORB_SLAM2的编译文件 FindEigen3.cmake + + find_package(OpenCV 2.4.3 REQUIRED) + find_package(Eigen3 3.1.0 REQUIRED) + find_package(Pangolin REQUIRED) + find_package( G2O REQUIRED ) + find_package( PCL 1.7 REQUIRED ) + + catkin_package() ###ros包类型说明 + + include_directories( + ${CODE_SOURCE_DIR} ### ORB_SLAM2的路径 + ${CODE_SOURCE_DIR}/../../../ + ${CODE_SOURCE_DIR}/../../../include + ${Pangolin_INCLUDE_DIRS} + ${PCL_INCLUDE_DIRS} + ${EIGEN3_INCLUDE_DIR} + ) + add_definitions( ${PCL_DEFINITIONS} ) + link_directories( ${PCL_LIBRARY_DIRS} ) + + set(LIBS + ${catkin_LIBRARIES} + ${OpenCV_LIBS} + ${EIGEN3_LIBS} + ${PCL_LIBRARIES} + ${Pangolin_LIBRARIES} + ${CODE_SOURCE_DIR}/../../../Thirdparty/DBoW2/lib/libDBoW2.so + #g2o_core g2o_types_slam3d g2o_solver_csparse g2o_stuff g2o_csparse_extension g2o_types_sim3 g2o_types_sba + ${CODE_SOURCE_DIR}/../../../Thirdparty/g2o/lib/libg2o.so + ${CODE_SOURCE_DIR}/../../../lib/libORB_SLAM2.so + ) + + # Node for monocular camera 单目相机 + add_executable(mono + src/ros_mono.cc + ) + target_link_libraries(mono + ${LIBS} + ) + # 单目相机 Augmented Reality 增强现实 + #add_executable(monoAR + #src/AR/ros_mono_ar.cc + #src/AR/ViewerAR.h + #src/AR/ViewerAR.cc + #) + #target_link_libraries(mono + #${LIBS} + #) + + # Node for RGB-D camera 深度相机 + add_executable(rgbd + src/ros_rgbd.cc + ) + target_link_libraries(rgbd + ${LIBS} + ) + + # Node for stereo camera 双目立体相机 + add_executable(stereo + src/ros_stereo.cc + ) + target_link_libraries(stereo + ${LIBS} + ) + + cd catkin_ws + catkin_make + + 运行单目相机SLAM节点 + rosrun ros_orb mono Vocabulary/ORBvoc.bin Examples/Monocular/TUM1.yaml /home/ewenwan/ewenwan/learn/vSLAM/test/vSLAM/ch9project/date/rgbd_dataset_freiburg1_xyz + + + + + ################# + ######################## + lsd-slam 直接法稠密点云slam Large Scale Direct Monocular + ######################################## + #################### + + http://www.luohanjie.com/2017-03-17/ubuntu-install-lsd-slam.html + https://vision.in.tum.de/research/vslam/lsdslam + https://www.cnblogs.com/hitcm/p/4907536.html + https://github.com/tum-vision/lsd_slam + + + 官方编译方法[1] + rosmake 编译 + sudo apt-get install python-rosinstall + sudo apt-get install ros-indigo-libg2o ros-indigo-cv-bridge liblapack-dev libblas-dev freeglut3-dev libqglviewer-dev libsuitesparse-dev libx11-dev + mkdir ~/SLAM/Code/rosbuild_ws + cd ~/SLAM/Code/rosbuild_ws + roses init . /opt/ros/indigo + mkdir package_dir + roses set ~/SLAM/Code/rosbuild_ws/package_dir -t . + echo "source ~/SLAM/Code/rosbuild_ws/setup.bash" >> ~/.bashrc + bash + cd package_dir + git clone https://github.com/tum-vision/lsd_slam.git lsd_slam + rosmake lsd_slam + + + 使用catkin对LSD-SLAM进行编译 + + mkdir -p ~/catkin_ws/src + git clone https://github.com/tum-vision/lsd_slam.git + cd lsd_slam + git checkout catkin + + 对lsd_slam/lsd_slam_viewer和lsd_slam/lsd_slam_core文件夹下的package.xml中添加: + cmake_modules + cmake_modules + + 对lsd_slam/lsd_slam_viewer和lsd_slam/lsd_slam_core文件夹下的CMakeFiles.txt中添加: + find_package(cmake_modules REQUIRED) + find_package(OpenCV 3.0 QUIET) #support opencv3 + if(NOT OpenCV_FOUND) + find_package(OpenCV 2.4.3 QUIET) + if(NOT OpenCV_FOUND) + message(FATAL_ERROR "OpenCV > 2.4.3 not found.") + endif() + endif() + + + 并且在所有的target_link_libraries中添加X11 ${OpenCV_LIBS},如: + target_link_libraries(lsdslam + ${FABMAP_LIB} + ${G2O_LIBRARIES} + ${catkin_LIBRARIES} + ${OpenCV_LIBS} + sparse cxsparse X11 + ) + + 然后开始编译: + cd ~/catkin_ws/ + catkin_make + + + 下载测试数据 474MB 日志回放 + vmcremers8.informatik.tu-muenchen.de/lsd/LSD_room.bag.zip + 解压 + + 打开一个终端: + roscoe + + 打开另外一个终端: + cd ~/catkin_ws/ + source devel/setup.sh + rosrun lsd_slam_viewer viewer + + 打开另外一个终端: + cd ~/catkin_ws/ + source devel/setup.sh + rosrun lsd_slam_core live_slam image:=/image_raw camera_info:=/camera_info + + 打开另外一个终端: + cd ~/catkin_ws/ + rosbag play ~/LSD_room.bag ###回放日志 即将之前的数据按话题发布 + + + + + + 使用摄像头运行LSD_SLAM + 安装驱动[4]: + cd ~/catkin_ws/ + source devel/setup.sh + cd ~/catkin_ws/src + git clone https://github.com/ktossell/camera_umd.git + cd .. + catkin_make + roscd uvc_camera/launch/ + roslaunch ./camera_node.launch + + camera_node.launch文件[5],如: + + + + + + + + + + + + + + + + + + 注意官方程序默认分辨率为640*480。 + + 打开一个窗口 + 运行roscore; + + 打开另外一个窗口: + cd ~/catkin_ws/ + source devel/setup.sh + rosrun lsd_slam_viewer viewer + + + 再打开另外一个窗口: + cd ~/catkin_ws/ + source devel/setup.sh + roslaunch uvc_camera camera_node.launch + + 再打开另外一个窗口: + rosrun lsd_slam_core live_slam /image:=image_raw _calib:= + 校正文件calibration_file可参考lsd_catkin_ws/src/lsd_slam/lsd_slam_core/calib中的cfg文件。 + + + + ########################### + ################################# + ##################################### + DSO: Direct Sparse Odometry 直接法稀疏点云 SLAM + https://github.com/JakobEngel/dso + + + 1.下载DSO源代码到相应文件路径,比如我的文件路径为/home/hyj/DSO + git clone https://github.com/JakobEngel/dso dso + 2.安装suitesparse and eigen3 (必需) + sudo apt-get install libsuitesparse-dev libeigen3-dev + + 3.安装opencv. DSO对opencv依赖很少,仅仅用于读或写图像等一些简单的操作。 + sudo apt-get install libopencv-dev + + 4.安装pangolin. 强烈推荐安装,考虑到ORB_SLAM中也选择pangolin作为显 示工具,而使用也非常方便,因此建议大家学习。 安装教程请移步pangolin的github主页 + + 5.安装ziplib. 建议安装,DSO用这个库来解压读取数据集压缩包中的图片,这样就不要每次都把下再的图片数据集进行解压了。 + sudo apt-get install zlib1g-dev + cd thirdparty #找到DSO所在文件路径,切换到thirdparty文件夹下 + tar -zxvf libzip-1.1.1.tar.gz + cd libzip-1.1.1/./configure + make + sudo make install + sudo cp lib/zipconf.h /usr/local/include/zipconf.h + + 6.编译DSO. + cd /home/hyj/DSO/dso + mkdir build + cd build + cmake .. + make -j + 至此,不出意外的话,我们就可以很顺利的完成了DOS的安装。 + + + + + + + + + + ############################## + ################################### + Pangolin 可视化库的使用 + 参考地址: + 【1】Pangolin:https://github.com/stevenlovegrove/Pangolin + 【2】Pangolin安装问题:http://www.cnblogs.com/liufuqiang/p/5618335.html + 【3】Pangolin的Example:https://github.com/stevenlovegrove/Pangolin/tree/master/examples + 【4】Pangolin的使用:http://docs.ros.org/fuerte/api/pangolin_wrapper/html/namespacepangolin.html + 【5】特性:http://www.stevenlovegrove.com/?id=44 + + https://www.cnblogs.com/shhu1993/p/6814714.html + + + diff --git a/vSLAM/ch9project/readme.md b/vSLAM/ch9project/readme.md new file mode 100644 index 00000000..193dfbca --- /dev/null +++ b/vSLAM/ch9project/readme.md @@ -0,0 +1,2309 @@ + +# rgbd-slam 第一版 +[rgbd-slam 第二版](https://github.com/Ewenwan/rgbd-slam-tutor2/blob/master/README.md) + +# 工程结构 + 1. /bin 存放可执行的二进制文件 + 2. /include/myslam 存放slam工程模块的头文件,只要是.h 引用头文件时时 + 需写 include "myslam/xxx.h"不容易和其他库混淆 + 3. /src 存放源代码文件 主要是.cpp文件 + 4. /test 存放测试用的文件 也是 .cpp文件 + 5. /lib 存放编译好的库文件 + 6. /config 存放配置文件 + 7. /cmake_modules 存放第三方库的cmake文件 例如使用g2o eigen库时 + + +# 数据对象结构 + 0.1版本 类 + Frame 帧 Frame::Ptr frame + Camera 相机模型 Camera::Ptr camera_ + MapPoint 特征点/路标点 MapPoint::Ptr map_point + Map 管理特征点 保存所有的特征点/路标 和关键帧 + Config 提供配置参数 + + + +# CMakeLists.txt 编译文件 + CMAKE_MINIMUM_REQUIRED( VERSION 2.8 ) # 设定版本 + PROJECT( slam ) # 设定工程名 + SET( CMAKE_CXX_COMPILER "g++") # 设定编译器 + + # 设定 可执行 二进制文件 的目录========= + # 二进制就是可以直接运行的程序 + SET( EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) + + # 设定存放 编译出来 的库文件的目录===== + # 库文件呢,就是为这些二进制提供函数的啦 + SET( LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib) + # 并且把该目录设为 连接目录 + LINK_DIRECTORIES( ${PROJECT_SOURCE_DIR}/lib) + + # 设定头文件目录 + INCLUDE_DIRECTORIES( ${PROJECT_SOURCE_DIR}/include) + + # 增加子文件夹,也就是进入 源代码 文件夹继续构建 + ADD_SUBDIRECTORY( ${PROJECT_SOURCE_DIR}/src) + + # 增加一个可执行的二进制 + ADD_EXECUTABLE( main main.cpp ) + + # ========================================= + # 增加PCL库的依赖 + FIND_PACKAGE( PCL REQUIRED COMPONENTS common io ) + + # 增加opencv的依赖 + FIND_PACKAGE( OpenCV REQUIRED ) + + # 添加头文件和库文件 + ADD_DEFINITIONS( ${PCL_DEFINITIONS} ) + INCLUDE_DIRECTORIES( ${PCL_INCLUDE_DIRS} ) + LINK_LIBRARIES( ${PCL_LIBRARY_DIRS} ) + + ADD_EXECUTABLE( generate_pointcloud generatePointCloud.cpp ) + TARGET_LINK_LIBRARIES( generate_pointcloud ${OpenCV_LIBS} + ${PCL_LIBRARIES} ) + + + # 自检函数库======= + # 最后,在 src/CMakeLists.txt 中加入以下几行,将 slamBase.cpp 编译成一个库,供将来调用: + + ADD_LIBRARY( slambase slamBase.cpp ) + TARGET_LINK_LIBRARIES( slambase + ${OpenCV_LIBS} + ${PCL_LIBRARIES} ) + +# RGBD SLAM 工程 记录 +[rgbdslam_v2 参考](https://github.com/Ewenwan/rgbdslam_v2) + +[高翔博士 博客](https://www.cnblogs.com/gaoxiang12/p/4669490.html) + +[高翔博士代码](https://github.com/gaoxiang12/rgbd-slam-tutorial-gx) + + +# 2d 点转 3d点 函数 +```c +// generatePointCloud.cpp +// https://www.cnblogs.com/gaoxiang12/p/4652478.html + +// 部分头文件省略 +// 定义点云类型 +typedef pcl::PointXYZRGBA PointT; # 点类型 +typedef pcl::PointCloud PointCloud; # 点云类型 + +/* + +我们使用OpenCV的imread函数读取图片。在OpenCV2里,图像是以矩阵(cv::MAt)作为基本的数据结构。 +Mat结构既可以帮你管理内存、像素信息,还支持一些常见的矩阵运算,是非常方便的结构。 +彩色图像含有R,G,B三个通道,每个通道占8个bit(也就是unsigned char),故称为8UC3(8位unsigend char, 3通道)结构。 +而深度图则是单通道的图像,每个像素由16个bit组成(也就是C++里的unsigned short),像素的值代表该点离传感器的距离。 +通常1000的值代表1米,所以我们把camera_factor设置成1000. +这样,深度图里每个像素点的读数除以1000,就是它离你的真实距离了。 + +*/ + + +// 相机内参 +const double camera_factor = 1000; // 深度值放大倍数 +const double camera_cx = 325.5; +const double camera_cy = 253.5; +const double camera_fx = 518.0; +const double camera_fy = 519.0; + + // 点云变量 + // 使用智能指针,创建一个空点云。这种指针用完会自动释放。 + PointCloud::Ptr cloud ( new PointCloud ); + // 遍历深度图 + // 按照“先列后行”的顺序,遍历了整张深度图。 + for (int m = 0; m < depth.rows; m++) // 每一行 + for (int n=0; n < depth.cols; n++) // 每一列 + { + // 获取深度图中(m,n)处的值 + ushort d = depth.ptr(m)[n]; + // 深度图第m行,第n行的数据可以使用depth.ptr(m) [n]来获取。 + // 其中,cv::Mat的ptr函数会返回指向该图像第m行数据的头指针。 + // 然后加上位移n后,这个指针指向的数据就是我们需要读取的数据啦。 + + + + // d 可能没有值,若如此,跳过此点 + if (d == 0) + continue; + // d 存在值,则向点云增加一个点 + PointT p; + + // 计算这个点的空间坐标 + p.z = double(d) / camera_factor; + p.x = (n - camera_cx) * p.z / camera_fx; + p.y = (m - camera_cy) * p.z / camera_fy; + + // 从rgb图像中获取它的颜色 + // rgb是三通道的BGR格式图,所以按下面的顺序获取颜色 + p.b = rgb.ptr(m)[n*3]; + p.g = rgb.ptr(m)[n*3+1]; + p.r = rgb.ptr(m)[n*3+2]; + + // 把p加入到点云中 + cloud->points.push_back( p ); + } +``` + + +# 2d 点转 3d点 函数 封装成库 + +```c +// include/slamBase.h 库头文件 +/************************************************************************* + > File Name: rgbd-slam-tutorial-gx/part III/code/include/slamBase.h + > Author: xiang gao + > Mail: gaoxiang12@mails.tsinghua.edu.cn + > Created Time: 2015年07月18日 星期六 15时14分22秒 + > 说明:rgbd-slam教程所用到的基本函数(C风格) + ************************************************************************/ +# pragma once + +// 各种头文件 +// C++标准库 +#include +#include +using namespace std; + +// OpenCV +#include +#include + +//PCL +#include +#include + +// 类型定义 +typedef pcl::PointXYZRGBA PointT; +typedef pcl::PointCloud PointCloud; + +// 相机内参结构=============================== +// 把相机参数封装成了一个结构体, +struct CAMERA_INTRINSIC_PARAMETERS +{ + double cx, cy, fx, fy, scale; +}; + +// 另外还声明了 image2PointCloud 和 point2dTo3d 两个函数 +// 函数接口 +// image2PonitCloud 将rgb图转换为点云 +PointCloud::Ptr image2PointCloud( cv::Mat& rgb, cv::Mat& depth, CAMERA_INTRINSIC_PARAMETERS& camera ); + +// point2dTo3d 将单个点从图像坐标转换为空间坐标 +// input: 3维点Point3f (u,v,d) +cv::Point3f point2dTo3d( cv::Point3f& point, CAMERA_INTRINSIC_PARAMETERS& camera ); + +``` + +```c +// src/slamBase.cpp +/************************************************************************* + > File Name: src/slamBase.cpp + > Author: xiang gao + > Mail: gaoxiang12@mails.tsinghua.edu.cn + > Implementation of slamBase.h + > Created Time: 2015年07月18日 星期六 15时31分49秒 + ************************************************************************/ + +#include "slamBase.h" +// image2PonitCloud 将rgb图转 换为 点云==================== +PointCloud::Ptr image2PointCloud( cv::Mat& rgb, cv::Mat& depth, CAMERA_INTRINSIC_PARAMETERS& camera ) +{ + PointCloud::Ptr cloud ( new PointCloud ); + + for (int m = 0; m < depth.rows; m++) + for (int n=0; n < depth.cols; n++) + { + // 获取深度图中(m,n)处的值 + ushort d = depth.ptr(m)[n]; + // d 可能没有值,若如此,跳过此点 + if (d == 0) + continue; + // d 存在值,则向点云增加一个点 + PointT p; + + + +// 小萝卜2号:关于图像上下翻转问题,是因为opencv定义的坐标系和pcl_viewer显示坐标系不同,opencv是x右y下,而pcl显示是x右y上。 +// 解决方法:找到群主程序image2PointCloud函数中,把计算点空间坐标的公式的p.y值添加负号, +// 这样y方向就可以正常显示了,so easy。(或许还有别的方法) + + // 计算这个点的空间坐标 + p.z = double(d) / camera.scale; + p.x = (n - camera.cx) * p.z / camera.fx; + p.y = (m - camera.cy) * p.z / camera.fy; + + // 从rgb图像中获取它的颜色 + // rgb是三通道的BGR格式图,所以按下面的顺序获取颜色 + p.b = rgb.ptr(m)[n*3]; + p.g = rgb.ptr(m)[n*3+1]; + p.r = rgb.ptr(m)[n*3+2]; + + + + // 把p加入到点云中 + cloud->points.push_back( p ); + } + // 设置并保存点云 + cloud->height = 1; + cloud->width = cloud->points.size(); + cloud->is_dense = false; + + return cloud; +} +// point2dTo3d 将单个点从图像坐标转换为空间坐标 +// input: 3维点Point3f (u,v,d) +cv::Point3f point2dTo3d( cv::Point3f& point, CAMERA_INTRINSIC_PARAMETERS& camera ) +{ + cv::Point3f p; // 3D 点 + p.z = double( point.z ) / camera.scale; + p.x = ( point.x - camera.cx) * p.z / camera.fx; + p.y = ( point.y - camera.cy) * p.z / camera.fy; + return p; +} + + + +``` + + # 自检函数库======= + # 最后,在 src/CMakeLists.txt 中加入以下几行,将 slamBase.cpp 编译成一个库,供将来调用: + + ADD_LIBRARY( slambase slamBase.cpp ) + TARGET_LINK_LIBRARIES( slambase + ${OpenCV_LIBS} + ${PCL_LIBRARIES} ) + + + +# 图像配准 数学部分 3d-3d配准 + 用基于特征的方法(feature-based)或直接的方法(direct method)来解。 + 虽说直接法已经有了一定的发展,但目前主流的方法还是基于特征点的方式。 + 在后者的方法中,首先你需要知道图像里的“特征”,以及这些特征的一一对应关系。 + + 假设我们有两个帧:F1和F2. 并且,我们获得了两组一一对应的 特征点: + P={p1,p2,…,pN}∈F1 + Q={q1,q2,…,qN}∈F2 + 其中p和q都是 R3 中的点。 + + 我们的目的是求出一个旋转矩阵R和位移矢量t,使得: + ∀i, pi = R*qi + t + + 然而实际当中由于误差的存在,等号基本是不可能的。所以我们通过最小化一个误差来求解R,t: +  min R,t ∑i=1/N * ∥pi−(R*qi + t)∥2 +   这个问题可以用经典的ICP算法求解。其核心是奇异值分解(SVD)。 + 我们将调用OpenCV中的函数求解此问题, + + 那么从这个数学问题上来讲,我们的关键就是要获取一组一一对应的空间点, + 这可以通过图像的特征匹配来完成。   + 提示:由于OpenCV中没有提供ICP,我们在实现中使用PnP进行求解。 2d-3d +# 配准编程 +```c +// detectFeatures.cpp +/************************************************************************* + > File Name: detectFeatures.cpp + > Author: xiang gao + > Mail: gaoxiang12@mails.tsinghua.edu.cn + > 特征提取与匹配 + > Created Time: 2015年07月18日 星期六 16时00分21秒 + ************************************************************************/ + +#include +#include "slamBase.h" +using namespace std; + +// OpenCV 特征检测模块 +#include +// #include // use this if you want to use SIFT or SURF +#include + +int main( int argc, char** argv ) +{ + // 声明并从data文件夹里读取两个rgb与深度图 + cv::Mat rgb1 = cv::imread( "./data/rgb1.png"); + cv::Mat rgb2 = cv::imread( "./data/rgb2.png"); + cv::Mat depth1 = cv::imread( "./data/depth1.png", -1); + cv::Mat depth2 = cv::imread( "./data/depth2.png", -1); + + // 声明特征提取器 与 描述子提取器 + cv::Ptr detector; + cv::Ptr descriptor; + + // 构建提取器,默认两者都为 ORB + + // 如果使用 sift, surf ,之前要初始化nonfree模块========= + // cv::initModule_nonfree(); + // _detector = cv::FeatureDetector::create( "SIFT" ); + // _descriptor = cv::DescriptorExtractor::create( "SIFT" ); + + detector = cv::FeatureDetector::create("ORB"); + descriptor = cv::DescriptorExtractor::create("ORB"); + +// 使用 _detector->detect()函数提取关键点============================== + // 关键点是一种cv::KeyPoint的类型。 + // 带有 Point2f pt 这个成员变量,指这个关键点的像素坐标。 + + // kp1[i].pt 获取 这个关键点的像素坐标 (u,v) ================== + + // 此外,有的关键点还有半径、角度等参数,画在图里就会像一个个的圆一样。 + vector< cv::KeyPoint > kp1, kp2; // 关键点 + detector->detect( rgb1, kp1 ); // 提取关键点 + detector->detect( rgb2, kp2 ); + + cout<<"Key points of two images: "<compute( rgb1, kp1, desp1 ); + descriptor->compute( rgb2, kp2, desp2 ); + + // 匹配描述子=================================================== + // 对上述的描述子进行匹配。 + // 在OpenCV中,你需要选择一个匹配算法, + // 例如粗暴式(bruteforce),近似最近邻(Fast Library for Approximate Nearest Neighbour, FLANN)等等。 + // 这里我们构建一个FLANN的匹配算法: + vector< cv::DMatch > matches; + // cv::BFMatcher matcher; // 暴力匹配,穷举 + cv::FlannBasedMatcher matcher; // 近似最近邻 + matcher.match( desp1, desp2, matches ); + cout<<"Find total "< goodMatches; + double minDis = 9999; + for ( size_t i=0; i pts_obj;// desp1 的2d点 利用深度值 转换成 3d点 + // 第二个帧的图像点 + vector< cv::Point2f > pts_img; + + // 相机内参 + CAMERA_INTRINSIC_PARAMETERS C; + C.cx = 325.5; + C.cy = 253.5; + C.fx = 518.0; + C.fy = 519.0; + C.scale = 1000.0; + + for (size_t i=0; i( int(p.y) )[ int(p.x) ];// 从深度图 取得深度=== + if (d == 0) + continue;// 跳过深度值异常的点============= + + pts_img.push_back( cv::Point2f( kp2[goodMatches[i].trainIdx].pt ) );// 图像2 关键点对应的 2d像素点 + + // 将(u,v,d)转成(x,y,z)======================= + cv::Point3f pt ( p.x, p.y, d ); + cv::Point3f pd = point2dTo3d( pt, C ); + pts_obj.push_back( pd );// 图像1 关键点对应 2d像素点 对应的 3d点 + } + +// 相机内参数矩阵K =============================== + double camera_matrix_data[3][3] = + { + {C.fx, 0, C.cx}, + {0, C.fy, C.cy}, + {0, 0, 1} + }; + + // 构建相机矩阵 + cv::Mat cameraMatrix( 3, 3, CV_64F, camera_matrix_data );// 8字节 + cv::Mat rvec, tvec, inliers; + // 求解pnp 3d点 2d点 相机内参数矩阵K 旋转向量 rvec 平移向量tvec + cv::solvePnPRansac( pts_obj, pts_img, cameraMatrix, cv::Mat(), rvec, tvec, false, 100, 1.0, 100, inliers ); + +// 这个就叫做“幸福的家庭都是相似的,不幸的家庭各有各的不幸”吧。 +// 你这样理解也可以。ransac适用于数据噪声比较大的场合 + + cout<<"inliers: "< kp; // 关键点 集 kp[i].pt 是关键点对应的像素坐标 +}; + +// PnP 结果 2d-3d 配置结果===== 结构体 +struct RESULT_OF_PNP +{ + cv::Mat rvec, tvec; + int inliers; // 内点数量=====!!!! +}; + +// computeKeyPointsAndDesp 同时提取关键点与特征描述子========引用传递============== +void computeKeyPointsAndDesp( FRAME & frame, string detector, string descriptor ); + +// estimateMotion 2d-3d pnp配准 计算两个帧之间的运动==========引用传递============== +// 输入:帧1和帧2, 相机内参 +RESULT_OF_PNP estimateMotion( FRAME & frame1, FRAME & frame2, CAMERA_INTRINSIC_PARAMETERS& camera ); + + +``` + +```c +// 提取关键点与特征描述子函数 2d-3d-pnp配准函数 src/slamBase.cpp========================= + +// computeKeyPointsAndDesp 同时提取关键点与特征描述子============引用传递============== +void computeKeyPointsAndDesp( FRAME & frame, string detector, string descriptor ) +{ + cv::Ptr _detector; // 关键点检测 + cv::Ptr _descriptor; // 描述子计算 + + cv::initModule_nonfree(); // 如果使用 SIFI / SURF 的话======== + + _detector = cv::FeatureDetector::create( detector.c_str() ); + _descriptor = cv::DescriptorExtractor::create( descriptor.c_str() ); + + if (!_detector || !_descriptor) + { + cerr<<"Unknown detector or discriptor type !"<detect( frame.rgb, frame.kp ); // 检测关键点 + _descriptor->compute( frame.rgb, frame.kp, frame.desp );// 计算描述子 + + return; +} + +// estimateMotion 计算两个帧之间的运动========================================================== +// 输入:帧1和帧2 +// 输出:rvec 和 tvec +RESULT_OF_PNP estimateMotion( FRAME& frame1, FRAME& frame2, CAMERA_INTRINSIC_PARAMETERS& camera ) +{ + static ParameterReader pd; // // 好关键点阈值 参数 读取============== + vector< cv::DMatch > matches;// 匹配点对 + cv::FlannBasedMatcher matcher;// 快速最近邻 匹配器============ + matcher.match( frame1.desp, frame2.desp, matches );// 对两个关键帧的关键点 进行匹配 + + cout<<"find total "< goodMatches; + double minDis = 9999; + + double good_match_threshold = atof( pd.getData( "good_match_threshold" ).c_str() );// 好关键点阈值 读取 + + for ( size_t i=0; i pts_obj; // 2d 关键点对应的像素点 + 对应的深度距离 根据相机参数 转换得到 + // 第二个帧的图像点 + vector< cv::Point2f > pts_img;// 2d 关键点对应的像素点 + +// 从匹配点对 获取 2d-3d点对 =========================== + for (size_t i=0; i( int(p.y) )[ int(p.x) ];// y行,x列 + if (d == 0) + continue; // 深度值不好 跳过 + // 将(u,v,d)转成(x,y,z) + cv::Point3f pt ( p.x, p.y, d ); // 2d 关键点对应的像素点 + 对应的深度距离 + cv::Point3f pd = point2dTo3d( pt, camera );// 根据相机参数 转换得到 3d点 + pts_obj.push_back( pd ); + + + pts_img.push_back( cv::Point2f( frame2.kp[goodMatches[i].trainIdx].pt ) );// 后一帧的 2d像素点 + + } + +// 相机内参数矩阵 K ========================= + double camera_matrix_data[3][3] = + { + {camera.fx, 0, camera.cx}, + {0, camera.fy, camera.cy}, + {0, 0, 1} + }; + + cout<<"solving pnp"<::iterator iter = data.find(key);// 二叉树查找 log(n) + if (iter == data.end()) + { + cerr<<"Parameter name "<second; // 返回对应关键字对应 的 值 iter->first 为 key iter->second 为值 + } + +public: + map data; // 解析得到的参数字典 + +}; + +// 示例参数 +它读的参数文件是长这个样子的: + +# 这是一个参数文件 +# 去你妹的yaml! 我再也不用yaml了!简简单单多好! +# 等号前后不能有空格 +# part 4 里定义的参数 + +detector=ORB +descriptor=ORB +good_match_threshold=4 + +# camera +camera.cx=325.5; +camera.cy=253.5; +camera.fx=518.0; +camera.fy=519.0; +camera.scale=1000.0; + +# 如果我们想更改特征类型,就只需在parameters.txt文件里进行修改,不必编译源代码了。 +# 这对接下去的各种调试都会很有帮助。 +``` + + +# 点云拼接 + + 点云的拼接,实质上是对点云做变换的过程。这个变换往往是用变换矩阵(transform matrix)来描述的: + T=[R t + O 1]∈R4×4 + 该矩阵的左上部分 R 是一个3×3的旋转矩阵,它是一个正交阵。 + 右上部分 t 是3×1的位移矢量。 + 左下O是3×1的 !!!缩放矢量!!!!,在SLAM中通常取成0, + 因为环境里的东西不太可能突然变大变小(又没有缩小灯)。 + + 右下角是个1. 这样的一个阵可以对点或者其他东西进行齐次变换。 + + [X1 [X2 + Y1 Y2 + Z1 = T⋅ Z2 + 1] 1] + 由于变换矩阵t 结合了 旋转R 和 平移t,是一种较为经济实用的表达方式。 + 它在机器人和许多三维空间相关的科学中都有广泛的应用。 + PCL里提供了点云的变换函数,只要给定了变换矩阵,就能对移动整个点云: + + pcl::transformPointCloud( input, output, T ); + + OpenCV认为旋转矩阵R,虽然有3×3 那么大,自由变量却只有三个,不够节省空间。 + 所以在OpenCV里使用了一个向量来表达旋转。 + 向量的方向是旋转轴,大小则是转过的弧度. + 我们先用 罗德里格斯变换(Rodrigues)将旋转向量转换为矩阵,然后“组装”成变换矩阵。 + 代码如下: + +```c +// src/jointPointCloud.cpp=============================== +/***************************************************** + > File Name: src/jointPointCloud.cpp + > Author: Xiang gao + > Mail: gaoxiang12@mails.tsinghua.edu.cn + > Created Time: 2015年07月22日 星期三 20时46分08秒 + **********************************************/ + +#include +using namespace std; + +#include "slamBase.h" + +#include + +#include // 点云转换 +#include // 点云显示 + +// Eigen ! +#include +#include + +int main( int argc, char** argv ) +{ +// 参数读取器, 请见include/slamBase.h + ParameterReader pd; + // 声明两个帧,FRAME结构请见include/slamBase.h + FRAME frame1, frame2; + //本节要拼合data中的两对图像 + //读取图像============================== + frame1.rgb = cv::imread( "./data/rgb1.png" ); + frame1.depth = cv::imread( "./data/depth1.png", -1);// + frame2.rgb = cv::imread( "./data/rgb2.png" ); + frame2.depth = cv::imread( "./data/depth2.png", -1 ); + + // 提取特征并计算描述子==================== + cout<<"extracting features"< trans(result.tvec.at(0,0), + result.tvec.at(0,1), + result.tvec.at(0,2));// 多余??????========= + T = angle;// 旋转矩阵 赋值 给 变换矩阵 T + T(0,3) = result.tvec.at(0,0); // 添加 平移部分 + T(1,3) = result.tvec.at(0,1); + T(2,3) = result.tvec.at(0,2); + + // 转换点云 + cout<<"converting image to clouds"< F2下 + + *output += *cloud2;// 在 F2下 加和 两部分 点云 ======== + pcl::io::savePCDFile("data/result.pcd", *output); + cout<<"Final result saved."< 旋转向量 和平移向量 变换成 变换矩阵T 放入库 +```c +// src/slamBase.cpp +// cvMat2Eigen +// 旋转向量 rvec 和 平移向量 tvec 变换成 变换矩阵T=========================== +Eigen::Isometry3d cvMat2Eigen( cv::Mat& rvec, cv::Mat& tvec ) +{ + cv::Mat R; + // 旋转向量 rvec 变成 旋转矩阵========== + cv::Rodrigues( rvec, R ); + // cv 3×3矩阵 转换成 Eigen 3×3 矩阵==== + Eigen::Matrix3d r; + for ( int i=0; i<3; i++ ) + for ( int j=0; j<3; j++ ) + r(i,j) = R.at(i,j);// 8×8字节 double + + // 将平移向量 和 旋转矩阵 转换成 变换矩阵 T + Eigen::Isometry3d T = Eigen::Isometry3d::Identity();// 单位阵 + + Eigen::AngleAxisd angle(r);// 旋转矩阵 >>> Eigen 旋转轴 + T = angle;// 旋转轴 >>> 变换矩阵 + T(0,3) = tvec.at(0,0); // 附加上 平移向量 + T(1,3) = tvec.at(1,0); + T(2,3) = tvec.at(2,0); + return T; +} + + +``` + +> 前后两帧点云合并 +```c + +// joinPointCloud +// 输入:原始点云,新来的帧 以及 它的位姿 +// 输出:将新来帧加到原始帧后的图像 +PointCloud::Ptr joinPointCloud( PointCloud::Ptr original, // 原始点云 + FRAME& newFrame, // 新来的帧 + Eigen::Isometry3d T, // 它的位姿,相对 原始点云的位姿 + CAMERA_INTRINSIC_PARAMETERS& camera ) // 相机参数 +{ + // 新来的帧 根据 RGB 和 深度图 产生 一帧点云 ======= + PointCloud::Ptr newCloud = image2PointCloud( newFrame.rgb, newFrame.depth, camera ); + + // 合并点云 + PointCloud::Ptr output (new PointCloud()); + pcl::transformPointCloud( *original, *output, T.matrix() );// 怎么是前面的点云 变换到 当前帧 下 + *newCloud += *output; // 当前帧 点云 和变换的点云 加和 + + // Voxel grid 滤波降采样 + static pcl::VoxelGrid voxel;// 静态变量 体素格下采样,只会有一个 变量实体====================== + static ParameterReader pd; // 静态变量 文件参数读取器 + double gridsize = atof( pd.getData("voxel_grid").c_str() );// 体素格精度 + voxel.setLeafSize( gridsize, gridsize, gridsize );// 设置体素格子 大小 + voxel.setInputCloud( newCloud );// 输入点云 + PointCloud::Ptr tmp( new PointCloud() );// 临时点云 + voxel.filter( *tmp );// 滤波输出点云 + return tmp; +} + + +``` + +> 新添加的参数 +```c +# part 5 + +# 数据相关================= +# 图片序列 起始 与 终止索引 +start_index=1 +end_index=700 +# 数据 所在目录 ========= +rgb_dir=../data/rgb_png/ +rgb_extension=.png +depth_dir=../data/depth_png/ +depth_extension=.png +# 点云分辨率 ============ +voxel_grid=0.02 +# 是否实时可视化 是否显示点云 +visualize_pointcloud=yes +# 最小匹配数量 +min_good_match=10 最少特征匹配数量 +# 最小内点 数量 pnp求解 返回的 匹配点数 +min_inliers=5 +# 最大运动量 , 运动量过大也可能是噪声======= +max_norm=0.3 + + + +``` + +## 实现VO + 最后,利用之前写好的工具函数,实现一个VO: + src/visualOdometry.cpp +```c +/************************************************************************* + > File Name: rgbd-slam-tutorial-gx/part V/src/visualOdometry.cpp + > Author: xiang gao + > Mail: gaoxiang12@mails.tsinghua.edu.cn + > Created Time: 2015年08月01日 星期六 15时35分42秒 + ************************************************************************/ + +#include +#include +#include +using namespace std; + +#include "slamBase.h" + +// 给定index,读取一帧数据 +FRAME readFrame( int index, ParameterReader& pd ); +// 度量运动的大小 +double normofTransform( cv::Mat rvec, cv::Mat tvec ); + +int main( int argc, char** argv ) +{ + +// 数据集================================================================== + ParameterReader pd; + int startIndex = atoi( pd.getData( "start_index" ).c_str() );// 起始图片 + int endIndex = atoi( pd.getData( "end_index" ).c_str() );// 终止图片 + // 初始化 initialize + cout<<"Initializing ..."<>filename; + f.rgb = cv::imread( filename );// 读取文件 RGB + + ss.clear(); + filename.clear(); + ss<>filename; + + f.depth = cv::imread( filename, -1 );// 深度图 + return f; +} +// 估计一个运动的大小 ===================================== +double normofTransform( cv::Mat rvec, cv::Mat tvec ) +{ +// 旋转大小 0~2*pi + 平移大小============= + return fabs(min(cv::norm(rvec), 2*M_PI - cv::norm(rvec)))+ fabs(cv::norm(tvec)); +} + + + +``` + +  这个里程计有什么不足呢? + 1. 一旦出现了错误匹配,整个程序就会跑飞。 + 2. 误差会累积。常见的现象是:相机转过去的过程能够做对,但转回来之后则出现明显的偏差。 + 3. 效率方面不尽如人意。在线的点云显示比较费时。 + + + +# 图优化工具g2o + 姿态图(原理部分) + 姿态图,顾名思义,就是由相机姿态构成的一个图(graph)。 + 这里的图,是从图论的意义上来说的。 + 一个图由 节点 vertex 与 边 edge 构成: + G={V,E}. + + 在最简单的情况下,节点代表相机的各个姿态(四元数形式或矩阵形式): + vi=[x,y,z,qx,qy,qz,qw]= Ti=[R3×3 t3×1 + O1×3 1]i + + 而边指的是两个节点间的变换: + Ei,j = Ti,j = [R3×3 t3×1 + O1×3 1]i,j. + + 利用 边可以将两个节点进行变换,由于计算误差,变换不可能完全一致,就会出现误差 + 我们就可以优化一个不一致性误差: + min C = ∑i,j∥v'i − Ti,j * v'j∥2 . 非线性平方误差函数 + v’ 是上面 pnp求解出来的初始变量值,最开始 误差C有一个初始值,可以使用梯度下降法来优化变量 + + v'(t+1) = v'(t) - 学习率*导数*C(t) , t 表示优化迭代id。 + + https://github.com/Ewenwan/MVision/blob/master/vSLAM/ch6/g2o_curve_fitting/main.cpp + + 调整v的值使得E缩小。最后,如果这个问题收敛的话,v的 变化 就会越来越小,E也收敛到一个极小值。 + + 根据迭代策略的不同,又可分为Gauss-Netwon(GN)下山法, + Levenberg-Marquardt(LM)方法等等。 + 这个问题也称为Bundle Adjustment(BA), + 我们通常使用LM方法优化这个非线性平方误差函数。 + + 为什么说slam里的BA问题稀疏呢?因为同样的场景很少出现在许多位置中。 + 这导致上面的pose graph中,图G离全图很远,只有少部分的节点存在直接边的联系。 + 这就是姿态图的稀疏性。 + + 求解BA的软件包有很多,感兴趣的读者可以去看wiki: https://en.wikipedia.org/wiki/Bundle_adjustment。我 + 们这里介绍的g2o(Generalized Graph Optimizer),就是近年很流行的一个图优化求解软件包。 + + +## G2O 实验 + 要使用g2o,首先你需要下载并安装它:https://github.com/RainerKuemmerle/g2o。 + 安装依赖项: + sudo apt-get install libeigen3-dev libsuitesparse-dev libqt4-dev qt4-qmake libqglviewer-qt4-dev + 1404或1604的最后一项改为 libqglviewer-dev 即可。 + + 解压g2o并编译安装: + 进入g2o的代码目录,并: + + mkdir build + cd build + cmake .. + make + sudo make install + + 多说两句,你可以安装cmake-curses-gui这个包, + 通过gui来选择你想编译的g2o模块并设定cmake编译过程中的flags。 + 例如,当你实在装不好上面的libqglviewer时,你可以选择不编译g2o可视化模块(把G2O_BUILD_APPS关掉), + 这样即使没有libqglviewer,你也能编译过g2o。 + + cd build + ccmake .. + make + sudo make install + + 安装成功后,你可以在/usr/local/include/g2o中找到它的头文件,而在/usr/local/lib中找到它的库文件。 + 使用g2o + 安装完成后,我们把g2o引入自己的cmake工程: + + # 添加g2o的依赖 + # 因为g2o不是常用库,要添加它的findg2o.cmake文件 + LIST( APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules ) + SET( G2O_ROOT /usr/local/include/g2o ) + FIND_PACKAGE( G2O ) + # CSparse + FIND_PACKAGE( CSparse ) + INCLUDE_DIRECTORIES( ${G2O_INCLUDE_DIR} ${CSPARSE_INCLUDE_DIR} ) + + 同时,在代码根目录下新建cmake_modules文件夹, + 把g2o代码目录下的cmake_modules里的东西都拷进来, + 保证cmake能够顺利找到g2o。 + + +```c + + +// src/slamEnd.cpp=========================================================== +/************************************************************************* + > File Name: rgbd-slam-tutorial-gx/part V/src/visualOdometry.cpp + > Author: xiang gao + > Mail: gaoxiang12@mails.tsinghua.edu.cn + > Created Time: 2015年08月15日 星期六 15时35分42秒 + * add g2o slam end to visual odometry + ************************************************************************/ + +#include +#include +#include +using namespace std; + +#include "slamBase.h" + +// G2O图优化=============================================== +#include //顶点类型 +#include // 稀疏优化 +#include // 矩阵分块 +#include +#include +#include // GN 优化 +#include // 核函数 +#include +#include +// 莱文贝格-马夸特方法(Levenberg–Marquardt algorithm)能提供数非线性最小化(局部最小)的数值解。 +#include + + +// 给定index,读取一帧数据 +FRAME readFrame( int index, ParameterReader& pd ); +// 估计一个运动的大小 +double normofTransform( cv::Mat rvec, cv::Mat tvec ); + +int main( int argc, char** argv ) +{ +// 数据集================================================================== + // 前面部分和vo是一样的 + ParameterReader pd; + int startIndex = atoi( pd.getData( "start_index" ).c_str() ); + int endIndex = atoi( pd.getData( "end_index" ).c_str() ); + +// initialize 初始化============================= + cout<<"Initializing ..."< SlamLinearSolver; + +// 类型选择 ========================== +// 由于我们是3D的slam,所以顶点取成了相机姿态:g2o::VertexSE3, +// 而边则是连接两个VertexSE3的边:g2o::EdgeSE3。 4×4的变换矩阵, +// 如果你想用别的类型的顶点(如2Dslam,路标点),你可以看看/usr/local/include/g2o/types/下的文件, +// 基本上涵盖了各种slam的应用,应该能满足你的需求。 + + // 初始化求解器 + SlamLinearSolver* linearSolver = new SlamLinearSolver(); + linearSolver->setBlockOrdering( false ); + SlamBlockSolver* blockSolver = new SlamBlockSolver( linearSolver ); + g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg( blockSolver ); + + g2o::SparseOptimizer globalOptimizer; // 最后用的就是这个东东 + globalOptimizer.setAlgorithm( solver ); + // 不要输出调试信息 + globalOptimizer.setVerbose( false ); + + // 向globalOptimizer增加第一个顶点==================================== + g2o::VertexSE3* v = new g2o::VertexSE3(); + v->setId( currIndex ); + v->setEstimate( Eigen::Isometry3d::Identity() ); //估计为单位矩阵 + v->setFixed( true ); // 第一个顶点固定,不用优化 + globalOptimizer.addVertex( v ); + + int lastIndex = currIndex; // 上一帧的id + + for ( currIndex=startIndex+1; currIndex>filename; + f.rgb = cv::imread( filename ); // RGB + + ss.clear(); + filename.clear(); + ss<>filename; + + f.depth = cv::imread( filename, -1 ); // 深度图 + f.frameID = index; + return f; +} + +// 估计一个运动的大小 ===================================== +double normofTransform( cv::Mat rvec, cv::Mat tvec ) +{ +// 旋转大小 0~2*pi + 平移大小============= + return fabs(min(cv::norm(rvec), 2*M_PI-cv::norm(rvec)))+ fabs(cv::norm(tvec)); +} + + + +``` + + + + +# 添加回环检测 + 程序分析: + 1. 关键帧的提取。 + 把每一帧都拼到地图是去是不明智的。 + 因为帧与帧之间距离很近,导致地图需要频繁更新,浪费时间与空间。 + 所以,我们希望,当机器人的运动超过一定间隔,就增加一个“关键帧”。 + 最后只需把关键帧拼到地图里就行了。 + 2. 回环的检测。 + 回环的本质是识别曾经到过的地方。 + 最简单的回环检测策略,就是把新来的关键帧与之前所有的关键帧进行比较, + 不过这样会导致越往后,需要比较的帧越多。 + 所以,稍微快速一点的方法是在过去的帧里随机挑选一些,与之进行比较。 + 更进一步的,也可以用图像处理/模式识别的方法计算图像间的相似性,对相似的图像进行检测。 + +以下为伪码: + + 1. 初始化关键帧序列:F,并将第一帧f0放入F。 + 2. 对于新来的一帧I,计算 关键帧序列 F中最后一个关键帧帧 与 当前帧I 的 运动,并估计该运动的大小e。 + 有以下几种可能性: + a. 若e>Eerror,说明运动太大,可能是计算错误,丢弃该帧; + b. 若没有匹配上(match太少),说明该帧图像质量不高,丢弃; + c. 若e File Name: rgbd-slam-tutorial-gx/part V/src/visualOdometry.cpp + > Author: xiang gao + > Mail: gaoxiang12@mails.tsinghua.edu.cn + > Created Time: 2015年08月15日 星期六 15时35分42秒 + * add g2o slam end to visual odometry + * add keyframe and simple loop closure + ************************************************************************/ + +#include +#include +#include +using namespace std; + +#include "slamBase.h" + +// 点云可视化================= +#include +#include + +// G2O图优化================== +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// 把g2o的定义放到前面=================================== +typedef g2o::BlockSolver_6_3 SlamBlockSolver; +typedef g2o::LinearSolverEigen< SlamBlockSolver::PoseMatrixType > SlamLinearSolver; + +// 给定index,读取一帧数据===== +FRAME readFrame( int index, ParameterReader& pd ); +// 估计一个运动的大小========= +double normofTransform( cv::Mat rvec, cv::Mat tvec ); + + +// 关键帧选取 ==============枚举变量 +enum CHECK_RESULT { + NOT_MATCHED=0, // 两帧无匹配 + TOO_FAR_AWAY, // 相隔太远 + TOO_CLOSE, // 相隔太近 + KEYFRAME}; // 相隔正好,可作为关键帧===== + +// 和最近一个关键帧进行匹配,关键帧检测,适当时需要在g2o中键入 关键帧节点======= +// 函数声明==检查关键帧=== +CHECK_RESULT checkKeyframes( FRAME& f1, FRAME& f2, + g2o::SparseOptimizer& opti, + bool is_loops=false ); + +// 检测近距离的回环======= +void checkNearbyLoops( vector& frames, FRAME& currFrame, g2o::SparseOptimizer& opti ); +// 随机检测回环========== +void checkRandomLoops( vector& frames, FRAME& currFrame, g2o::SparseOptimizer& opti ); + +int main( int argc, char** argv ) +{ + // 前面部分和vo是一样的 + ParameterReader pd;// 参数读取 + int startIndex = atoi( pd.getData( "start_index" ).c_str() ); + int endIndex = atoi( pd.getData( "end_index" ).c_str() ); + + // 所有的关键帧都放在了这里 + vector< FRAME > keyframes;// 关键帧集合 , 这里关键帧 和普通帧 结构对象上无区别==== + // initialize 初始化======================== + cout<<"Initializing ..."<setBlockOrdering( false ); + SlamBlockSolver* blockSolver = new SlamBlockSolver( linearSolver ); + g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg( blockSolver ); + + g2o::SparseOptimizer globalOptimizer; // 最后用的就是这个东东 + globalOptimizer.setAlgorithm( solver ); + // 不要输出调试信息 + globalOptimizer.setVerbose( false ); + + // 向globalOptimizer增加第一个顶点 + g2o::VertexSE3* v = new g2o::VertexSE3(); + v->setId( currIndex ); + v->setEstimate( Eigen::Isometry3d::Identity() ); //估计为单位矩阵,世界坐标系 + v->setFixed( true ); //第一个顶点固定,不用优化 + globalOptimizer.addVertex( v ); + + keyframes.push_back( currFrame );// 第一帧就作为关键帧,其实可以根据关键点数量超过阈值,才作为地一个关键帧 + + double keyframe_threshold = atof( pd.getData("keyframe_threshold").c_str() );// 关键帧阈值,距离 + bool check_loop_closure = pd.getData("check_loop_closure")==string("yes"); // 回环检测==== + + for ( currIndex=startIndex+1; currIndex voxel; // 网格滤波器,调整地图分辨率 + pcl::PassThrough pass; // z方向区间滤波器,由于rgbd相机的有效深度区间有限,把太远的去掉 + pass.setFilterFieldName("z"); + pass.setFilterLimits( 0.0, 4.0 ); //4m以上就不要了 保留相机前方 0~4m范围 + + double gridsize = atof( pd.getData( "voxel_grid" ).c_str() ); //分辨图可以在parameters.txt里调 + voxel.setLeafSize( gridsize, gridsize, gridsize );// 体素格滤波====== + + for (size_t i=0; i(globalOptimizer.vertex( keyframes[i].frameID )); + Eigen::Isometry3d pose = vertex->estimate(); // 该帧优化后的位姿 + PointCloud::Ptr newCloud = image2PointCloud( keyframes[i].rgb, keyframes[i].depth, camera ); //转成点云 + // 以下是滤波 + voxel.setInputCloud( newCloud ); + voxel.filter( *tmp ); + pass.setInputCloud( tmp ); + pass.filter( *newCloud ); + + // 之前的工程是 将之前的点晕转换到 当前点云下 ================= + + // 不过这里 pose.matrix() 在 checkKeyframes 加入的是 PNP 估计出来的逆矩阵 + // 原来是 f1 ---> f2 + // 逆矩阵 之后是 f2 ----> f1 + + // 把 点云 变换 后 加入全局地图中 当前点云 + pcl::transformPointCloud( *newCloud, *tmp, pose.matrix() ); + *output += *tmp; + tmp->clear(); // 滤波点云清空 + newCloud->clear();// 新点云清空 + } + + voxel.setInputCloud( output ); + voxel.filter( *tmp ); // 最后整体滤波================== + //存储 + pcl::io::savePCDFile( "./result.pcd", *tmp ); + + cout<<"Final map is saved."<>filename; + f.rgb = cv::imread( filename ); + + ss.clear(); + filename.clear(); + ss<>filename; + + f.depth = cv::imread( filename, -1 ); + f.frameID = index; + return f; +} +// 运动量大小=========== +double normofTransform( cv::Mat rvec, cv::Mat tvec ) +{ + return fabs(min(cv::norm(rvec), 2*M_PI-cv::norm(rvec)))+ fabs(cv::norm(tvec)); +} + +// 和最近一个关键帧进行匹配,关键帧检测,适当时需要在g2o中键入 关键帧节点======= +CHECK_RESULT checkKeyframes( FRAME& f1, FRAME& f2, g2o::SparseOptimizer& opti, bool is_loops) +{ + static ParameterReader pd; + static int min_inliers = atoi( pd.getData("min_inliers").c_str() ); // pnp 内点数量 + static double max_norm = atof( pd.getData("max_norm").c_str() ); // 运动量太大 阈值 + static double keyframe_threshold = atof( pd.getData("keyframe_threshold").c_str() );// 关键帧 运动量阈值,小于就太小 + static double max_norm_lp = atof( pd.getData("max_norm_lp").c_str() ); // 运动距离 + static CAMERA_INTRINSIC_PARAMETERS camera = getDefaultCamera(); // 相机参数====== + + // 比较f1 和 f2 + RESULT_OF_PNP result = estimateMotion( f1, f2, camera );// pnp 估计帧间运动 + if ( result.inliers < min_inliers ) //inliers不够,放弃该帧 + return NOT_MATCHED; // 未匹配上 + + // 计算运动范围是否太大 + double norm = normofTransform(result.rvec, result.tvec);// 计算运动量 + if ( is_loops == false ) + { + if ( norm >= max_norm ) // 运动量过大阈值 + return TOO_FAR_AWAY; // too far away, may be error + } + else + { + if ( norm >= max_norm_lp) // 运动量过大阈值 + return TOO_FAR_AWAY; + } + + if ( norm <= keyframe_threshold ) + return TOO_CLOSE; // too adjacent frame + + // 剩下的就是运动量杠杆好=========================== + + // 向g2o中增加这个顶点与上一帧联系的边 + // 顶点部分 + // 顶点只需设定id即可 + if (is_loops == false) + { + g2o::VertexSE3 *v = new g2o::VertexSE3(); + v->setId( f2.frameID ); + v->setEstimate( Eigen::Isometry3d::Identity() ); + opti.addVertex(v); + } + // 边部分 + g2o::EdgeSE3* edge = new g2o::EdgeSE3(); + // 连接此边的两个顶点id + edge->setVertex( 0, opti.vertex(f1.frameID )); + edge->setVertex( 1, opti.vertex(f2.frameID )); + + edge->setRobustKernel( new g2o::RobustKernelHuber() );// +// 回环检测是很怕"false positive"的,即“将实际上不同的地方当成了同一处”,这会导致地图出现明显的不一致。 +// 所以,在使用g2o时,要在边里添加"robust kernel",保证一两个错误的边不会影响整体结果。 + + // 信息矩阵 + Eigen::Matrix information = Eigen::Matrix< double, 6,6 >::Identity(); + // 信息矩阵是协方差矩阵的逆,表示我们对边的精度的预先估计 + // 因为pose为6D的,信息矩阵是6*6的阵,假设位置和角度的估计精度均为0.1且互相独立 + // 那么协方差则为对角为0.01的矩阵,信息阵则为100的矩阵 + information(0,0) = information(1,1) = information(2,2) = 100; // 角度信息 + information(3,3) = information(4,4) = information(5,5) = 100; // 平移量信息 + // 也可以将角度设大一些,表示对角度的估计更加准确 + + edge->setInformation( information ); + + // 边的估计即是pnp求解之结果 + Eigen::Isometry3d T = cvMat2Eigen( result.rvec, result.tvec ); + + // edge->setMeasurement( T ); + edge->setMeasurement( T.inverse() ); // 相反的 ,就是 f2---> f1 + + // 将此边加入图中 + opti.addEdge(edge); + return KEYFRAME; +} + + +// 局部回环检测========== +void checkNearbyLoops( vector& frames, FRAME& currFrame, g2o::SparseOptimizer& opti ) +{ + static ParameterReader pd; + static int nearby_loops = atoi( pd.getData("nearby_loops").c_str() ); + + // 就是把currFrame和 frames里末尾几个测一遍 + if ( frames.size() <= nearby_loops ) + { + // no enough keyframes, check everyone + for (size_t i=0; i& frames, FRAME& currFrame, g2o::SparseOptimizer& opti ) +{ + static ParameterReader pd; + static int random_loops = atoi( pd.getData("random_loops").c_str() ); + srand( (unsigned int) time(NULL) ); + // 随机取一些帧进行检测 + + if ( frames.size() <= random_loops ) + { + // no enough keyframes, check everyone + for (size_t i=0; i2块--> 再切一刀->4块-->再切一刀->8块 8卦 +![](https://images2015.cnblogs.com/blog/606958/201512/606958-20151212140710419-2029480818.png) + + 实际的数据结构呢,就是一个树根不断地往下扩,每次分成八个枝,直到叶子为止。 + 叶子节点代表了分辨率最高的情况。例如分辨率设成0.01m,那么每个叶子就是一个1cm见方的小方块了呢! + 每个小方块都有一个数描述它是否被占据。在最简单的情况下,可以用0-1两个数表示(太简单了所以没什么用)。 + 通常还是用0~1之间的浮点数表示它被占据的概率。0.5表示未确定,越大则表示被占据的可能性越高,反之亦然。 + 由于它是八叉树,那么一个节点的八个孩子都有一定的概率被占据或不被占据啦!(下图是一棵八叉树)。 +![](https://images2015.cnblogs.com/blog/606958/201512/606958-20151212142153278-792679245.png) + + 用树结构的好处时:当某个节点的子结点都“占据”或“不占据”或“未确定”时,就可以把它给剪掉! + 换句话说,如果没必要进一步描述更精细的结构(孩子节点)时,我们只要一个粗方块(父节点)的信息就够了。 + 这可以省去很多的存储空间。因为我们不用存一个“全八叉树”呀! + + 2. 八叉树的更新 + 在八叉树中,我们用概率来表达一个叶子是否被占据。为什么不直接用0-1表达呢? + 因为在对环境的观测过程中,由于噪声的存在,某个方块有时可能被观测到是“占据”的, + 过了一会儿,在另一些方块中又是“不占据”的。有时“占据”的时候多,有时“不占据”的时候多。 + 这一方面可能是由于环境本身有动态特征(例如桌子被挪走了),另一方面(多数时候)可能是由于噪声。 + 根据八叉树的推导,假设t=1,…,T时刻,观测的数据为z1,…,zT,那么第n个叶子节点记录的信息为: + + p(n|z1:zT) = [ 1+ (1-p(n|zT))/p(n|ZT) * (1-p(n|z1:zT-1))/p(n|z1:zT-1) * p(n)/(1-p(n)) ]^(-1) + + + logit 变换 把 0~1概率 映射到 全实数R空间 -无穷大 ~ +无穷大 +![](https://upload.wikimedia.org/wikipedia/commons/thumb/c/c8/Logit.svg/350px-Logit.svg.png) + + p = 0~1 上图中的x + a = logit(p) = log(p/(1-p)) 范围为 -无穷大 ~ +无穷大 + 反过来可以得到 + exp(a) = p/(1-p) ===> + exp(a) = p(1+exp(a)) ====> + p = exp(a)/(1+exp(a)) = 1/(1+exp(-a)) // sigmod(a) 神经网络激活函数 + -无穷大 ~ +无穷大 映射为 0~1 + + 我们对 p() 取logit 变换得到 + L(P) = L(n|z1:zT) = L(n|z1:zT-1) + L(n|zT) 每一次的logit变换值 只是前面观测的 + 当前次概率的logit值 + 然后我们再对 logit值 求反变换 得到其概率值p!!!!!!!!!!!!!方便计算========================= + + 每新来一个就直接加到原来的上面 + 此外还要加一个最大最小值的限制。最后转换回原来的概率即可。 + + + 八叉树中的父亲节点占据概率,可以根据孩子节点的数值进行计算。比较简单的是取平均值或最大值。 + 如果把八叉树按照占据概率进行渲染,不确定的方块渲染成透明的, + 确定占据的渲染成不透明的,就能看到我们平时见到的那种东西啦! + octomap本身的数学原理还是简单的。不过它的可视化做的比较好。 + + + + 下载 + https://github.com/Ewenwan/octomap + api 文档 + http://octomap.github.io/octomap/doc/ + + 安装 + mkdir build + cd build + cmake .. + make + + 事实上,octomap的代码主要含两个模块:本身的octomap和可视化工具octovis。 + octovis依赖于qt4和qglviewer,所以如果你没有装这两个依赖, + 请安装它们:sudo apt-get install libqt4-dev qt4-qmake libqglviewer-dev + + 如果编译没有给出任何警告,恭喜你编译成功! + + 使用octovis查看示例地图 + 在bin/文件夹中,存放着编译出来可执行文件。为了直观起见,我们直接看一个示例地图: + + bin/octovis octomap/share/data/geb079.bt + + octovis会打开这个地图并显示。它的UI是长这样的。你可以玩玩菜单里各种东西(虽然也不多,我就不一一介绍UI怎么玩了), + 能看出这是一层楼的扫描图。octovis是一个比较实用的工具,你生成的各种octomap地图都可以用它来看。 + (所以你可以把octovis放到/usr/local/bin/下,省得以后还要找。) + +## pcl PointXYZRGBA 点云 转换到 xyz类型的 octomap +```c +/************************************************************************* + > File Name: src/pcd2octomap.cpp + > Author: Gao Xiang + > Mail: gaoxiang12@mails.tsinghua.edu.cn + > Created Time: 2015年12月12日 星期六 15时51分45秒 + + 将命令行参数1作为输入文件,参数2作为输出文件,把输入的pcd格式点云转换成octomap格式的点云。 + 通过这个例子,你可以学会如何创建一个简单的OcTree对象并往里面添加新的点。  + + 调用: bin/pcd2octomap data/sample.pcd data/sample.bt + + 这个octomap里只存储了点的空间信息,而没有颜色信息。 + 我按照高度给它染色了,否则它应该就是灰色的。 + 通过octomap,我们能查看每个小方块是否可以通行,从而实现导航的工作。 + + octomap存储的文件后缀名是.bt(二进制文件)和.ot(普通文件),前者相对更小一些。 + 不过octomap文件普遍都很小,所以也不差这么些容量。 + 如果你存成了其他后缀名,octovis可能认不出来。 + + ************************************************************************/ + +#include +#include + +// pcl========== +#include +#include + +// octomap ===== +#include + +// 命名空间====== +using namespace std; + +int main( int argc, char** argv ) +{ + if (argc != 3) + { + cout<<"Usage: pcd2octomap "< cloud; + pcl::io::loadPCDFile ( input_file, cloud );// 载入点云 + + cout<<"point cloud loaded, piont size = "< cmakelists +```c + +# 增加PCL库的依赖 +FIND_PACKAGE( PCL REQUIRED COMPONENTS common io ) + +# SET设置变量 支持C++11 -O2 优化等级 +SET(CMAKE_C_FLAGS "${CMAK_C_FLAGS} -g -Wall -O2 -std=c11") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall -O2 -std=c++11") +# 支持C++14, when gcc version > 5.1, use -std=c++14 instead of c++1y +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall -O2 -std=c++1y") + +# 添加头文件和库文件 +ADD_DEFINITIONS( ${PCL_DEFINITIONS} ) +INCLUDE_DIRECTORIES( ${PCL_INCLUDE_DIRS} ) +LINK_LIBRARIES( ${PCL_LIBRARY_DIRS} ) + +# octomap +FIND_PACKAGE( octomap REQUIRED ) +INCLUDE_DIRECTORIES( ${OCTOMAP_INCLUDE_DIRS} ) + +ADD_EXECUTABLE( pcd2octomap pcd2octomap.cpp ) +TARGET_LINK_LIBRARIES( pcd2octomap + ${PCL_LIBRARIES} + ${OCTOMAP_LIBRARIES}) + +ADD_EXECUTABLE( pcd2colorOctomap pcd2colorOctomap.cpp ) +TARGET_LINK_LIBRARIES( pcd2colorOctomap + ${PCL_LIBRARIES} + ${OCTOMAP_LIBRARIES}) + +FIND_PACKAGE(OpenCV REQUIRED) + +ADD_EXECUTABLE( joinmap joinMap.cpp ) +TARGET_LINK_LIBRARIES( joinmap + ${OCTOMAP_LIBRARIES} + ${OpenCV_LIBS}) + + +``` + + + + +## pcl PointXYZRGBA 点云 转换到 xyzrgb类型的 octomap +```c +// octomap提供了 ColorOcTree 类,能够帮你存储颜色信息。下面我们就来做一个保存颜色信息的示例。 +// 代码见:src/pcd2colorOctomap.cpp + +/************************************************************************* + > File Name: src/pcd2colorOctomap.cpp + > Author: Gao Xiang + > Mail: gaoxiang12@mails.tsinghua.edu.cn + > Created Time: 2015年12月12日 星期六 15时51分45秒 + + 调用 + bin/pcd2colorOctomap data/sample.pcd data/sample.ot + 这段代码会编译出pcd2colorOctomap这个程序,完成带颜色的转换。不过,后缀名改成了.ot文件。  + 颜色信息能够更好地帮助我们辨认结果是否正确,给予一个直观的印象。 + + ************************************************************************/ + +#include +#include + +//pcl======================= +#include +#include + +//octomap ================= +#include +#include + +using namespace std; + +int main( int argc, char** argv ) +{ + if (argc != 3) + { + cout<<"Usage: pcd2colorOctomap "< cloud; + pcl::io::loadPCDFile ( input_file, cloud ); // 载入pcl点云 + + cout<<"point cloud loaded, piont size = "< File Name: src/joinMap.cpp + > Author: Gao Xiang + > Mail: gaoxiang12@mails.tsinghua.edu.cn + > Created Time: 2015年12月13日 星期日 14时37分05秒 + ************************************************************************/ + +#include +#include + +// octomap ================ +#include +#include +#include + +// opencv 用于图像数据读取与处理=========== +#include +#include +#include + +// 使用Eigen的Geometry模块处理3d运动====== +#include +#include + +// pcl============================ +#include +#include + +// boost.format 字符串处理 +#include + +using namespace std; + +// 全局变量:相机矩阵 +// 更好的写法是存到参数文件中,但为方便起见我就直接这样做了 +float camera_scale = 1000; +float camera_cx = 325.5; +float camera_cy = 253.5; +float camera_fx = 518.0; +float camera_fy = 519.0; + +int main( int argc, char** argv ) +{ + // 读关键帧编号===================================== + ifstream fin( "./data/keyframe.txt" ); + vector keyframes; + vector< Eigen::Isometry3d > poses; + // 把文件 ./data/keyframe.txt 里的数据读取到vector中 + while( fin.peek() != EOF ) + { + int index_keyframe; + fin>>index_keyframe; + if (fin.fail()) break; + keyframes.push_back( index_keyframe ); + } + fin.close(); + + cout<<"load total "<>index_keyframe; + for ( int i=0; i<7; i++ ) + { + fin>>data[i]; + cout< cloud; + cout<<"converting "< (m) [n];// 深度值 + if (d == 0) + continue; + float z = float(d) / camera_scale; + float x = (n - camera_cx) * z / camera_fx; + float y = (m - camera_cy) * z / camera_fy; + pcl::PointXYZRGBA p; + p.x = x; p.y = y; p.z = z; + + uchar* rgbdata = &rgb.ptr(m)[n*3]; + uchar b = rgbdata[0]; + uchar g = rgbdata[1]; + uchar r = rgbdata[2]; + + p.r = r; p.g = g; p.b = b; + cloud.points.push_back( p ); + } + // 将cloud旋转之后插入全局地图 + pcl::PointCloud::Ptr temp( new pcl::PointCloud() ); + pcl::transformPointCloud( cloud, *temp, pose.matrix() ); // 转换到当前枕坐标系下 + + octomap::Pointcloud cloud_octo; // 当前帧octo点云========================== + for (auto p:temp->points) // 遍例每一个 pcl点云 + cloud_octo.push_back( p.x, p.y, p.z ); + + // 总octo点云 中插入 octo 点云============================ +// insertPointCloud会比单纯的插入点更好一些。octomap里的pointcloud是一种射线的形式, +// 只有末端才存在被占据的点,中途的点则是没被占据的。这会使一些重叠地方处理的更好。 + tree.insertPointCloud( cloud_octo, + octomap::point3d( pose(0,3), pose(1,3), pose(2,3) ) );//按当前帧的位置 插入 + + for (auto p:temp->points) + tree.integrateNodeColor( p.x, p.y, p.z, p.r, p.g, p.b );//加入颜色 + } + + tree.updateInnerOccupancy();// 更新 + tree.write( "./data/map.ot" );// 保存 + + cout<<"done."<>> make -j4 - -sudo chmod 777 build.sh -./build.sh - - -之后会在lib文件夹下生成libORB_SLAM2.so, -并且在Examples文件夹下生成 -mono_tum,mono_kitti, mono_euroc in Examples/Monocular 单目 , -rgbd_tum in Examples/Monocular RGB-D, -stereo_kitti 和 stereo_euroc in Examples/Stereo 双目立体。 - - -数据集: -KITTI dataset 对于 单目 stereo 或者 双目 monocular -http://www.cvlibs.net/datasets/kitti/eval_odometry.php - -EuRoC dataset 对于 单目 stereo 或者 双目 monocular -http://projects.asl.ethz.ch/datasets/doku.php?id=kmavvisualinertialdatasets - -TUM dataset 对于 RGB-D 或者 单目monocular -https://vision.in.tum.de/data/datasets/rgbd-dataset - - -论文: -ORB-SLAM: -[Monocular] Raúl Mur-Artal, J. M. M. Montiel and Juan D. Tardós. ORB-SLAM: A Versatile and Accurate Monocular SLAM System. -IEEE Transactions on Robotics, vol. 31, no. 5, pp. 1147-1163, 2015. (2015 IEEE Transactions on Robotics Best Paper Award). -http://webdiis.unizar.es/%7Eraulmur/MurMontielTardosTRO15.pdf - -ORB-SLAM2: -[Stereo and RGB-D] Raúl Mur-Artal and Juan D. Tardós. ORB-SLAM2: an Open-Source SLAM System for Monocular, Stereo and RGB-D Cameras. -IEEE Transactions on Robotics, vol. 33, no. 5, pp. 1255-1262, 2017. -https://128.84.21.199/pdf/1610.06475.pdf - -词袋模型: -[DBoW2 Place Recognizer] Dorian Gálvez-López and Juan D. Tardós. Bags of Binary Words for Fast Place Recognition in Image Sequences. -IEEE Transactions on Robotics, vol. 28, no. 5, pp. 1188-1197, 2012. -http://doriangalvez.com/papers/GalvezTRO12.pdf - - -单目测试 -在http://vision.in.tum.de/data/datasets/rgbd-dataset/download下载一个序列,并解压。 -转到ORBSLAM2文件夹下,执行下面的命令。 -根据下载的视频序列freiburg1, freiburg2 和 freiburg3将TUMX.yaml分别转换为对应的 TUM1.yaml 或 TUM2.yaml 或 TUM3.yaml -(相机参数文件)。 -将PATH_TO_SEQUENCE_FOLDER 更改为解压的视频序列文件夹。 -./Examples/Monocular/mono_tum Vocabulary/ORBvoc.txt Examples/Monocular/TUMX.yaml PATH_TO_SEQUENCE_FOLDER - 解压的视频序列文件夹 - -双目测试 -在 http://projects.asl.ethz.ch/datasets/doku.php?id=kmavvisualinertialdatasets 下载一个序列 Vicon Room 1 02 大小1.2GB -./Examples/Stereo/stereo_euroc Vocabulary/ORBvoc.txt Examples/Stereo/EuRoC.yaml PATH_TO_SEQUENCE/cam0/data PATH_TO_SEQUENCE/cam1/data Examples/Stereo/EuRoC_TimeStamps/SEQUENCE.txt - - -################################### -词带 - orb词带txt载入太慢,看到有人转换为binary,速度超快,试了下,确实快. -链接:https://github.com/raulmur/ORB_SLAM2/pull/21/commits/4122702ced85b20bd458d0e74624b9610c19f8cc -Vocabulary/ORBvoc.txt >>> Vocabulary/ORBvoc.bin -################################################################ -#CMakeLists.txt -最后添加 -## .txt >>> .bin 文件转换 -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/tools) -add_executable(bin_vocabulary -tools/bin_vocabulary.cc) -target_link_libraries(bin_vocabulary ${PROJECT_NAME}) - -# build.sh 转换 .txt >>> .bin -最后添加 -cd .. -echo "Converting vocabulary to binary" -./tools/bin_vocabulary - -#### 新建转换文件 -tools/bin_vocabulary.cc - -#include -#include "ORBVocabulary.h" -using namespace std; - -bool load_as_text(ORB_SLAM2::ORBVocabulary* voc, const std::string infile) { - clock_t tStart = clock(); - bool res = voc->loadFromTextFile(infile); - printf("Loading fom text: %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); - return res; -} - -void load_as_xml(ORB_SLAM2::ORBVocabulary* voc, const std::string infile) { - clock_t tStart = clock(); - voc->load(infile); - printf("Loading fom xml: %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); -} - -void load_as_binary(ORB_SLAM2::ORBVocabulary* voc, const std::string infile) { - clock_t tStart = clock(); - voc->loadFromBinaryFile(infile); - printf("Loading fom binary: %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); -} - -void save_as_xml(ORB_SLAM2::ORBVocabulary* voc, const std::string outfile) { - clock_t tStart = clock(); - voc->save(outfile); - printf("Saving as xml: %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); -} - -void save_as_text(ORB_SLAM2::ORBVocabulary* voc, const std::string outfile) { - clock_t tStart = clock(); - voc->saveToTextFile(outfile); - printf("Saving as text: %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); -} - -void save_as_binary(ORB_SLAM2::ORBVocabulary* voc, const std::string outfile) { - clock_t tStart = clock(); - voc->saveToBinaryFile(outfile); - printf("Saving as binary: %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); -} - -int main(int argc, char **argv) { - cout << "BoW load/save benchmark" << endl; - ORB_SLAM2::ORBVocabulary* voc = new ORB_SLAM2::ORBVocabulary(); - - load_as_text(voc, "Vocabulary/ORBvoc.txt"); - save_as_binary(voc, "Vocabulary/ORBvoc.bin"); - - return 0; -} - -修改读入文件: -Thirdparty/DBoW2/DBoW2/TemplatedVocabulary.h -line 248 -添加 -// WYW ADD 2017.11.4 - /** - * Loads the vocabulary from a Binary file - * @param filename - */ - bool loadFromBinaryFile(const std::string &filename); - - /** - * Saves the vocabulary into a Binary file - * @param filename - */ - void saveToBinaryFile(const std::string &filename) const; - - -line 1460 -// WYW ADD 2017.11.4 读取二进制 词带 -// -------------------------------------------------------------------------- -template -bool TemplatedVocabulary::loadFromBinaryFile(const std::string &filename) { - fstream f; - f.open(filename.c_str(), ios_base::in|ios::binary); - unsigned int nb_nodes, size_node; - f.read((char*)&nb_nodes, sizeof(nb_nodes)); - f.read((char*)&size_node, sizeof(size_node)); - f.read((char*)&m_k, sizeof(m_k)); - f.read((char*)&m_L, sizeof(m_L)); - f.read((char*)&m_scoring, sizeof(m_scoring)); - f.read((char*)&m_weighting, sizeof(m_weighting)); - createScoringObject(); - - m_words.clear(); - m_words.reserve(pow((double)m_k, (double)m_L + 1)); - m_nodes.clear(); - m_nodes.resize(nb_nodes+1); - m_nodes[0].id = 0; - char buf[size_node]; int nid = 1; - while (!f.eof()) { - f.read(buf, size_node); - m_nodes[nid].id = nid; - // FIXME - const int* ptr=(int*)buf; - m_nodes[nid].parent = *ptr; - //m_nodes[nid].parent = *(const int*)buf; - m_nodes[m_nodes[nid].parent].children.push_back(nid); - m_nodes[nid].descriptor = cv::Mat(1, F::L, CV_8U); - memcpy(m_nodes[nid].descriptor.data, buf+4, F::L); - m_nodes[nid].weight = *(float*)(buf+4+F::L); - if (buf[8+F::L]) { // is leaf - int wid = m_words.size(); - m_words.resize(wid+1); - m_nodes[nid].word_id = wid; - m_words[wid] = &m_nodes[nid]; - } - else - m_nodes[nid].children.reserve(m_k); - nid+=1; - } - f.close(); - return true; -} - -// -------------------------------------------------------------------------- -template -void TemplatedVocabulary::saveToBinaryFile(const std::string &filename) const { - fstream f; - f.open(filename.c_str(), ios_base::out|ios::binary); - unsigned int nb_nodes = m_nodes.size(); - float _weight; - unsigned int size_node = sizeof(m_nodes[0].parent) + F::L*sizeof(char) + sizeof(_weight) + sizeof(bool); - f.write((char*)&nb_nodes, sizeof(nb_nodes)); - f.write((char*)&size_node, sizeof(size_node)); - f.write((char*)&m_k, sizeof(m_k)); - f.write((char*)&m_L, sizeof(m_L)); - f.write((char*)&m_scoring, sizeof(m_scoring)); - f.write((char*)&m_weighting, sizeof(m_weighting)); - for(size_t i=1; i -bool has_suffix(const std::string &str, const std::string &suffix) { - std::size_t index = str.find(suffix, str.size() - suffix.size()); - return (index != std::string::npos); -} - -line 68 -/////// //////////////////////////////////// -//// wyw 修改 2017.11.4 - clock_t tStart = clock(); - mpVocabulary = new ORBVocabulary(); - //bool bVocLoad = mpVocabulary->loadFromTextFile(strVocFile); - bool bVocLoad = false; // chose loading method based on file extension - if (has_suffix(strVocFile, ".txt")) - bVocLoad = mpVocabulary->loadFromTextFile(strVocFile);//txt格式打开 - else - bVocLoad = mpVocabulary->loadFromBinaryFile(strVocFile);//bin格式打开 - - if(!bVocLoad) - { - cerr << "Wrong path to vocabulary. " << endl; - cerr << "Failed to open at: " << strVocFile << endl; - exit(-1); - } - //cout << "Vocabulary loaded!" << endl << endl; - printf("Vocabulary loaded in %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);//显示文件载入时间 - - - - -单目SLAM: -例如,我自己的电脑上,该命令变为: -./Examples/Monocular/mono_tum Vocabulary/ORBvoc.txt Examples/Monocular/TUM1.yaml /home/ewenwan/ewenwan/learn/vSLAM/test/vSLAM/ch9project/date/rgbd_dataset_freiburg1_xyz - -载入二进制词带 -./Examples/Monocular/mono_tum Vocabulary/ORBvoc.bin Examples/Monocular/TUM1.yaml /home/ewenwan/ewenwan/learn/vSLAM/test/vSLAM/ch9project/date/rgbd_dataset_freiburg1_xyz - - - -双目测试 -./Examples/Stereo/stereo_euroc Vocabulary/ORBvoc.txt Examples/Stereo/EuRoC.yaml /home/ewenwan/ewenwan/learn/vSLAM/test/vSLAM/ch9project/date/ /cam0/data /home/ewenwan/ewenwan/learn/vSLAM/test/vSLAM/ch9project/date/ /cam1/data Examples/Stereo/EuRoC_TimeStamps/V102.txt -载入二进制词带 -./Examples/Stereo/stereo_euroc Vocabulary/ORBvoc.bin Examples/Stereo/EuRoC.yaml /home/ewenwan/ewenwan/learn/vSLAM/test/vSLAM/ch9project/date/ /cam0/data /home/ewenwan/ewenwan/learn/vSLAM/test/vSLAM/ch9project/date/ /cam1/data Examples/Stereo/EuRoC_TimeStamps/V102.txt - - -ros下的工程: -http://blog.csdn.net/sinat_31802439/article/details/52331465 添加稠密地图 -https://pan.baidu.com/s/1miDA952 - - -manifest.xml >>>> package.xml - - - - ros_orb #####包名 - 0.0.1 #####版本 - ORB_SLAM2#####工程描述 - EWenWan ####作者 - Raul Mur-Artal##### 维护 - GPLv3 ####开源协议 - - catkin #### 编译工具以来 - - roscpp #### 编译依赖 - pcl - tf - sensor_msgs - image_transport - message_filters - cv_bridge - cmake_modules - - roscpp #### 运行依赖 - pcl - tf - sensor_msgs - image_transport - message_filters - cv_bridge - - - - -编译信息文件 -CMakeLists.txt - -cmake_minimum_required(VERSION 2.8.3) ### cmake版本限制 - -project(ros_orb)##工程名 -find_package(catkin REQUIRED COMPONENTS###依赖包 - roscpp - sensor_msgs - image_transport - message_filters - cv_bridge - cmake_modules) - -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -O3 -march=native ") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -O3 -march=native") - -### ORB_SLAM2的路径 -set(CODE_SOURCE_DIR /home/ewenwan/ewenwan/learn/vSLAM/test/vSLAM/ch9project/oRB_SLAM2/Examples/ROS/ORB_SLAM2) - -# Check C++11 or C++0x support -include(CheckCXXCompilerFlag) -CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) -CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) -if(COMPILER_SUPPORTS_CXX11) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") - add_definitions(-DCOMPILEDWITHC11) - message(STATUS "Using flag -std=c++11.") -elseif(COMPILER_SUPPORTS_CXX0X) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") - add_definitions(-DCOMPILEDWITHC0X) - message(STATUS "Using flag -std=c++0x.") -else() - message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") -endif() - - -LIST(APPEND CMAKE_MODULE_PATH ${CODE_SOURCE_DIR}/../../../cmake_modules)## ORB_SLAM2的编译文件 FindEigen3.cmake - -find_package(OpenCV 2.4.3 REQUIRED) -find_package(Eigen3 3.1.0 REQUIRED) -find_package(Pangolin REQUIRED) -find_package( G2O REQUIRED ) -find_package( PCL 1.7 REQUIRED ) - -catkin_package() ###ros包类型说明 - -include_directories( -${CODE_SOURCE_DIR} ### ORB_SLAM2的路径 -${CODE_SOURCE_DIR}/../../../ -${CODE_SOURCE_DIR}/../../../include -${Pangolin_INCLUDE_DIRS} -${PCL_INCLUDE_DIRS} -${EIGEN3_INCLUDE_DIR} -) -add_definitions( ${PCL_DEFINITIONS} ) -link_directories( ${PCL_LIBRARY_DIRS} ) - -set(LIBS -${catkin_LIBRARIES} -${OpenCV_LIBS} -${EIGEN3_LIBS} -${PCL_LIBRARIES} -${Pangolin_LIBRARIES} -${CODE_SOURCE_DIR}/../../../Thirdparty/DBoW2/lib/libDBoW2.so -#g2o_core g2o_types_slam3d g2o_solver_csparse g2o_stuff g2o_csparse_extension g2o_types_sim3 g2o_types_sba -${CODE_SOURCE_DIR}/../../../Thirdparty/g2o/lib/libg2o.so -${CODE_SOURCE_DIR}/../../../lib/libORB_SLAM2.so -) - -# Node for monocular camera 单目相机 -add_executable(mono -src/ros_mono.cc -) -target_link_libraries(mono -${LIBS} -) -# 单目相机 Augmented Reality 增强现实 -#add_executable(monoAR -#src/AR/ros_mono_ar.cc -#src/AR/ViewerAR.h -#src/AR/ViewerAR.cc -#) -#target_link_libraries(mono -#${LIBS} -#) - -# Node for RGB-D camera 深度相机 -add_executable(rgbd -src/ros_rgbd.cc -) -target_link_libraries(rgbd -${LIBS} -) - -# Node for stereo camera 双目立体相机 -add_executable(stereo -src/ros_stereo.cc -) -target_link_libraries(stereo -${LIBS} -) - -cd catkin_ws -catkin_make - -运行单目相机SLAM节点 -rosrun ros_orb mono Vocabulary/ORBvoc.bin Examples/Monocular/TUM1.yaml /home/ewenwan/ewenwan/learn/vSLAM/test/vSLAM/ch9project/date/rgbd_dataset_freiburg1_xyz - - - - -################# -######################## -lsd-slam 直接法稠密点云slam Large Scale Direct Monocular -######################################## -#################### - -http://www.luohanjie.com/2017-03-17/ubuntu-install-lsd-slam.html -https://vision.in.tum.de/research/vslam/lsdslam -https://www.cnblogs.com/hitcm/p/4907536.html -https://github.com/tum-vision/lsd_slam - - -官方编译方法[1] -rosmake 编译 -sudo apt-get install python-rosinstall -sudo apt-get install ros-indigo-libg2o ros-indigo-cv-bridge liblapack-dev libblas-dev freeglut3-dev libqglviewer-dev libsuitesparse-dev libx11-dev -mkdir ~/SLAM/Code/rosbuild_ws -cd ~/SLAM/Code/rosbuild_ws -roses init . /opt/ros/indigo -mkdir package_dir -roses set ~/SLAM/Code/rosbuild_ws/package_dir -t . -echo "source ~/SLAM/Code/rosbuild_ws/setup.bash" >> ~/.bashrc -bash -cd package_dir -git clone https://github.com/tum-vision/lsd_slam.git lsd_slam -rosmake lsd_slam - - -使用catkin对LSD-SLAM进行编译 - -mkdir -p ~/catkin_ws/src -git clone https://github.com/tum-vision/lsd_slam.git -cd lsd_slam -git checkout catkin - -对lsd_slam/lsd_slam_viewer和lsd_slam/lsd_slam_core文件夹下的package.xml中添加: -cmake_modules -cmake_modules - -对lsd_slam/lsd_slam_viewer和lsd_slam/lsd_slam_core文件夹下的CMakeFiles.txt中添加: -find_package(cmake_modules REQUIRED) -find_package(OpenCV 3.0 QUIET) #support opencv3 -if(NOT OpenCV_FOUND) - find_package(OpenCV 2.4.3 QUIET) - if(NOT OpenCV_FOUND) - message(FATAL_ERROR "OpenCV > 2.4.3 not found.") - endif() -endif() - - -并且在所有的target_link_libraries中添加X11 ${OpenCV_LIBS},如: -target_link_libraries(lsdslam -${FABMAP_LIB} -${G2O_LIBRARIES} -${catkin_LIBRARIES} -${OpenCV_LIBS} -sparse cxsparse X11 -) - -然后开始编译: -cd ~/catkin_ws/ -catkin_make - - -下载测试数据 474MB 日志回放 -vmcremers8.informatik.tu-muenchen.de/lsd/LSD_room.bag.zip -解压 - -打开一个终端: -roscoe - -打开另外一个终端: -cd ~/catkin_ws/ -source devel/setup.sh -rosrun lsd_slam_viewer viewer - -打开另外一个终端: -cd ~/catkin_ws/ -source devel/setup.sh -rosrun lsd_slam_core live_slam image:=/image_raw camera_info:=/camera_info - -打开另外一个终端: -cd ~/catkin_ws/ -rosbag play ~/LSD_room.bag ###回放日志 即将之前的数据按话题发布 - - - - - -使用摄像头运行LSD_SLAM -安装驱动[4]: -cd ~/catkin_ws/ -source devel/setup.sh -cd ~/catkin_ws/src -git clone https://github.com/ktossell/camera_umd.git -cd .. -catkin_make -roscd uvc_camera/launch/ -roslaunch ./camera_node.launch - -camera_node.launch文件[5],如: - - - - - - - - - - - - - - - - - -注意官方程序默认分辨率为640*480。 - -打开一个窗口 -运行roscore; - -打开另外一个窗口: -cd ~/catkin_ws/ -source devel/setup.sh -rosrun lsd_slam_viewer viewer - - -再打开另外一个窗口: -cd ~/catkin_ws/ -source devel/setup.sh -roslaunch uvc_camera camera_node.launch - -再打开另外一个窗口: -rosrun lsd_slam_core live_slam /image:=image_raw _calib:= -校正文件calibration_file可参考lsd_catkin_ws/src/lsd_slam/lsd_slam_core/calib中的cfg文件。 - - - -########################### -################################# -##################################### -DSO: Direct Sparse Odometry 直接法稀疏点云 SLAM -https://github.com/JakobEngel/dso - - -1.下载DSO源代码到相应文件路径,比如我的文件路径为/home/hyj/DSO -git clone https://github.com/JakobEngel/dso dso -2.安装suitesparse and eigen3 (必需) - sudo apt-get install libsuitesparse-dev libeigen3-dev - -3.安装opencv. DSO对opencv依赖很少,仅仅用于读或写图像等一些简单的操作。 - sudo apt-get install libopencv-dev - -4.安装pangolin. 强烈推荐安装,考虑到ORB_SLAM中也选择pangolin作为显 示工具,而使用也非常方便,因此建议大家学习。 安装教程请移步pangolin的github主页 - -5.安装ziplib. 建议安装,DSO用这个库来解压读取数据集压缩包中的图片,这样就不要每次都把下再的图片数据集进行解压了。 - sudo apt-get install zlib1g-dev - cd thirdparty #找到DSO所在文件路径,切换到thirdparty文件夹下 - tar -zxvf libzip-1.1.1.tar.gz - cd libzip-1.1.1/./configure - make - sudo make install - sudo cp lib/zipconf.h /usr/local/include/zipconf.h - -6.编译DSO. - cd /home/hyj/DSO/dso - mkdir build - cd build - cmake .. - make -j -至此,不出意外的话,我们就可以很顺利的完成了DOS的安装。 - - - - - - - - - -############################## -################################### -Pangolin 可视化库的使用 -参考地址: -【1】Pangolin:https://github.com/stevenlovegrove/Pangolin -【2】Pangolin安装问题:http://www.cnblogs.com/liufuqiang/p/5618335.html -【3】Pangolin的Example:https://github.com/stevenlovegrove/Pangolin/tree/master/examples -【4】Pangolin的使用:http://docs.ros.org/fuerte/api/pangolin_wrapper/html/namespacepangolin.html -【5】特性:http://www.stevenlovegrove.com/?id=44 - -https://www.cnblogs.com/shhu1993/p/6814714.html - - - diff --git "a/vSLAM/ch9project/slam\345\267\245\347\250\213.txt~" "b/vSLAM/ch9project/slam\345\267\245\347\250\213.txt~" deleted file mode 100644 index 5d94fd21..00000000 --- "a/vSLAM/ch9project/slam\345\267\245\347\250\213.txt~" +++ /dev/null @@ -1,481 +0,0 @@ - - -1、ORBSLAM2 -ORBSLAM2在Ubuntu14.04上详细配置流程 -http://blog.csdn.net/zzlyw/article/details/54730830 -1 安装必要工具 -首先,有两个工具是需要提前安装的。即cmake和git。 -sudo apt-get install cmake -sudo apt-get install git - -2 安装Pangolin,用于可视化和用户接口 -安装依赖项: -sudo apt-get install libglew-dev -sudo apt-get install libpython2.7-dev -sudo apt-get install build-essential - -先转到一个要存储Pangolin的路径下,例如~/Documents,然后 -git clone https://github.com/stevenlovegrove/Pangolin.git -cd Pangolin -mkdir build -cd build -cmake .. -make -j -sudo make install - - -3 安装OpenCV - -最低的OpenCV版本为2.4.3,建议采用OpenCV 2.4.11或者OpenCV 3.2.0。从OpenCV官网下载OpenCV2.4.11。然后安装依赖项: - -sudo apt-get install libgtk2.0-dev -sudo apt-get install pkg-config - -将下载的OpenCV解压到自己的指定目录,然后cd到OpenCV的目录下。 -cd ~/Downloads/opencv-2.4.11 -mkdir release -cd release -cmake -D CMAKE_BUILD_TYPE=RELEASE -DCMAKE_INSTALL_PREFIX=/usr/local .. -make -sudo make install - - -4 安装Eigen3 - -最低要求版本为3.1.0。在http://eigen.tuxfamily.org 下载Eigen3的最新版本, -一般是一个压缩文件,下载后解压,然后cd到Eigen3的根目录下。 - -mkdir build -cd build -cmake .. -make -sudo make install - - -5 安装ORBSLAM2 - -先转到自己打算存储ORBSLAM2工程的路径,然后执行下列命令 -git clone https://github.com/raulmur/ORB_SLAM2.git oRB_SLAM2 -cd ORB_SLAM2 -修改编译 线程数(不然编译时可能会卡住): -vim build.sh -最后 make -j >>> make -j4 - -sudo chmod 777 build.sh -./build.sh - - -之后会在lib文件夹下生成libORB_SLAM2.so, -并且在Examples文件夹下生成 -mono_tum,mono_kitti, mono_euroc in Examples/Monocular 单目 , -rgbd_tum in Examples/Monocular RGB-D, -stereo_kitti 和 stereo_euroc in Examples/Stereo 双目立体。 - - -数据集: -KITTI dataset 对于 单目 stereo 或者 双目 monocular -http://www.cvlibs.net/datasets/kitti/eval_odometry.php - -EuRoC dataset 对于 单目 stereo 或者 双目 monocular -http://projects.asl.ethz.ch/datasets/doku.php?id=kmavvisualinertialdatasets - -TUM dataset 对于 RGB-D 或者 单目monocular -https://vision.in.tum.de/data/datasets/rgbd-dataset - - -论文: -ORB-SLAM: -[Monocular] Raúl Mur-Artal, J. M. M. Montiel and Juan D. Tardós. ORB-SLAM: A Versatile and Accurate Monocular SLAM System. -IEEE Transactions on Robotics, vol. 31, no. 5, pp. 1147-1163, 2015. (2015 IEEE Transactions on Robotics Best Paper Award). -http://webdiis.unizar.es/%7Eraulmur/MurMontielTardosTRO15.pdf - -ORB-SLAM2: -[Stereo and RGB-D] Raúl Mur-Artal and Juan D. Tardós. ORB-SLAM2: an Open-Source SLAM System for Monocular, Stereo and RGB-D Cameras. -IEEE Transactions on Robotics, vol. 33, no. 5, pp. 1255-1262, 2017. -https://128.84.21.199/pdf/1610.06475.pdf - -词袋模型: -[DBoW2 Place Recognizer] Dorian Gálvez-López and Juan D. Tardós. Bags of Binary Words for Fast Place Recognition in Image Sequences. -IEEE Transactions on Robotics, vol. 28, no. 5, pp. 1188-1197, 2012. -http://doriangalvez.com/papers/GalvezTRO12.pdf - - -单目测试 -在http://vision.in.tum.de/data/datasets/rgbd-dataset/download下载一个序列,并解压。 -转到ORBSLAM2文件夹下,执行下面的命令。 -根据下载的视频序列freiburg1, freiburg2 和 freiburg3将TUMX.yaml分别转换为对应的 TUM1.yaml 或 TUM2.yaml 或 TUM3.yaml -(相机参数文件)。 -将PATH_TO_SEQUENCE_FOLDER 更改为解压的视频序列文件夹。 -./Examples/Monocular/mono_tum Vocabulary/ORBvoc.txt Examples/Monocular/TUMX.yaml PATH_TO_SEQUENCE_FOLDER - 解压的视频序列文件夹 - -双目测试 -在 http://projects.asl.ethz.ch/datasets/doku.php?id=kmavvisualinertialdatasets 下载一个序列 Vicon Room 1 02 大小1.2GB -./Examples/Stereo/stereo_euroc Vocabulary/ORBvoc.txt Examples/Stereo/EuRoC.yaml PATH_TO_SEQUENCE/cam0/data PATH_TO_SEQUENCE/cam1/data Examples/Stereo/EuRoC_TimeStamps/SEQUENCE.txt - - -################################### -词带 - orb词带txt载入太慢,看到有人转换为binary,速度超快,试了下,确实快. -链接:https://github.com/raulmur/ORB_SLAM2/pull/21/commits/4122702ced85b20bd458d0e74624b9610c19f8cc -Vocabulary/ORBvoc.txt >>> Vocabulary/ORBvoc.bin -################################################################ -#CMakeLists.txt -最后添加 -## .txt >>> .bin 文件转换 -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/tools) -add_executable(bin_vocabulary -tools/bin_vocabulary.cc) -target_link_libraries(bin_vocabulary ${PROJECT_NAME}) - -# build.sh 转换 .txt >>> .bin -最后添加 -cd .. -echo "Converting vocabulary to binary" -./tools/bin_vocabulary - -#### 新建转换文件 -tools/bin_vocabulary.cc - -#include -#include "ORBVocabulary.h" -using namespace std; - -bool load_as_text(ORB_SLAM2::ORBVocabulary* voc, const std::string infile) { - clock_t tStart = clock(); - bool res = voc->loadFromTextFile(infile); - printf("Loading fom text: %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); - return res; -} - -void load_as_xml(ORB_SLAM2::ORBVocabulary* voc, const std::string infile) { - clock_t tStart = clock(); - voc->load(infile); - printf("Loading fom xml: %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); -} - -void load_as_binary(ORB_SLAM2::ORBVocabulary* voc, const std::string infile) { - clock_t tStart = clock(); - voc->loadFromBinaryFile(infile); - printf("Loading fom binary: %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); -} - -void save_as_xml(ORB_SLAM2::ORBVocabulary* voc, const std::string outfile) { - clock_t tStart = clock(); - voc->save(outfile); - printf("Saving as xml: %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); -} - -void save_as_text(ORB_SLAM2::ORBVocabulary* voc, const std::string outfile) { - clock_t tStart = clock(); - voc->saveToTextFile(outfile); - printf("Saving as text: %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); -} - -void save_as_binary(ORB_SLAM2::ORBVocabulary* voc, const std::string outfile) { - clock_t tStart = clock(); - voc->saveToBinaryFile(outfile); - printf("Saving as binary: %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); -} - -int main(int argc, char **argv) { - cout << "BoW load/save benchmark" << endl; - ORB_SLAM2::ORBVocabulary* voc = new ORB_SLAM2::ORBVocabulary(); - - load_as_text(voc, "Vocabulary/ORBvoc.txt"); - save_as_binary(voc, "Vocabulary/ORBvoc.bin"); - - return 0; -} - -修改读入文件: -Thirdparty/DBoW2/DBoW2/TemplatedVocabulary.h -line 248 -添加 -// WYW ADD 2017.11.4 - /** - * Loads the vocabulary from a Binary file - * @param filename - */ - bool loadFromBinaryFile(const std::string &filename); - - /** - * Saves the vocabulary into a Binary file - * @param filename - */ - void saveToBinaryFile(const std::string &filename) const; - - -line 1460 -// WYW ADD 2017.11.4 读取二进制 词带 -// -------------------------------------------------------------------------- -template -bool TemplatedVocabulary::loadFromBinaryFile(const std::string &filename) { - fstream f; - f.open(filename.c_str(), ios_base::in|ios::binary); - unsigned int nb_nodes, size_node; - f.read((char*)&nb_nodes, sizeof(nb_nodes)); - f.read((char*)&size_node, sizeof(size_node)); - f.read((char*)&m_k, sizeof(m_k)); - f.read((char*)&m_L, sizeof(m_L)); - f.read((char*)&m_scoring, sizeof(m_scoring)); - f.read((char*)&m_weighting, sizeof(m_weighting)); - createScoringObject(); - - m_words.clear(); - m_words.reserve(pow((double)m_k, (double)m_L + 1)); - m_nodes.clear(); - m_nodes.resize(nb_nodes+1); - m_nodes[0].id = 0; - char buf[size_node]; int nid = 1; - while (!f.eof()) { - f.read(buf, size_node); - m_nodes[nid].id = nid; - // FIXME - const int* ptr=(int*)buf; - m_nodes[nid].parent = *ptr; - //m_nodes[nid].parent = *(const int*)buf; - m_nodes[m_nodes[nid].parent].children.push_back(nid); - m_nodes[nid].descriptor = cv::Mat(1, F::L, CV_8U); - memcpy(m_nodes[nid].descriptor.data, buf+4, F::L); - m_nodes[nid].weight = *(float*)(buf+4+F::L); - if (buf[8+F::L]) { // is leaf - int wid = m_words.size(); - m_words.resize(wid+1); - m_nodes[nid].word_id = wid; - m_words[wid] = &m_nodes[nid]; - } - else - m_nodes[nid].children.reserve(m_k); - nid+=1; - } - f.close(); - return true; -} - -// -------------------------------------------------------------------------- -template -void TemplatedVocabulary::saveToBinaryFile(const std::string &filename) const { - fstream f; - f.open(filename.c_str(), ios_base::out|ios::binary); - unsigned int nb_nodes = m_nodes.size(); - float _weight; - unsigned int size_node = sizeof(m_nodes[0].parent) + F::L*sizeof(char) + sizeof(_weight) + sizeof(bool); - f.write((char*)&nb_nodes, sizeof(nb_nodes)); - f.write((char*)&size_node, sizeof(size_node)); - f.write((char*)&m_k, sizeof(m_k)); - f.write((char*)&m_L, sizeof(m_L)); - f.write((char*)&m_scoring, sizeof(m_scoring)); - f.write((char*)&m_weighting, sizeof(m_weighting)); - for(size_t i=1; i -bool has_suffix(const std::string &str, const std::string &suffix) { - std::size_t index = str.find(suffix, str.size() - suffix.size()); - return (index != std::string::npos); -} - -line 68 -/////// //////////////////////////////////// -//// wyw 修改 2017.11.4 - clock_t tStart = clock(); - mpVocabulary = new ORBVocabulary(); - //bool bVocLoad = mpVocabulary->loadFromTextFile(strVocFile); - bool bVocLoad = false; // chose loading method based on file extension - if (has_suffix(strVocFile, ".txt")) - bVocLoad = mpVocabulary->loadFromTextFile(strVocFile);//txt格式打开 - else - bVocLoad = mpVocabulary->loadFromBinaryFile(strVocFile);//bin格式打开 - - if(!bVocLoad) - { - cerr << "Wrong path to vocabulary. " << endl; - cerr << "Failed to open at: " << strVocFile << endl; - exit(-1); - } - //cout << "Vocabulary loaded!" << endl << endl; - printf("Vocabulary loaded in %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);//显示文件载入时间 - - - - -单目SLAM: -例如,我自己的电脑上,该命令变为: -./Examples/Monocular/mono_tum Vocabulary/ORBvoc.txt Examples/Monocular/TUM1.yaml /home/ewenwan/ewenwan/learn/vSLAM/test/vSLAM/ch9project/date/rgbd_dataset_freiburg1_xyz - -载入二进制词带 -./Examples/Monocular/mono_tum Vocabulary/ORBvoc.bin Examples/Monocular/TUM1.yaml /home/ewenwan/ewenwan/learn/vSLAM/test/vSLAM/ch9project/date/rgbd_dataset_freiburg1_xyz - - - -双目测试 -./Examples/Stereo/stereo_euroc Vocabulary/ORBvoc.txt Examples/Stereo/EuRoC.yaml /home/ewenwan/ewenwan/learn/vSLAM/test/vSLAM/ch9project/date/ /cam0/data /home/ewenwan/ewenwan/learn/vSLAM/test/vSLAM/ch9project/date/ /cam1/data Examples/Stereo/EuRoC_TimeStamps/V102.txt -载入二进制词带 -./Examples/Stereo/stereo_euroc Vocabulary/ORBvoc.bin Examples/Stereo/EuRoC.yaml /home/ewenwan/ewenwan/learn/vSLAM/test/vSLAM/ch9project/date/ /cam0/data /home/ewenwan/ewenwan/learn/vSLAM/test/vSLAM/ch9project/date/ /cam1/data Examples/Stereo/EuRoC_TimeStamps/V102.txt - - -ros下的工程: -http://blog.csdn.net/sinat_31802439/article/details/52331465 添加稠密地图 -https://pan.baidu.com/s/1miDA952 - - -manifest.xml >>>> package.xml - - - - ros_orb #####包名 - 0.0.1 #####版本 - ORB_SLAM2#####工程描述 - EWenWan ####作者 - Raul Mur-Artal##### 维护 - GPLv3 ####开源协议 - - catkin #### 编译工具以来 - - roscpp #### 编译依赖 - pcl - tf - sensor_msgs - image_transport - message_filters - cv_bridge - cmake_modules - - roscpp #### 运行依赖 - pcl - tf - sensor_msgs - image_transport - message_filters - cv_bridge - - - - -编译信息文件 -CMakeLists.txt - -cmake_minimum_required(VERSION 2.8.3) ### cmake版本限制 - -project(ros_orb)##工程名 -find_package(catkin REQUIRED COMPONENTS###依赖包 - roscpp - sensor_msgs - image_transport - message_filters - cv_bridge - cmake_modules) - -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -O3 -march=native ") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -O3 -march=native") - -### ORB_SLAM2的路径 -set(CODE_SOURCE_DIR /home/ewenwan/ewenwan/learn/vSLAM/test/vSLAM/ch9project/oRB_SLAM2/Examples/ROS/ORB_SLAM2) - -# Check C++11 or C++0x support -include(CheckCXXCompilerFlag) -CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) -CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) -if(COMPILER_SUPPORTS_CXX11) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") - add_definitions(-DCOMPILEDWITHC11) - message(STATUS "Using flag -std=c++11.") -elseif(COMPILER_SUPPORTS_CXX0X) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") - add_definitions(-DCOMPILEDWITHC0X) - message(STATUS "Using flag -std=c++0x.") -else() - message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") -endif() - - -LIST(APPEND CMAKE_MODULE_PATH ${CODE_SOURCE_DIR}/../../../cmake_modules)## ORB_SLAM2的编译文件 FindEigen3.cmake - -find_package(OpenCV 2.4.3 REQUIRED) -find_package(Eigen3 3.1.0 REQUIRED) -find_package(Pangolin REQUIRED) -find_package( G2O REQUIRED ) -find_package( PCL 1.7 REQUIRED ) - -catkin_package() ###ros包类型说明 - -include_directories( -${CODE_SOURCE_DIR} ### ORB_SLAM2的路径 -${CODE_SOURCE_DIR}/../../../ -${CODE_SOURCE_DIR}/../../../include -${Pangolin_INCLUDE_DIRS} -${PCL_INCLUDE_DIRS} -${EIGEN3_INCLUDE_DIR} -) -add_definitions( ${PCL_DEFINITIONS} ) -link_directories( ${PCL_LIBRARY_DIRS} ) - -set(LIBS -${catkin_LIBRARIES} -${OpenCV_LIBS} -${EIGEN3_LIBS} -${PCL_LIBRARIES} -${Pangolin_LIBRARIES} -${CODE_SOURCE_DIR}/../../../Thirdparty/DBoW2/lib/libDBoW2.so -#g2o_core g2o_types_slam3d g2o_solver_csparse g2o_stuff g2o_csparse_extension g2o_types_sim3 g2o_types_sba -${CODE_SOURCE_DIR}/../../../Thirdparty/g2o/lib/libg2o.so -${CODE_SOURCE_DIR}/../../../lib/libORB_SLAM2.so -) - -# Node for monocular camera 单目相机 -add_executable(mono -src/ros_mono.cc -) -target_link_libraries(mono -${LIBS} -) -# 单目相机 Augmented Reality 增强现实 -#add_executable(monoAR -#src/AR/ros_mono_ar.cc -#src/AR/ViewerAR.h -#src/AR/ViewerAR.cc -#) -#target_link_libraries(mono -#${LIBS} -#) - -# Node for RGB-D camera 深度相机 -add_executable(rgbd -src/ros_rgbd.cc -) -target_link_libraries(rgbd -${LIBS} -) - -# Node for stereo camera 双目立体相机 -add_executable(stereo -src/ros_stereo.cc -) -target_link_libraries(stereo -${LIBS} -) - -cd catkin_ws -catkin_make - -运行单目相机SLAM节点 -rosrun ros_orb Mono Vocabulary/ORBvoc.bin Examples/Monocular/TUM1.yaml /home/ewenwan/ewenwan/learn/vSLAM/test/vSLAM/ch9project/date/rgbd_dataset_freiburg1_xyz - - - - - - - diff --git "a/vSLAM/ch9project/\345\267\245\347\250\213\347\273\223\346\236\204.txt" "b/vSLAM/ch9project/\345\267\245\347\250\213\347\273\223\346\236\204.txt" deleted file mode 100644 index c3bdbb34..00000000 --- "a/vSLAM/ch9project/\345\267\245\347\250\213\347\273\223\346\236\204.txt" +++ /dev/null @@ -1,22 +0,0 @@ -1. /bin 存放可执行的二进制文件 -2. /include/myslam 存放slam工程模块的头文件,只要是.h 引用头文件时时 - 需写 include "myslam/xxx.h"不容易和其他库混淆 -3. /src 存放源代码文件 主要是.cpp文件 -4. /test 存放测试用的文件 也是 .cpp文件 -5. /lib 存放编译好的库文件 -6. /config 存放配置文件 -7. /cmake_modules 存放第三方库的cmake文件 例如使用g2o eigen库时 - - - -0.1版本 类 -Frame 帧 Frame::Ptr frame -Camera 相机模型 Camera::Ptr camera_ -MapPoint 特征点/路标点 MapPoint::Ptr map_point -Map 管理特征点 保存所有的特征点/路标 和关键帧 -Config 提供配置参数 - - - - - diff --git "a/vSLAM/ch9project/\345\267\245\347\250\213\347\273\223\346\236\204.txt~" "b/vSLAM/ch9project/\345\267\245\347\250\213\347\273\223\346\236\204.txt~" deleted file mode 100644 index 3cf9d2cd..00000000 --- "a/vSLAM/ch9project/\345\267\245\347\250\213\347\273\223\346\236\204.txt~" +++ /dev/null @@ -1,22 +0,0 @@ -1. /bin 存放可执行的二进制文件 -2. /include/myslam 存放slam工程模块的头文件,只要是.h 引用头文件时时 - 需写 include "myslam/xxx.h"不容易和其他库混淆 -3. /src 存放源代码文件 主要是.cpp文件 -4. /test 存放测试用的文件 也是 .cpp文件 -5. /lib 存放编译好的库文件 -6. /config 存放配置文件 -7. /cmake_modules 存放第三方库的cmake文件 例如使用g2o eigen库时 - - - -0.1版本 类 -Frame 帧 -Camera 相机模型 -MapPoint 特征点/路标点 -Map 管理特征点 -Config 提供配置参数 - - - - - diff --git a/vSLAM/dso_slam/readme.md b/vSLAM/dso_slam/readme.md index 190c32ea..198a22d2 100644 --- a/vSLAM/dso_slam/readme.md +++ b/vSLAM/dso_slam/readme.md @@ -7,6 +7,12 @@ [安装](https://github.com/Ewenwan/MVision/blob/master/vSLAM/dso_slam/install.md) + +[TUM 德国 慕尼黑工业大学(Technische Universität München)](https://vision.in.tum.de/research/vslam/ldso) + +[高翔 带有回环检测sim3变换的的DSO LDSO](https://github.com/Ewenwan/LDSO) + + DSO属于稀疏直接法的视觉里程计。它不是完整的SLAM,因为它不包含回环检测、地图复用的功能。 因此,它不可避免地会出现累计误差,尽管很小,但不能消除。 diff --git "a/vSLAM/oRB_SLAM2/DBoW2\347\211\271\345\276\201\350\257\215\345\270\246.md" "b/vSLAM/oRB_SLAM2/DBoW2\347\211\271\345\276\201\350\257\215\345\270\246.md" new file mode 100644 index 00000000..8223899b --- /dev/null +++ "b/vSLAM/oRB_SLAM2/DBoW2\347\211\271\345\276\201\350\257\215\345\270\246.md" @@ -0,0 +1,24 @@ +# DBoW2特征词带 + DBoW2是一个对大量训练图像使用fast关键点+BRIEF描述子的方法提取特征, + 再将大量特征做K-mean++聚类形成一棵词典树的模型。 + 词典离线建立好之后,在实际应用过程之中, + 将每一幅待处理图像提取特征与词典树中的描述子相比较得到一些索引, + 从而可以提高搜索相似图像和得到图像之间特征匹配的效率。 + +# 代码分析 + + class BowVector: public std::map + // stl的map结构,key为wordId,value为 tfidf 中的tf + +## 聚类 + // 1. 从输入的数据点集合中随机选择一个点作为第一个聚类中心 + // 2. 对于数据集中的每一个点x,计算它与最近聚类中心(指已选择的聚类中心)的距离D(x)并保存在一个数组里, + // 然后把这些距离加起来得到Sum(D(x))。 + // 3. 选择一个新的数据点作为新的聚类中心,选择的原则是:D(x)较大的点,被选取作为聚类中心的概率较大 + // 实际做法:取一个0~Sum(D(x))之间的随机值Random,计算Sum(D(0),D(1)...D(j))>=Random,第j个点为种子点 + // 4. 重复2和3直到k个聚类中心被选出来 + // 5. 利用这k个初始的聚类中心来运行标准的k-means算法 + + + + diff --git a/vSLAM/oRB_SLAM2/readme.md b/vSLAM/oRB_SLAM2/readme.md index e157acd3..d74fba6b 100644 --- a/vSLAM/oRB_SLAM2/readme.md +++ b/vSLAM/oRB_SLAM2/readme.md @@ -4,10 +4,25 @@ [本文github链接](https://github.com/Ewenwan/MVision/blob/master/vSLAM/oRB_SLAM2/readme.md) -[orbslam2 + imu](https://github.com/Ewenwan/LearnVIORB) +[基于ORBSLAM2加入线特征重建 半稠密地图](https://github.com/Ewenwan/ORB_Line_SLAM) + +[orbslam2 单目imu](https://github.com/Ewenwan/LearnVIORB) + +[orbslam2 双目imu 地图保存 ](https://github.com/MRwangmaomao/ORB_SLAM2_SaveMap_Catkin) + +[RB-SLAM2-IMU-VIO 直接法加速 单目imu ](https://github.com/Ewenwan/ORB-YGZ-SLAM) [ORBSLAM2_with_pointcloud_map 添加一个可视化线程用来显示点云](https://github.com/Ewenwan/ORBSLAM2_with_pointcloud_map) +[ORB_SLAM2_SSD_Semantic 依据ssd目标检测的语义信息和点云信息 获取3d语义目标信息 构建3d语义地图](https://github.com/Ewenwan/ORB_SLAM2_SSD_Semantic) + +[ORB_SLAM2 + mask_rcnn 动态环境建图 ](https://github.com/Ewenwan/DynaSLAM) + +[maskFusion elasFusion+ mask_rcnn 动态物体跟踪重建 ](https://github.com/Ewenwan/maskfusion) + +[DS-SLAM ORB_SLAM2 + SegNet 动态语义 slam](https://arxiv.org/pdf/1809.08379.pdf) + +[ORB SLAM2 + 拓扑地图 路径规划导航](https://github.com/Ewenwan/Active-ORB-SLAM2) ORB-SLAM是一个基于特征点的实时单目SLAM系统,在大规模的、小规模的、室内室外的环境都可以运行。 该系统对剧烈运动也很鲁棒,支持宽基线的闭环检测和重定位,包括全自动初始化。 @@ -16,6 +31,9 @@ 由于ORB-SLAM系统是基于特征点的SLAM系统,故其能够实时计算出相机的轨线,并生成场景的稀疏三维重建结果。 ORB-SLAM2在ORB-SLAM的基础上,还支持标定后的双目相机和RGB-D相机。 + + + **系统框架** ![](https://img-blog.csdn.net/20161114115058814) diff --git a/vSLAM/oRB_SLAM2/src/FrameDrawer.cc b/vSLAM/oRB_SLAM2/src/FrameDrawer.cc index e23b86c2..d39bc63d 100644 --- a/vSLAM/oRB_SLAM2/src/FrameDrawer.cc +++ b/vSLAM/oRB_SLAM2/src/FrameDrawer.cc @@ -1,21 +1,6 @@ /** * This file is part of ORB-SLAM2. -* -* Copyright (C) 2014-2016 Raúl Mur-Artal (University of Zaragoza) -* For more information see -* -* ORB-SLAM2 is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* ORB-SLAM2 is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with ORB-SLAM2. If not, see . +* 获取帧 显示 图像+关键点==== */ #include "FrameDrawer.h" @@ -32,42 +17,44 @@ namespace ORB_SLAM2 FrameDrawer::FrameDrawer(Map* pMap):mpMap(pMap) { mState=Tracking::SYSTEM_NOT_READY; - mIm = cv::Mat(480,640,CV_8UC3, cv::Scalar(0,0,0)); + mIm = cv::Mat(480,640,CV_8UC3, cv::Scalar(0,0,0));// 初始化一个空的三通道图像 } cv::Mat FrameDrawer::DrawFrame() { cv::Mat im; - vector vIniKeys; // Initialization: KeyPoints in reference frame - vector vMatches; // Initialization: correspondeces with reference keypoints - vector vCurrentKeys; // KeyPoints in current frame - vector vbVO, vbMap; // Tracked MapPoints in current frame + vector vIniKeys; // 初始化参考帧关键点 Initialization: KeyPoints in reference frame + vector vMatches; // 匹配点 Initialization: correspondeces with reference keypoints + vector vCurrentKeys; // 当前帧关键点 KeyPoints in current frame + vector vbVO, vbMap; // 跟踪的关键点 Tracked MapPoints in current frame + // vbMap 匹配到地图上一个点 + // vbVO int state; // Tracking state //Copy variables within scoped mutex { - unique_lock lock(mMutex); + unique_lock lock(mMutex);// 对数据上锁==== state=mState; if(mState==Tracking::SYSTEM_NOT_READY) - mState=Tracking::NO_IMAGES_YET; + mState=Tracking::NO_IMAGES_YET;// 切换成 没有图像== - mIm.copyTo(im); + mIm.copyTo(im); // 有update函数从 tracer内拷贝过来====== if(mState==Tracking::NOT_INITIALIZED) { - vCurrentKeys = mvCurrentKeys; - vIniKeys = mvIniKeys; - vMatches = mvIniMatches; + vCurrentKeys = mvCurrentKeys;// 类对象 复制过来 + vIniKeys = mvIniKeys; // 初始关键帧 关键点 + vMatches = mvIniMatches; // 初始关键帧 关键帧匹配点 } else if(mState==Tracking::OK) { - vCurrentKeys = mvCurrentKeys; - vbVO = mvbVO; + vCurrentKeys = mvCurrentKeys;// 当前关键帧 关键点 + vbVO = mvbVO; // 跟踪到的 vbMap = mvbMap; } - else if(mState==Tracking::LOST) + else if(mState==Tracking::LOST)// 跟丢了,关键点就没有匹配上=== { - vCurrentKeys = mvCurrentKeys; + vCurrentKeys = mvCurrentKeys;// 只有 当前帧 检测到的关键点 } } // destroy scoped mutex -> release mutex @@ -75,7 +62,7 @@ cv::Mat FrameDrawer::DrawFrame() cvtColor(im,im,CV_GRAY2BGR); //Draw - if(state==Tracking::NOT_INITIALIZED) //INITIALIZING + if(state==Tracking::NOT_INITIALIZED) //INITIALIZING=====初始化==== { for(unsigned int i=0; iKeyFramesInMap(); - int nMPs = mpMap->MapPointsInMap(); - s << "KFs: " << nKFs << ", MPs: " << nMPs << ", Matches: " << mnTracked; + s << "LOCALIZATION | ";// 定位 + int nKFs = mpMap->KeyFramesInMap();// 地图中 关键帧数量 + int nMPs = mpMap->MapPointsInMap();// 地图中 地图点数量 + s << "KFs: " << nKFs << ", MPs: " << nMPs << ", current Matches: " << mnTracked; if(mnTrackedVO>0) - s << ", + VO matches: " << mnTrackedVO; + s << ", + current VO matches: " << mnTrackedVO; } else if(nState==Tracking::LOST) { @@ -155,49 +143,54 @@ void FrameDrawer::DrawTextInfo(cv::Mat &im, int nState, cv::Mat &imText) } int baseline=0; - cv::Size textSize = cv::getTextSize(s.str(),cv::FONT_HERSHEY_PLAIN,1,1,&baseline); + cv::Size textSize = cv::getTextSize(s.str(),cv::FONT_HERSHEY_PLAIN,1,1,&baseline);//文字 - imText = cv::Mat(im.rows+textSize.height+10,im.cols,im.type()); - im.copyTo(imText.rowRange(0,im.rows).colRange(0,im.cols)); - imText.rowRange(im.rows,imText.rows) = cv::Mat::zeros(textSize.height+10,im.cols,im.type()); - cv::putText(imText,s.str(),cv::Point(5,imText.rows-5),cv::FONT_HERSHEY_PLAIN,1,cv::Scalar(255,255,255),1,8); + imText = cv::Mat(im.rows+textSize.height+10,im.cols,im.type());// 图片扩展几行,用来显示文字========= + + im.copyTo(imText.rowRange(0,im.rows).colRange(0,im.cols));// 图像拷贝到 带文字框 的图像 + + imText.rowRange(im.rows,imText.rows) = cv::Mat::zeros(textSize.height+10,im.cols,im.type());// 上次文字区域 清空 + + cv::putText(imText,s.str(),cv::Point(5,imText.rows-5),cv::FONT_HERSHEY_PLAIN,1,cv::Scalar(255,255,255),1,8);// 更新字体===== } +// 从Track对象中 更新本 类内数据============================== void FrameDrawer::Update(Tracking *pTracker) { - unique_lock lock(mMutex); - pTracker->mImGray.copyTo(mIm); - mvCurrentKeys=pTracker->mCurrentFrame.mvKeys; - N = mvCurrentKeys.size(); + unique_lock lock(mMutex);// 上锁==== + pTracker->mImGray.copyTo(mIm);// 图像 + mvCurrentKeys=pTracker->mCurrentFrame.mvKeys;// 当前帧 关键帧 + N = mvCurrentKeys.size();// 关键帧数量 mvbVO = vector(N,false); mvbMap = vector(N,false); - mbOnlyTracking = pTracker->mbOnlyTracking; + mbOnlyTracking = pTracker->mbOnlyTracking;// 模式 if(pTracker->mLastProcessedState==Tracking::NOT_INITIALIZED) { - mvIniKeys=pTracker->mInitialFrame.mvKeys; - mvIniMatches=pTracker->mvIniMatches; + mvIniKeys=pTracker->mInitialFrame.mvKeys;// 初始化关键帧 关键点 + mvIniMatches=pTracker->mvIniMatches; // 匹配点==== } - else if(pTracker->mLastProcessedState==Tracking::OK) + + else if(pTracker->mLastProcessedState==Tracking::OK)// 跟踪ok { for(int i=0;imCurrentFrame.mvpMapPoints[i]; + MapPoint* pMP = pTracker->mCurrentFrame.mvpMapPoints[i];//当前帧的地图点 if(pMP) { - if(!pTracker->mCurrentFrame.mvbOutlier[i]) + if(!pTracker->mCurrentFrame.mvbOutlier[i])// 是否是外点 { - if(pMP->Observations()>0) + if(pMP->Observations()>0)// 该地图点也被其他 帧观测到,玩儿哦实实在在的地图点 mvbMap[i]=true; else - mvbVO[i]=true; + mvbVO[i]=true;// 没有被 观测到,只存在与上一帧===== } } } } - mState=static_cast(pTracker->mLastProcessedState); + mState=static_cast(pTracker->mLastProcessedState);// 跟踪器状态========= } } //namespace ORB_SLAM diff --git a/vSLAM/oRB_SLAM2/src/MapDrawer.cc b/vSLAM/oRB_SLAM2/src/MapDrawer.cc index 4d9990bc..4810284b 100644 --- a/vSLAM/oRB_SLAM2/src/MapDrawer.cc +++ b/vSLAM/oRB_SLAM2/src/MapDrawer.cc @@ -1,21 +1,8 @@ /** * This file is part of ORB-SLAM2. -* -* Copyright (C) 2014-2016 Raúl Mur-Artal (University of Zaragoza) -* For more information see -* -* ORB-SLAM2 is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* ORB-SLAM2 is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with ORB-SLAM2. If not, see . +* 地图显示 普通地图点 黑色 参考地图点红色 + 关键帧 蓝色 当前帧 绿色 + */ #include "MapDrawer.h" @@ -32,85 +19,108 @@ MapDrawer::MapDrawer(Map* pMap, const string &strSettingPath):mpMap(pMap) { cv::FileStorage fSettings(strSettingPath, cv::FileStorage::READ); - mKeyFrameSize = fSettings["Viewer.KeyFrameSize"]; - mKeyFrameLineWidth = fSettings["Viewer.KeyFrameLineWidth"]; - mGraphLineWidth = fSettings["Viewer.GraphLineWidth"]; - mPointSize = fSettings["Viewer.PointSize"]; - mCameraSize = fSettings["Viewer.CameraSize"]; - mCameraLineWidth = fSettings["Viewer.CameraLineWidth"]; - + mKeyFrameSize = fSettings["Viewer.KeyFrameSize"];//关键帧 线长 + mKeyFrameLineWidth = fSettings["Viewer.KeyFrameLineWidth"];//关键帧线宽 + mGraphLineWidth = fSettings["Viewer.GraphLineWidth"];// 关键帧连线宽度 + mPointSize = fSettings["Viewer.PointSize"];// 点大小 + mCameraSize = fSettings["Viewer.CameraSize"];// 当前帧 相机线长 + mCameraLineWidth = fSettings["Viewer.CameraLineWidth"];// 当前帧 相机线宽 + + /* + Viewer.KeyFrameSize: 0.05 + Viewer.KeyFrameLineWidth: 1 + Viewer.GraphLineWidth: 0.9 + Viewer.PointSize:2 + Viewer.CameraSize: 0.08 + Viewer.CameraLineWidth: 3 + Viewer.ViewpointX: 0 + Viewer.ViewpointY: -0.7 + Viewer.ViewpointZ: -1.8 + Viewer.ViewpointF: 500 + */ } + +// 显示点======普通点黑色===参考地图点红色===颜色可修改==== void MapDrawer::DrawMapPoints() { - const vector &vpMPs = mpMap->GetAllMapPoints(); - const vector &vpRefMPs = mpMap->GetReferenceMapPoints(); + const vector &vpMPs = mpMap->GetAllMapPoints();// 所有地图点 黑色 + const vector &vpRefMPs = mpMap->GetReferenceMapPoints();// 参考 地图点 红色=== - set spRefMPs(vpRefMPs.begin(), vpRefMPs.end()); + set spRefMPs(vpRefMPs.begin(), vpRefMPs.end());// set有序集合, 查找快!!!!! if(vpMPs.empty()) return; - glPointSize(mPointSize); + glPointSize(mPointSize);// 点大小 +// 开始添加点=========== glBegin(GL_POINTS); - glColor3f(0.0,0.0,0.0); + glColor3f(0.0,0.0,0.0);// 普通地图点 为黑色================rgb= - for(size_t i=0, iend=vpMPs.size(); iisBad() || spRefMPs.count(vpMPs[i])) + if(vpMPs[i]->isBad() || spRefMPs.count(vpMPs[i]))// 除去不好的 和 参考帧点 continue; - cv::Mat pos = vpMPs[i]->GetWorldPos(); - glVertex3f(pos.at(0),pos.at(1),pos.at(2)); + cv::Mat pos = vpMPs[i]->GetWorldPos();// 点的时间坐标 位姿 + glVertex3f(pos.at(0),pos.at(1),pos.at(2));// 顶点 } +// 结束添加点========= glEnd(); - glPointSize(mPointSize); + glPointSize(mPointSize);// 点大小 +// 开始添加点=========== glBegin(GL_POINTS); - glColor3f(1.0,0.0,0.0); + glColor3f(1.0,0.0,0.0);// 参考 地图点 显示红色============rgb======= for(set::iterator sit=spRefMPs.begin(), send=spRefMPs.end(); sit!=send; sit++) { if((*sit)->isBad()) - continue; + continue;// 除去不好的 cv::Mat pos = (*sit)->GetWorldPos(); - glVertex3f(pos.at(0),pos.at(1),pos.at(2)); + glVertex3f(pos.at(0),pos.at(1),pos.at(2));// 添加点 } - +// 结束添加点========= glEnd(); } +// 显示关键帧================蓝色============================ void MapDrawer::DrawKeyFrames(const bool bDrawKF, const bool bDrawGraph) { const float &w = mKeyFrameSize; const float h = w*0.75; const float z = w*0.6; - const vector vpKFs = mpMap->GetAllKeyFrames(); + const vector vpKFs = mpMap->GetAllKeyFrames();// 所有关键帧====== if(bDrawKF) { - for(size_t i=0; iGetPoseInverse().t(); - - glPushMatrix(); + KeyFrame* pKF = vpKFs[i];// 关键帧 + cv::Mat Twc = pKF->GetPoseInverse().t();// 帧到世界坐标系==== + glPushMatrix();// 矩阵 glMultMatrixf(Twc.ptr(0)); - glLineWidth(mKeyFrameLineWidth); - glColor3f(0.0f,0.0f,1.0f); - glBegin(GL_LINES); - glVertex3f(0,0,0); - glVertex3f(w,h,z); + glLineWidth(mKeyFrameLineWidth);//关键帧线宽 + glColor3f(0.0f,0.0f,1.0f);// rgb 蓝色 帧位姿 + glBegin(GL_LINES); // 开始添加线======= + +// 相机光心 与 顶点 连线======== + glVertex3f(0,0,0); // 相机光心 + glVertex3f(w,h,z); // 宽 高 深度 + glVertex3f(0,0,0); glVertex3f(w,-h,z); + glVertex3f(0,0,0); glVertex3f(-w,-h,z); + glVertex3f(0,0,0); glVertex3f(-w,h,z); +// 四个顶点之间连线============ glVertex3f(w,h,z); glVertex3f(w,-h,z); @@ -122,7 +132,8 @@ void MapDrawer::DrawKeyFrames(const bool bDrawKF, const bool bDrawGraph) glVertex3f(-w,-h,z); glVertex3f(w,-h,z); - glEnd(); + + glEnd();// 画线结束 glPopMatrix(); } @@ -131,14 +142,17 @@ void MapDrawer::DrawKeyFrames(const bool bDrawKF, const bool bDrawGraph) if(bDrawGraph) { glLineWidth(mGraphLineWidth); - glColor4f(0.0f,1.0f,0.0f,0.6f); + glColor4f(0.0f,1.0f,0.0f,0.6f);// rgba 透明度 + +// 开始画线=============== glBegin(GL_LINES); for(size_t i=0; i vCovKFs = vpKFs[i]->GetCovisiblesByWeight(100); + // Covisibility Graph 共视图 === + const vector vCovKFs = vpKFs[i]->GetCovisiblesByWeight(100);// 共视图 权重 交大的=== cv::Mat Ow = vpKFs[i]->GetCameraCenter(); + if(!vCovKFs.empty()) { for(vector::const_iterator vit=vCovKFs.begin(), vend=vCovKFs.end(); vit!=vend; vit++) @@ -151,7 +165,7 @@ void MapDrawer::DrawKeyFrames(const bool bDrawKF, const bool bDrawGraph) } } - // Spanning tree + // Spanning tree 最小生成树====== KeyFrame* pParent = vpKFs[i]->GetParent(); if(pParent) { @@ -160,25 +174,27 @@ void MapDrawer::DrawKeyFrames(const bool bDrawKF, const bool bDrawGraph) glVertex3f(Owp.at(0),Owp.at(1),Owp.at(2)); } - // Loops + // Loops 闭环帧===连接线====== set sLoopKFs = vpKFs[i]->GetLoopEdges(); for(set::iterator sit=sLoopKFs.begin(), send=sLoopKFs.end(); sit!=send; sit++) { - if((*sit)->mnIdmnId) + if((*sit)->mnId < vpKFs[i]->mnId)// 避免重复画线??? continue; cv::Mat Owl = (*sit)->GetCameraCenter(); glVertex3f(Ow.at(0),Ow.at(1),Ow.at(2)); glVertex3f(Owl.at(0),Owl.at(1),Owl.at(2)); } } - +// 结束画线============== glEnd(); } } + +// 显示当前帧 相机位姿========绿色========================= void MapDrawer::DrawCurrentCamera(pangolin::OpenGlMatrix &Twc) { - const float &w = mCameraSize; + const float &w = mCameraSize;// 当前帧 相机线长 const float h = w*0.75; const float z = w*0.6; @@ -190,18 +206,25 @@ void MapDrawer::DrawCurrentCamera(pangolin::OpenGlMatrix &Twc) glMultMatrixd(Twc.m); #endif - glLineWidth(mCameraLineWidth); - glColor3f(0.0f,1.0f,0.0f); + glLineWidth(mCameraLineWidth);// 当前帧 相机线宽 + glColor3f(0.0f,1.0f,0.0f);// 绿色======== +// 开始画线============= glBegin(GL_LINES); + +// 相机光心 与 顶点 连线======== glVertex3f(0,0,0); glVertex3f(w,h,z); + glVertex3f(0,0,0); glVertex3f(w,-h,z); + glVertex3f(0,0,0); glVertex3f(-w,-h,z); + glVertex3f(0,0,0); glVertex3f(-w,h,z); +// 四个顶点之间连线============ glVertex3f(w,h,z); glVertex3f(w,-h,z); @@ -213,18 +236,20 @@ void MapDrawer::DrawCurrentCamera(pangolin::OpenGlMatrix &Twc) glVertex3f(-w,-h,z); glVertex3f(w,-h,z); +// 结束画线============== glEnd(); glPopMatrix(); } - +// 设置当前帧 相机姿====================================== void MapDrawer::SetCurrentCameraPose(const cv::Mat &Tcw) { unique_lock lock(mMutexCamera); mCameraPose = Tcw.clone(); } +// 获取当前相机位姿,返回 OpenGlMatrix 类型===== void MapDrawer::GetCurrentOpenGLCameraMatrix(pangolin::OpenGlMatrix &M) { if(!mCameraPose.empty()) diff --git a/vSLAM/oRB_SLAM2/src/Tracking.cc b/vSLAM/oRB_SLAM2/src/Tracking.cc index a31c1591..c234b0b3 100644 --- a/vSLAM/oRB_SLAM2/src/Tracking.cc +++ b/vSLAM/oRB_SLAM2/src/Tracking.cc @@ -482,6 +482,27 @@ LocalMap包含: * * Tracking 线程 */ + +/* +完整跟踪: + 1. 系统开始前两帧用来初始化(单目/双目/RGBD) + 2. 后面两帧之间的跟踪 + a. 建图+定位模式 + 检查并更新上一帧 + 正常:跟踪参考帧 / 跟踪上一帧(运动模式) + 丢失:重定位 + b. 仅定位模式 + 丢失:重定位 + 正常: + 跟踪的点较多: 跟踪参考帧 / 跟踪上一帧(运动模式) + 跟踪的点少 : 运动模式/重定位模式 + 3. 局部地图跟踪( 小回环优化) + 局部地图根系,更新速度模型,清除当前帧中不好的点,检查创建关键帧 + 4. ----> 局部建图----->回环检测 + +*/ + + void Tracking::Track() { // track包含两部分:估计运动(前后两帧的运动变换矩阵)、 跟踪局部地图(在地图中定位) diff --git a/vSLAM/oRB_SLAM2/src/Viewer.cc b/vSLAM/oRB_SLAM2/src/Viewer.cc index dec3204f..cecf790b 100644 --- a/vSLAM/oRB_SLAM2/src/Viewer.cc +++ b/vSLAM/oRB_SLAM2/src/Viewer.cc @@ -1,21 +1,7 @@ /** * This file is part of ORB-SLAM2. -* -* Copyright (C) 2014-2016 Raúl Mur-Artal (University of Zaragoza) -* For more information see -* -* ORB-SLAM2 is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* ORB-SLAM2 is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with ORB-SLAM2. If not, see . +* 可视化器,使用地图显示器(胖果林) + 帧显示器(opencv)====== + 帧率、图像尺寸 胖果林显示地图点 当前帧 关键帧 cv显示特征点图像 菜单响应 */ #include "Viewer.h" @@ -26,54 +12,79 @@ namespace ORB_SLAM2 { -Viewer::Viewer(System* pSystem, FrameDrawer *pFrameDrawer, MapDrawer *pMapDrawer, Tracking *pTracking, const string &strSettingPath): - mpSystem(pSystem), mpFrameDrawer(pFrameDrawer),mpMapDrawer(pMapDrawer), mpTracker(pTracking), - mbFinishRequested(false), mbFinished(true), mbStopped(true), mbStopRequested(false) +Viewer::Viewer(System* pSystem, + FrameDrawer *pFrameDrawer, + MapDrawer *pMapDrawer, + Tracking *pTracking, + const string &strSettingPath): + mpSystem(pSystem), mpFrameDrawer(pFrameDrawer), + mpMapDrawer(pMapDrawer), mpTracker(pTracking), + mbFinishRequested(false), mbFinished(true), + mbStopped(true), mbStopRequested(false) { cv::FileStorage fSettings(strSettingPath, cv::FileStorage::READ); - float fps = fSettings["Camera.fps"]; + float fps = fSettings["Camera.fps"];// 帧率 if(fps<1) fps=30; - mT = 1e3/fps; + mT = 1e3/fps;// ms 帧率倒数 mImageWidth = fSettings["Camera.width"]; mImageHeight = fSettings["Camera.height"]; if(mImageWidth<1 || mImageHeight<1) - { + {// 图像尺寸 mImageWidth = 640; mImageHeight = 480; } - +// 视点位置======= mViewpointX = fSettings["Viewer.ViewpointX"]; mViewpointY = fSettings["Viewer.ViewpointY"]; mViewpointZ = fSettings["Viewer.ViewpointZ"]; mViewpointF = fSettings["Viewer.ViewpointF"]; +/* + Viewer.ViewpointY: -0.7 + Viewer.ViewpointZ: -1.8 + Viewer.ViewpointF: 500 +*/ } + +// 可视化主线程 函数================= void Viewer::Run() { mbFinished = false; mbStopped = false; - pangolin::CreateWindowAndBind("ORB-SLAM2: Map Viewer",1024,768); +// 1. 窗口设置 pangolin 胖果林 创建 地图 显示窗口=====1024×768===== + pangolin::CreateWindowAndBind("地图显示",1024,768);// 窗口名字和窗口大小===== +// 2. 混合颜色设置====== // 3D Mouse handler requires depth testing to be enabled glEnable(GL_DEPTH_TEST); +// 检查,当前像素前面是否有别的像素,如果别的像素挡道了它,那它就不会绘制, +// 也就是说,OpenGL就只绘制最前面的一层。 // Issue specific OpenGl we might need - glEnable (GL_BLEND); - glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - + glEnable (GL_BLEND); // 打开混合 +// 基于源像素Alpha通道值的半透明混合函数 +// 透过红色的玻璃去看绿色的物体,那么可以先绘制绿色的物体,再绘制红色玻璃。 +// 在绘制红色玻璃的时候,利用“混合”功能,把将要绘制上去的红色和原来的绿色进行混合, +// 于是得到一种新的颜色,看上去就好像玻璃是半透明的。 + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);// 颜色混合 + +// 3. 窗口菜单设置============= pangolin::CreatePanel("menu").SetBounds(0.0,1.0,0.0,pangolin::Attach::Pix(175)); - pangolin::Var menuFollowCamera("menu.Follow Camera",true,true); - pangolin::Var menuShowPoints("menu.Show Points",true,true); - pangolin::Var menuShowKeyFrames("menu.Show KeyFrames",true,true); - pangolin::Var menuShowGraph("menu.Show Graph",true,true); - pangolin::Var menuLocalizationMode("menu.Localization Mode",false,true); - pangolin::Var menuReset("menu.Reset",false,false); +// 菜单栏==== + pangolin::Var menuFollowCamera("menu.Follow Camera",true,true);// 地图视角跟随相机动 默认不勾选 + pangolin::Var menuShowPoints("menu.Show Points",true,true);// 显示地图点 + pangolin::Var menuShowKeyFrames("menu.Show KeyFrames",true,true);// 显示关键帧 + pangolin::Var menuShowGraph("menu.Show Graph",true,true);// 显示关键帧 连线 + pangolin::Var menuLocalizationMode("menu.Localization Mode",false,true);// 仅定位模式 默认不勾选 + + pangolin::Var menuReset("menu.Reset",false,false);// 重置 单行单按钮 // Define Camera Render Object (for view / scene browsing) +// 窗口视角 ======== pangolin::OpenGlRenderState s_cam( pangolin::ProjectionMatrix(1024,768,mViewpointF,mViewpointF,512,389,0.1,1000), pangolin::ModelViewLookAt(mViewpointX,mViewpointY,mViewpointZ, 0,0,0,0.0,-1.0, 0.0) @@ -87,7 +98,9 @@ void Viewer::Run() pangolin::OpenGlMatrix Twc; Twc.SetIdentity(); - cv::namedWindow("ORB-SLAM2: Current Frame"); + +// OPENCV 显示 当前帧============================== + cv::namedWindow("当前帧+关键点"); bool bFollow = true; bool bLocalizationMode = false; @@ -96,17 +109,17 @@ void Viewer::Run() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - mpMapDrawer->GetCurrentOpenGLCameraMatrix(Twc); + mpMapDrawer->GetCurrentOpenGLCameraMatrix(Twc);// 当前帧 位姿 OpenGL Matrix - if(menuFollowCamera && bFollow) + if(menuFollowCamera && bFollow)//menuFollowCamera 为菜单获取的值 { - s_cam.Follow(Twc); + s_cam.Follow(Twc); // 视角跟随 相机位姿=== } else if(menuFollowCamera && !bFollow) { s_cam.SetModelViewMatrix(pangolin::ModelViewLookAt(mViewpointX,mViewpointY,mViewpointZ, 0,0,0,0.0,-1.0, 0.0)); s_cam.Follow(Twc); - bFollow = true; + bFollow = true;// 防止一直循环==== } else if(!menuFollowCamera && bFollow) { @@ -115,30 +128,31 @@ void Viewer::Run() if(menuLocalizationMode && !bLocalizationMode) { - mpSystem->ActivateLocalizationMode(); - bLocalizationMode = true; + mpSystem->ActivateLocalizationMode(); // 仅定位模式 + bLocalizationMode = true;// 防止一直循环==== } else if(!menuLocalizationMode && bLocalizationMode) { - mpSystem->DeactivateLocalizationMode(); - bLocalizationMode = false; + mpSystem->DeactivateLocalizationMode();// 定位+建图 + bLocalizationMode = false;// 防止一直循环==== } d_cam.Activate(s_cam); glClearColor(1.0f,1.0f,1.0f,1.0f); - mpMapDrawer->DrawCurrentCamera(Twc); + + mpMapDrawer->DrawCurrentCamera(Twc);// 绘制当前帧 if(menuShowKeyFrames || menuShowGraph) - mpMapDrawer->DrawKeyFrames(menuShowKeyFrames,menuShowGraph); + mpMapDrawer->DrawKeyFrames(menuShowKeyFrames,menuShowGraph);// 绘制关键帧 及其之间的连线 if(menuShowPoints) - mpMapDrawer->DrawMapPoints(); + mpMapDrawer->DrawMapPoints();// 显示地图点 - pangolin::FinishFrame(); + pangolin::FinishFrame(); // 胖果林完成显示================= - cv::Mat im = mpFrameDrawer->DrawFrame(); - cv::imshow("ORB-SLAM2: Current Frame",im); + cv::Mat im = mpFrameDrawer->DrawFrame(); // 返回关键帧,带有 关键点======== + cv::imshow("当前帧+关键点",im); cv::waitKey(mT); - if(menuReset) + if(menuReset) // 重置==== { menuShowGraph = true; menuShowKeyFrames = true; @@ -153,7 +167,7 @@ void Viewer::Run() menuReset = false; } - if(Stop()) + if(Stop())//停止===== { while(isStopped()) { @@ -161,7 +175,7 @@ void Viewer::Run() } } - if(CheckFinish()) + if(CheckFinish())// 检查是否停止==== break; } diff --git a/vSLAM/readme.md b/vSLAM/readme.md index 636f3564..fd61bd84 100644 --- a/vSLAM/readme.md +++ b/vSLAM/readme.md @@ -10,6 +10,12 @@ **2d/3d 空间变换** ![](https://github.com/Ewenwan/MVision/blob/master/vSLAM/img/2D-planar-transformations.PNG) +[SLAM 开发学习资源与经验分享 ](https://github.com/Ewenwan/Lee-SLAM-source) + +[AR 增强现实开发资源汇总 ](https://github.com/Ewenwan/AR-Source) + +[VR 虚拟现实开发者必备资源汇总](https://github.com/Ewenwan/Lee-VR-Source) + [视觉SLAM基础知识总结](https://blog.csdn.net/myarrow/article/details/53704339) [SLAM/VIO学习总结](https://zhuanlan.zhihu.com/p/34995102) @@ -44,6 +50,17 @@ [LSD_slam & 激光雷达slam](http://www.cs.toronto.edu/~urtasun/courses/CSC2541/04_SLAM.pdf) +[视觉SLAM滑窗 局部全局优化 Double Window Optimisation for Constant Time Visual SLAM](http://www.doc.ic.ac.uk/~ajd/Publications/strasdat_etal_iccv2011.pdf) + +[Visual Odometry(视觉里程计) StereoScan viso2 ](https://github.com/Ewenwan/viso2) + +闭环检测: + +[DBoW2 二进制字符串特征 词袋模型](https://github.com/dorian3d/DBoW2) +[DBoW3 二进制、浮点型特征 词袋模型](https://github.com/rmsalinas/DBow3) +[FBOW AVX,SSE and MMX指令集优化的 DBoW2 DBoW3](https://github.com/rmsalinas/fbow) +[haloc 图像特征哈希表示 图像与图像匹配](https://github.com/srv/libhaloc) + # 目录: @@ -310,6 +327,7 @@ # 2. 李群李代数知识 +[【Sophus库 学习笔记 1】 Sophus的安装与使用 基础知识](https://blog.csdn.net/wb790238030/article/details/88014059?utm_medium=distribute.pc_relevant.none-task-blog-baidulandingword-8&spm=1001.2101.3001.4242) [李群李代数 反对称矩阵 指数映射 对数 刚体变换群SE3](https://blog.csdn.net/x_r_su/article/details/52749616) diff --git a/vSLAM/svo_slam/readme.md b/vSLAM/svo_slam/readme.md index 95a62993..eb7e9662 100644 --- a/vSLAM/svo_slam/readme.md +++ b/vSLAM/svo_slam/readme.md @@ -6,6 +6,8 @@ [SVO代码分析 较细致](https://www.cnblogs.com/hxzkh/p/8607714.html) +[学习rpg_svo 根据代码和论文进行一步步的分析](https://github.com/yueying/OpenMVO) + [svo: semi-direct visual odometry 论文解析](https://blog.csdn.net/heyijia0327/article/details/51083398) [鲁棒 边缘特征SVO](https://github.com/Ewenwan/svo_edgelet) diff --git "a/vSLAM/\345\275\251\350\211\262\345\233\276\345\216\273\350\211\262&\346\212\240\345\233\276.md" "b/vSLAM/\345\275\251\350\211\262\345\233\276\345\216\273\350\211\262&\346\212\240\345\233\276.md" new file mode 100644 index 00000000..b3e3b2a8 --- /dev/null +++ "b/vSLAM/\345\275\251\350\211\262\345\233\276\345\216\273\350\211\262&\346\212\240\345\233\276.md" @@ -0,0 +1,63 @@ +# 1. 对比度保留之彩色图像去色算法 + +[参考](https://www.cnblogs.com/Imageshop/p/3430742.html) + + 原来一直认为彩色图像的去色算法没啥研究价值,网络上已经有很多类似的算法了, + 比如著名的Gray = R*0.299 + G*0.587 + B*0.114公式,或者LAB颜色通道的L值,HSL的L通道等等, + 直到最近看一些论文,发现原来也有很多人对这个过程进行过详细的研究和创新。 + 在学习这些算法的同时,使我也认识到,任何你认为简单的东西在背后都有可能有着复杂的机理, + 只是你没有发现而已。 + + 好的去色算法能够保留 彩色图中的对比关系 + 某些去色算法使得红花和绿叶去色后基本变得一致了,这其实即是所谓的对比度丢失, + 这种丢失对于普通的图像处理用户也许问题不大,不过对于图像分析方面是很不利的。 + +[论文1 Color2Gray: Salience-Preserving Color Removal ](http://www.cs.northwestern.edu/~jet/docs/2005color2grayFINAL.pdf)[Color2GrayMatlabCode](http://files.cnblogs.com/Imageshop/Color2GrayMatlabCode.rar) + + 这个代码仅仅具有学习价值,因为作者在论文中说100*100大小的图像算法用时12.7秒,这么长的时间那还搞个屁啊。 + +[论文2 主页 Contrast Preserving Decolorization 代码已在opencv的decolor()函数实现](http://www.cse.cuhk.edu.hk/~leojia/projects/color2gray/)[论文](http://www.cs.northwestern.edu/~jet/docs/2005color2grayFINAL.pdf) + + OpenCV消色decolor函数,比RGB2Gray函数转换更鲁邦!!!!!!!!!!!!!!!!!!!!! + + void decolor(InputArray src, OutputArray grayscale, OutputArray color_boost) + Parameters: + src – Input 8-bit 3-channel image. + grayscale – Output 8-bit 1-channel image. + color_boost – Output 8-bit 3-channel image. + +[论文3 Real-time Contrast Preserving Decolorization](http://www.cse.cuhk.edu.hk/leojia/papers/siga12t_color2gray.pdf)[代码](https://github.com/Ewenwan/rtcprgb2gray) + + 速度快 + 他没有像第二篇那样采用了二维的模型,而是简化为一维模型, + 类似于公式Gray = R*0.299 + G*0.587 + B*0.114,论文中也是使用W1,W2,W3三个系数来控制结果值, + 但是这三个系数不是固定的,而是同用户输入的图像自适应的。 + 同时有约束条件W1>0;W2>0;W3>0,以及W1+W2+W3=1;满足这几个条件的W1,W2,W3的值的组合还是有无限个的, + 但是作者注意到系数的微小变化对于输出的结果的影响不是特别大, + 因此,论文中提出了将每个系数在[0,1]之间量化为10等份, + 即只取0、0.1、0.2、0.3、0.4、0.5、0.6、0.7、0.8,0.9、1.0这11个值, + 在满足约束条件的情况下,W1、W2、W2的组合总共只会有11*(11+1)/2 =66 种。 + + + 这种搜索空间的离散化,在很多算法中都可以去模仿的!!!!!!!!!! + +## 主要原理: 优化能量函数 + + min(sum((gx-gy-δx,y)^2)) + + 其中gx,gy为灰度化后的像素值。而δx,y则表示颜色对比度, + 三篇论文中开始的时候都是用的LAB颜色空间的一些相关计算公式。 + + + +# 2. 抠图技术 Image Matting +[参考](https://blog.csdn.net/On_theway10/article/details/81873538) + +[A global sampling method for alpha matting](https://github.com/Ewenwan/global-matting) + +[Natural-image-matting](https://github.com/Rnandani/Natural-image-matting) + + +# 3. 导向滤波 引导滤波 guided filter +[Guided filter for OpenCV](https://github.com/Ewenwan/guided-filter) + diff --git "a/vSLAM/\347\237\251\351\230\265\345\217\230\346\215\242python\345\207\275\346\225\260.py" "b/vSLAM/\347\237\251\351\230\265\345\217\230\346\215\242python\345\207\275\346\225\260.py" new file mode 100644 index 00000000..2b882aa9 --- /dev/null +++ "b/vSLAM/\347\237\251\351\230\265\345\217\230\346\215\242python\345\207\275\346\225\260.py" @@ -0,0 +1,1575 @@ +# -*- coding: utf-8 -*- +# transformations.py +# https://github.com/stormtiti/rpg_svo_test/blob/e138b08d952c903dc12de1f189ce6a080ad92a5b/rpg_vikit/vikit_py/src/vikit_py/transformations.py +# Copyright (c) 2006, Christoph Gohlke +# Copyright (c) 2006-2009, The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holders nor the names of any +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +"""Homogeneous Transformation Matrices and Quaternions. +A library for calculating 4x4 matrices for translating, rotating, reflecting, +scaling, shearing, projecting, orthogonalizing, and superimposing arrays of +3D homogeneous coordinates as well as for converting between rotation matrices, +Euler angles, and quaternions. Also includes an Arcball control object and +functions to decompose transformation matrices. +:Authors: + `Christoph Gohlke `__, + Laboratory for Fluorescence Dynamics, University of California, Irvine +:Version: 20090418 +Requirements +------------ +* `Python 2.6 `__ +* `Numpy 1.3 `__ +* `transformations.c 20090418 `__ + (optional implementation of some functions in C) +Notes +----- +Matrices (M) can be inverted using numpy.linalg.inv(M), concatenated using +numpy.dot(M0, M1), or used to transform homogeneous coordinates (v) using +numpy.dot(M, v) for shape (4, \*) "point of arrays", respectively +numpy.dot(v, M.T) for shape (\*, 4) "array of points". +Calculations are carried out with numpy.float64 precision. +This Python implementation is not optimized for speed. +Vector, point, quaternion, and matrix function arguments are expected to be +"array like", i.e. tuple, list, or numpy arrays. +Return types are numpy arrays unless specified otherwise. +Angles are in radians unless specified otherwise. +Quaternions ix+jy+kz+w are represented as [x, y, z, w]. +Use the transpose of transformation matrices for OpenGL glMultMatrixd(). +A triple of Euler angles can be applied/interpreted in 24 ways, which can +be specified using a 4 character string or encoded 4-tuple: + *Axes 4-string*: e.g. 'sxyz' or 'ryxy' + - first character : rotations are applied to 's'tatic or 'r'otating frame + - remaining characters : successive rotation axis 'x', 'y', or 'z' + *Axes 4-tuple*: e.g. (0, 0, 0, 0) or (1, 1, 1, 1) + - inner axis: code of axis ('x':0, 'y':1, 'z':2) of rightmost matrix. + - parity : even (0) if inner axis 'x' is followed by 'y', 'y' is followed + by 'z', or 'z' is followed by 'x'. Otherwise odd (1). + - repetition : first and last axis are same (1) or different (0). + - frame : rotations are applied to static (0) or rotating (1) frame. +References +---------- +(1) Matrices and transformations. Ronald Goldman. + In "Graphics Gems I", pp 472-475. Morgan Kaufmann, 1990. +(2) More matrices and transformations: shear and pseudo-perspective. + Ronald Goldman. In "Graphics Gems II", pp 320-323. Morgan Kaufmann, 1991. +(3) Decomposing a matrix into simple transformations. Spencer Thomas. + In "Graphics Gems II", pp 320-323. Morgan Kaufmann, 1991. +(4) Recovering the data from the transformation matrix. Ronald Goldman. + In "Graphics Gems II", pp 324-331. Morgan Kaufmann, 1991. +(5) Euler angle conversion. Ken Shoemake. + In "Graphics Gems IV", pp 222-229. Morgan Kaufmann, 1994. +(6) Arcball rotation control. Ken Shoemake. + In "Graphics Gems IV", pp 175-192. Morgan Kaufmann, 1994. +(7) Representing attitude: Euler angles, unit quaternions, and rotation + vectors. James Diebel. 2006. +(8) A discussion of the solution for the best rotation to relate two sets + of vectors. W Kabsch. Acta Cryst. 1978. A34, 827-828. +(9) Closed-form solution of absolute orientation using unit quaternions. + BKP Horn. J Opt Soc Am A. 1987. 4(4), 629-642. +(10) Quaternions. Ken Shoemake. + http://www.sfu.ca/~jwa3/cmpt461/files/quatut.pdf +(11) From quaternion to matrix and back. JMP van Waveren. 2005. + http://www.intel.com/cd/ids/developer/asmo-na/eng/293748.htm +(12) Uniform random rotations. Ken Shoemake. + In "Graphics Gems III", pp 124-132. Morgan Kaufmann, 1992. +Examples +-------- +>>> alpha, beta, gamma = 0.123, -1.234, 2.345 +>>> origin, xaxis, yaxis, zaxis = (0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1) +>>> I = identity_matrix() +>>> Rx = rotation_matrix(alpha, xaxis) +>>> Ry = rotation_matrix(beta, yaxis) +>>> Rz = rotation_matrix(gamma, zaxis) +>>> R = concatenate_matrices(Rx, Ry, Rz) +>>> euler = euler_from_matrix(R, 'rxyz') +>>> numpy.allclose([alpha, beta, gamma], euler) +True +>>> Re = euler_matrix(alpha, beta, gamma, 'rxyz') +>>> is_same_transform(R, Re) +True +>>> al, be, ga = euler_from_matrix(Re, 'rxyz') +>>> is_same_transform(Re, euler_matrix(al, be, ga, 'rxyz')) +True +>>> qx = quaternion_about_axis(alpha, xaxis) +>>> qy = quaternion_about_axis(beta, yaxis) +>>> qz = quaternion_about_axis(gamma, zaxis) +>>> q = quaternion_multiply(qx, qy) +>>> q = quaternion_multiply(q, qz) +>>> Rq = quaternion_matrix(q) +>>> is_same_transform(R, Rq) +True +>>> S = scale_matrix(1.23, origin) +>>> T = translation_matrix((1, 2, 3)) +>>> Z = shear_matrix(beta, xaxis, origin, zaxis) +>>> R = random_rotation_matrix(numpy.random.rand(3)) +>>> M = concatenate_matrices(T, R, Z, S) +>>> scale, shear, angles, trans, persp = decompose_matrix(M) +>>> numpy.allclose(scale, 1.23) +True +>>> numpy.allclose(trans, (1, 2, 3)) +True +>>> numpy.allclose(shear, (0, math.tan(beta), 0)) +True +>>> is_same_transform(R, euler_matrix(axes='sxyz', *angles)) +True +>>> M1 = compose_matrix(scale, shear, angles, trans, persp) +>>> is_same_transform(M, M1) +True +""" + +from __future__ import division + +import warnings +import math + +import numpy + +# Documentation in HTML format can be generated with Epydoc +__docformat__ = "restructuredtext en" + + +def identity_matrix(): + """Return 4x4 identity/unit matrix. + >>> I = identity_matrix() + >>> numpy.allclose(I, numpy.dot(I, I)) + True + >>> numpy.sum(I), numpy.trace(I) + (4.0, 4.0) + >>> numpy.allclose(I, numpy.identity(4, dtype=numpy.float64)) + True + """ + return numpy.identity(4, dtype=numpy.float64) + + +def translation_matrix(direction): + """Return matrix to translate by direction vector. + >>> v = numpy.random.random(3) - 0.5 + >>> numpy.allclose(v, translation_matrix(v)[:3, 3]) + True + """ + M = numpy.identity(4) + M[:3, 3] = direction[:3] + return M + + +def translation_from_matrix(matrix): + """Return translation vector from translation matrix. + >>> v0 = numpy.random.random(3) - 0.5 + >>> v1 = translation_from_matrix(translation_matrix(v0)) + >>> numpy.allclose(v0, v1) + True + """ + return numpy.array(matrix, copy=False)[:3, 3].copy() + +def convert_3x3_to_4x4(matrix_3x3): + M = numpy.identity(4) + M[:3,:3] = matrix_3x3 + return M + +def reflection_matrix(point, normal): + """Return matrix to mirror at plane defined by point and normal vector. + >>> v0 = numpy.random.random(4) - 0.5 + >>> v0[3] = 1.0 + >>> v1 = numpy.random.random(3) - 0.5 + >>> R = reflection_matrix(v0, v1) + >>> numpy.allclose(2., numpy.trace(R)) + True + >>> numpy.allclose(v0, numpy.dot(R, v0)) + True + >>> v2 = v0.copy() + >>> v2[:3] += v1 + >>> v3 = v0.copy() + >>> v2[:3] -= v1 + >>> numpy.allclose(v2, numpy.dot(R, v3)) + True + """ + normal = unit_vector(normal[:3]) + M = numpy.identity(4) + M[:3, :3] -= 2.0 * numpy.outer(normal, normal) + M[:3, 3] = (2.0 * numpy.dot(point[:3], normal)) * normal + return M + + +def reflection_from_matrix(matrix): + """Return mirror plane point and normal vector from reflection matrix. + >>> v0 = numpy.random.random(3) - 0.5 + >>> v1 = numpy.random.random(3) - 0.5 + >>> M0 = reflection_matrix(v0, v1) + >>> point, normal = reflection_from_matrix(M0) + >>> M1 = reflection_matrix(point, normal) + >>> is_same_transform(M0, M1) + True + """ + M = numpy.array(matrix, dtype=numpy.float64, copy=False) + # normal: unit eigenvector corresponding to eigenvalue -1 + l, V = numpy.linalg.eig(M[:3, :3]) + i = numpy.where(abs(numpy.real(l) + 1.0) < 1e-8)[0] + if not len(i): + raise ValueError("no unit eigenvector corresponding to eigenvalue -1") + normal = numpy.real(V[:, i[0]]).squeeze() + # point: any unit eigenvector corresponding to eigenvalue 1 + l, V = numpy.linalg.eig(M) + i = numpy.where(abs(numpy.real(l) - 1.0) < 1e-8)[0] + if not len(i): + raise ValueError("no unit eigenvector corresponding to eigenvalue 1") + point = numpy.real(V[:, i[-1]]).squeeze() + point /= point[3] + return point, normal + + +def rotation_matrix(angle, direction, point=None): + """Return matrix to rotate about axis defined by point and direction. + >>> angle = (random.random() - 0.5) * (2*math.pi) + >>> direc = numpy.random.random(3) - 0.5 + >>> point = numpy.random.random(3) - 0.5 + >>> R0 = rotation_matrix(angle, direc, point) + >>> R1 = rotation_matrix(angle-2*math.pi, direc, point) + >>> is_same_transform(R0, R1) + True + >>> R0 = rotation_matrix(angle, direc, point) + >>> R1 = rotation_matrix(-angle, -direc, point) + >>> is_same_transform(R0, R1) + True + >>> I = numpy.identity(4, numpy.float64) + >>> numpy.allclose(I, rotation_matrix(math.pi*2, direc)) + True + >>> numpy.allclose(2., numpy.trace(rotation_matrix(math.pi/2, + ... direc, point))) + True + """ + sina = math.sin(angle) + cosa = math.cos(angle) + direction = unit_vector(direction[:3]) + # rotation matrix around unit vector + R = numpy.array(((cosa, 0.0, 0.0), + (0.0, cosa, 0.0), + (0.0, 0.0, cosa)), dtype=numpy.float64) + R += numpy.outer(direction, direction) * (1.0 - cosa) + direction *= sina + R += numpy.array((( 0.0, -direction[2], direction[1]), + ( direction[2], 0.0, -direction[0]), + (-direction[1], direction[0], 0.0)), + dtype=numpy.float64) + M = numpy.identity(4) + M[:3, :3] = R + if point is not None: + # rotation not around origin + point = numpy.array(point[:3], dtype=numpy.float64, copy=False) + M[:3, 3] = point - numpy.dot(R, point) + return M + + +def rotation_from_matrix(matrix): + """Return rotation angle and axis from rotation matrix. + >>> angle = (random.random() - 0.5) * (2*math.pi) + >>> direc = numpy.random.random(3) - 0.5 + >>> point = numpy.random.random(3) - 0.5 + >>> R0 = rotation_matrix(angle, direc, point) + >>> angle, direc, point = rotation_from_matrix(R0) + >>> R1 = rotation_matrix(angle, direc, point) + >>> is_same_transform(R0, R1) + True + """ + R = numpy.array(matrix, dtype=numpy.float64, copy=False) + R33 = R[:3, :3] + # direction: unit eigenvector of R33 corresponding to eigenvalue of 1 + l, W = numpy.linalg.eig(R33.T) + i = numpy.where(abs(numpy.real(l) - 1.0) < 1e-8)[0] + if not len(i): + raise ValueError("no unit eigenvector corresponding to eigenvalue 1") + direction = numpy.real(W[:, i[-1]]).squeeze() + # point: unit eigenvector of R33 corresponding to eigenvalue of 1 + l, Q = numpy.linalg.eig(R) + i = numpy.where(abs(numpy.real(l) - 1.0) < 1e-8)[0] + if not len(i): + raise ValueError("no unit eigenvector corresponding to eigenvalue 1") + point = numpy.real(Q[:, i[-1]]).squeeze() + point /= point[3] + # rotation angle depending on direction + cosa = (numpy.trace(R33) - 1.0) / 2.0 + if abs(direction[2]) > 1e-8: + sina = (R[1, 0] + (cosa-1.0)*direction[0]*direction[1]) / direction[2] + elif abs(direction[1]) > 1e-8: + sina = (R[0, 2] + (cosa-1.0)*direction[0]*direction[2]) / direction[1] + else: + sina = (R[2, 1] + (cosa-1.0)*direction[1]*direction[2]) / direction[0] + angle = math.atan2(sina, cosa) + return angle, direction, point + + +def scale_matrix(factor, origin=None, direction=None): + """Return matrix to scale by factor around origin in direction. + Use factor -1 for point symmetry. + >>> v = (numpy.random.rand(4, 5) - 0.5) * 20.0 + >>> v[3] = 1.0 + >>> S = scale_matrix(-1.234) + >>> numpy.allclose(numpy.dot(S, v)[:3], -1.234*v[:3]) + True + >>> factor = random.random() * 10 - 5 + >>> origin = numpy.random.random(3) - 0.5 + >>> direct = numpy.random.random(3) - 0.5 + >>> S = scale_matrix(factor, origin) + >>> S = scale_matrix(factor, origin, direct) + """ + if direction is None: + # uniform scaling + M = numpy.array(((factor, 0.0, 0.0, 0.0), + (0.0, factor, 0.0, 0.0), + (0.0, 0.0, factor, 0.0), + (0.0, 0.0, 0.0, 1.0)), dtype=numpy.float64) + if origin is not None: + M[:3, 3] = origin[:3] + M[:3, 3] *= 1.0 - factor + else: + # nonuniform scaling + direction = unit_vector(direction[:3]) + factor = 1.0 - factor + M = numpy.identity(4) + M[:3, :3] -= factor * numpy.outer(direction, direction) + if origin is not None: + M[:3, 3] = (factor * numpy.dot(origin[:3], direction)) * direction + return M + + +def scale_from_matrix(matrix): + """Return scaling factor, origin and direction from scaling matrix. + >>> factor = random.random() * 10 - 5 + >>> origin = numpy.random.random(3) - 0.5 + >>> direct = numpy.random.random(3) - 0.5 + >>> S0 = scale_matrix(factor, origin) + >>> factor, origin, direction = scale_from_matrix(S0) + >>> S1 = scale_matrix(factor, origin, direction) + >>> is_same_transform(S0, S1) + True + >>> S0 = scale_matrix(factor, origin, direct) + >>> factor, origin, direction = scale_from_matrix(S0) + >>> S1 = scale_matrix(factor, origin, direction) + >>> is_same_transform(S0, S1) + True + """ + M = numpy.array(matrix, dtype=numpy.float64, copy=False) + M33 = M[:3, :3] + factor = numpy.trace(M33) - 2.0 + try: + # direction: unit eigenvector corresponding to eigenvalue factor + l, V = numpy.linalg.eig(M33) + i = numpy.where(abs(numpy.real(l) - factor) < 1e-8)[0][0] + direction = numpy.real(V[:, i]).squeeze() + direction /= vector_norm(direction) + except IndexError: + # uniform scaling + factor = (factor + 2.0) / 3.0 + direction = None + # origin: any eigenvector corresponding to eigenvalue 1 + l, V = numpy.linalg.eig(M) + i = numpy.where(abs(numpy.real(l) - 1.0) < 1e-8)[0] + if not len(i): + raise ValueError("no eigenvector corresponding to eigenvalue 1") + origin = numpy.real(V[:, i[-1]]).squeeze() + origin /= origin[3] + return factor, origin, direction + + +def projection_matrix(point, normal, direction=None, + perspective=None, pseudo=False): + """Return matrix to project onto plane defined by point and normal. + Using either perspective point, projection direction, or none of both. + If pseudo is True, perspective projections will preserve relative depth + such that Perspective = dot(Orthogonal, PseudoPerspective). + >>> P = projection_matrix((0, 0, 0), (1, 0, 0)) + >>> numpy.allclose(P[1:, 1:], numpy.identity(4)[1:, 1:]) + True + >>> point = numpy.random.random(3) - 0.5 + >>> normal = numpy.random.random(3) - 0.5 + >>> direct = numpy.random.random(3) - 0.5 + >>> persp = numpy.random.random(3) - 0.5 + >>> P0 = projection_matrix(point, normal) + >>> P1 = projection_matrix(point, normal, direction=direct) + >>> P2 = projection_matrix(point, normal, perspective=persp) + >>> P3 = projection_matrix(point, normal, perspective=persp, pseudo=True) + >>> is_same_transform(P2, numpy.dot(P0, P3)) + True + >>> P = projection_matrix((3, 0, 0), (1, 1, 0), (1, 0, 0)) + >>> v0 = (numpy.random.rand(4, 5) - 0.5) * 20.0 + >>> v0[3] = 1.0 + >>> v1 = numpy.dot(P, v0) + >>> numpy.allclose(v1[1], v0[1]) + True + >>> numpy.allclose(v1[0], 3.0-v1[1]) + True + """ + M = numpy.identity(4) + point = numpy.array(point[:3], dtype=numpy.float64, copy=False) + normal = unit_vector(normal[:3]) + if perspective is not None: + # perspective projection + perspective = numpy.array(perspective[:3], dtype=numpy.float64, + copy=False) + M[0, 0] = M[1, 1] = M[2, 2] = numpy.dot(perspective-point, normal) + M[:3, :3] -= numpy.outer(perspective, normal) + if pseudo: + # preserve relative depth + M[:3, :3] -= numpy.outer(normal, normal) + M[:3, 3] = numpy.dot(point, normal) * (perspective+normal) + else: + M[:3, 3] = numpy.dot(point, normal) * perspective + M[3, :3] = -normal + M[3, 3] = numpy.dot(perspective, normal) + elif direction is not None: + # parallel projection + direction = numpy.array(direction[:3], dtype=numpy.float64, copy=False) + scale = numpy.dot(direction, normal) + M[:3, :3] -= numpy.outer(direction, normal) / scale + M[:3, 3] = direction * (numpy.dot(point, normal) / scale) + else: + # orthogonal projection + M[:3, :3] -= numpy.outer(normal, normal) + M[:3, 3] = numpy.dot(point, normal) * normal + return M + + +def projection_from_matrix(matrix, pseudo=False): + """Return projection plane and perspective point from projection matrix. + Return values are same as arguments for projection_matrix function: + point, normal, direction, perspective, and pseudo. + >>> point = numpy.random.random(3) - 0.5 + >>> normal = numpy.random.random(3) - 0.5 + >>> direct = numpy.random.random(3) - 0.5 + >>> persp = numpy.random.random(3) - 0.5 + >>> P0 = projection_matrix(point, normal) + >>> result = projection_from_matrix(P0) + >>> P1 = projection_matrix(*result) + >>> is_same_transform(P0, P1) + True + >>> P0 = projection_matrix(point, normal, direct) + >>> result = projection_from_matrix(P0) + >>> P1 = projection_matrix(*result) + >>> is_same_transform(P0, P1) + True + >>> P0 = projection_matrix(point, normal, perspective=persp, pseudo=False) + >>> result = projection_from_matrix(P0, pseudo=False) + >>> P1 = projection_matrix(*result) + >>> is_same_transform(P0, P1) + True + >>> P0 = projection_matrix(point, normal, perspective=persp, pseudo=True) + >>> result = projection_from_matrix(P0, pseudo=True) + >>> P1 = projection_matrix(*result) + >>> is_same_transform(P0, P1) + True + """ + M = numpy.array(matrix, dtype=numpy.float64, copy=False) + M33 = M[:3, :3] + l, V = numpy.linalg.eig(M) + i = numpy.where(abs(numpy.real(l) - 1.0) < 1e-8)[0] + if not pseudo and len(i): + # point: any eigenvector corresponding to eigenvalue 1 + point = numpy.real(V[:, i[-1]]).squeeze() + point /= point[3] + # direction: unit eigenvector corresponding to eigenvalue 0 + l, V = numpy.linalg.eig(M33) + i = numpy.where(abs(numpy.real(l)) < 1e-8)[0] + if not len(i): + raise ValueError("no eigenvector corresponding to eigenvalue 0") + direction = numpy.real(V[:, i[0]]).squeeze() + direction /= vector_norm(direction) + # normal: unit eigenvector of M33.T corresponding to eigenvalue 0 + l, V = numpy.linalg.eig(M33.T) + i = numpy.where(abs(numpy.real(l)) < 1e-8)[0] + if len(i): + # parallel projection + normal = numpy.real(V[:, i[0]]).squeeze() + normal /= vector_norm(normal) + return point, normal, direction, None, False + else: + # orthogonal projection, where normal equals direction vector + return point, direction, None, None, False + else: + # perspective projection + i = numpy.where(abs(numpy.real(l)) > 1e-8)[0] + if not len(i): + raise ValueError( + "no eigenvector not corresponding to eigenvalue 0") + point = numpy.real(V[:, i[-1]]).squeeze() + point /= point[3] + normal = - M[3, :3] + perspective = M[:3, 3] / numpy.dot(point[:3], normal) + if pseudo: + perspective -= normal + return point, normal, None, perspective, pseudo + + +def clip_matrix(left, right, bottom, top, near, far, perspective=False): + """Return matrix to obtain normalized device coordinates from frustrum. + The frustrum bounds are axis-aligned along x (left, right), + y (bottom, top) and z (near, far). + Normalized device coordinates are in range [-1, 1] if coordinates are + inside the frustrum. + If perspective is True the frustrum is a truncated pyramid with the + perspective point at origin and direction along z axis, otherwise an + orthographic canonical view volume (a box). + Homogeneous coordinates transformed by the perspective clip matrix + need to be dehomogenized (devided by w coordinate). + >>> frustrum = numpy.random.rand(6) + >>> frustrum[1] += frustrum[0] + >>> frustrum[3] += frustrum[2] + >>> frustrum[5] += frustrum[4] + >>> M = clip_matrix(*frustrum, perspective=False) + >>> numpy.dot(M, [frustrum[0], frustrum[2], frustrum[4], 1.0]) + array([-1., -1., -1., 1.]) + >>> numpy.dot(M, [frustrum[1], frustrum[3], frustrum[5], 1.0]) + array([ 1., 1., 1., 1.]) + >>> M = clip_matrix(*frustrum, perspective=True) + >>> v = numpy.dot(M, [frustrum[0], frustrum[2], frustrum[4], 1.0]) + >>> v / v[3] + array([-1., -1., -1., 1.]) + >>> v = numpy.dot(M, [frustrum[1], frustrum[3], frustrum[4], 1.0]) + >>> v / v[3] + array([ 1., 1., -1., 1.]) + """ + if left >= right or bottom >= top or near >= far: + raise ValueError("invalid frustrum") + if perspective: + if near <= _EPS: + raise ValueError("invalid frustrum: near <= 0") + t = 2.0 * near + M = ((-t/(right-left), 0.0, (right+left)/(right-left), 0.0), + (0.0, -t/(top-bottom), (top+bottom)/(top-bottom), 0.0), + (0.0, 0.0, -(far+near)/(far-near), t*far/(far-near)), + (0.0, 0.0, -1.0, 0.0)) + else: + M = ((2.0/(right-left), 0.0, 0.0, (right+left)/(left-right)), + (0.0, 2.0/(top-bottom), 0.0, (top+bottom)/(bottom-top)), + (0.0, 0.0, 2.0/(far-near), (far+near)/(near-far)), + (0.0, 0.0, 0.0, 1.0)) + return numpy.array(M, dtype=numpy.float64) + + +def shear_matrix(angle, direction, point, normal): + """Return matrix to shear by angle along direction vector on shear plane. + The shear plane is defined by a point and normal vector. The direction + vector must be orthogonal to the plane's normal vector. + A point P is transformed by the shear matrix into P" such that + the vector P-P" is parallel to the direction vector and its extent is + given by the angle of P-P'-P", where P' is the orthogonal projection + of P onto the shear plane. + >>> angle = (random.random() - 0.5) * 4*math.pi + >>> direct = numpy.random.random(3) - 0.5 + >>> point = numpy.random.random(3) - 0.5 + >>> normal = numpy.cross(direct, numpy.random.random(3)) + >>> S = shear_matrix(angle, direct, point, normal) + >>> numpy.allclose(1.0, numpy.linalg.det(S)) + True + """ + normal = unit_vector(normal[:3]) + direction = unit_vector(direction[:3]) + if abs(numpy.dot(normal, direction)) > 1e-6: + raise ValueError("direction and normal vectors are not orthogonal") + angle = math.tan(angle) + M = numpy.identity(4) + M[:3, :3] += angle * numpy.outer(direction, normal) + M[:3, 3] = -angle * numpy.dot(point[:3], normal) * direction + return M + + +def shear_from_matrix(matrix): + """Return shear angle, direction and plane from shear matrix. + >>> angle = (random.random() - 0.5) * 4*math.pi + >>> direct = numpy.random.random(3) - 0.5 + >>> point = numpy.random.random(3) - 0.5 + >>> normal = numpy.cross(direct, numpy.random.random(3)) + >>> S0 = shear_matrix(angle, direct, point, normal) + >>> angle, direct, point, normal = shear_from_matrix(S0) + >>> S1 = shear_matrix(angle, direct, point, normal) + >>> is_same_transform(S0, S1) + True + """ + M = numpy.array(matrix, dtype=numpy.float64, copy=False) + M33 = M[:3, :3] + # normal: cross independent eigenvectors corresponding to the eigenvalue 1 + l, V = numpy.linalg.eig(M33) + i = numpy.where(abs(numpy.real(l) - 1.0) < 1e-4)[0] + if len(i) < 2: + raise ValueError("No two linear independent eigenvectors found %s" % l) + V = numpy.real(V[:, i]).squeeze().T + lenorm = -1.0 + for i0, i1 in ((0, 1), (0, 2), (1, 2)): + n = numpy.cross(V[i0], V[i1]) + l = vector_norm(n) + if l > lenorm: + lenorm = l + normal = n + normal /= lenorm + # direction and angle + direction = numpy.dot(M33 - numpy.identity(3), normal) + angle = vector_norm(direction) + direction /= angle + angle = math.atan(angle) + # point: eigenvector corresponding to eigenvalue 1 + l, V = numpy.linalg.eig(M) + i = numpy.where(abs(numpy.real(l) - 1.0) < 1e-8)[0] + if not len(i): + raise ValueError("no eigenvector corresponding to eigenvalue 1") + point = numpy.real(V[:, i[-1]]).squeeze() + point /= point[3] + return angle, direction, point, normal + + +def decompose_matrix(matrix): + """Return sequence of transformations from transformation matrix. + matrix : array_like + Non-degenerative homogeneous transformation matrix + Return tuple of: + scale : vector of 3 scaling factors + shear : list of shear factors for x-y, x-z, y-z axes + angles : list of Euler angles about static x, y, z axes + translate : translation vector along x, y, z axes + perspective : perspective partition of matrix + Raise ValueError if matrix is of wrong type or degenerative. + >>> T0 = translation_matrix((1, 2, 3)) + >>> scale, shear, angles, trans, persp = decompose_matrix(T0) + >>> T1 = translation_matrix(trans) + >>> numpy.allclose(T0, T1) + True + >>> S = scale_matrix(0.123) + >>> scale, shear, angles, trans, persp = decompose_matrix(S) + >>> scale[0] + 0.123 + >>> R0 = euler_matrix(1, 2, 3) + >>> scale, shear, angles, trans, persp = decompose_matrix(R0) + >>> R1 = euler_matrix(*angles) + >>> numpy.allclose(R0, R1) + True + """ + M = numpy.array(matrix, dtype=numpy.float64, copy=True).T + if abs(M[3, 3]) < _EPS: + raise ValueError("M[3, 3] is zero") + M /= M[3, 3] + P = M.copy() + P[:, 3] = 0, 0, 0, 1 + if not numpy.linalg.det(P): + raise ValueError("Matrix is singular") + + scale = numpy.zeros((3, ), dtype=numpy.float64) + shear = [0, 0, 0] + angles = [0, 0, 0] + + if any(abs(M[:3, 3]) > _EPS): + perspective = numpy.dot(M[:, 3], numpy.linalg.inv(P.T)) + M[:, 3] = 0, 0, 0, 1 + else: + perspective = numpy.array((0, 0, 0, 1), dtype=numpy.float64) + + translate = M[3, :3].copy() + M[3, :3] = 0 + + row = M[:3, :3].copy() + scale[0] = vector_norm(row[0]) + row[0] /= scale[0] + shear[0] = numpy.dot(row[0], row[1]) + row[1] -= row[0] * shear[0] + scale[1] = vector_norm(row[1]) + row[1] /= scale[1] + shear[0] /= scale[1] + shear[1] = numpy.dot(row[0], row[2]) + row[2] -= row[0] * shear[1] + shear[2] = numpy.dot(row[1], row[2]) + row[2] -= row[1] * shear[2] + scale[2] = vector_norm(row[2]) + row[2] /= scale[2] + shear[1:] /= scale[2] + + if numpy.dot(row[0], numpy.cross(row[1], row[2])) < 0: + scale *= -1 + row *= -1 + + angles[1] = math.asin(-row[0, 2]) + if math.cos(angles[1]): + angles[0] = math.atan2(row[1, 2], row[2, 2]) + angles[2] = math.atan2(row[0, 1], row[0, 0]) + else: + #angles[0] = math.atan2(row[1, 0], row[1, 1]) + angles[0] = math.atan2(-row[2, 1], row[1, 1]) + angles[2] = 0.0 + + return scale, shear, angles, translate, perspective + + +def compose_matrix(scale=None, shear=None, angles=None, translate=None, + perspective=None): + """Return transformation matrix from sequence of transformations. + This is the inverse of the decompose_matrix function. + Sequence of transformations: + scale : vector of 3 scaling factors + shear : list of shear factors for x-y, x-z, y-z axes + angles : list of Euler angles about static x, y, z axes + translate : translation vector along x, y, z axes + perspective : perspective partition of matrix + >>> scale = numpy.random.random(3) - 0.5 + >>> shear = numpy.random.random(3) - 0.5 + >>> angles = (numpy.random.random(3) - 0.5) * (2*math.pi) + >>> trans = numpy.random.random(3) - 0.5 + >>> persp = numpy.random.random(4) - 0.5 + >>> M0 = compose_matrix(scale, shear, angles, trans, persp) + >>> result = decompose_matrix(M0) + >>> M1 = compose_matrix(*result) + >>> is_same_transform(M0, M1) + True + """ + M = numpy.identity(4) + if perspective is not None: + P = numpy.identity(4) + P[3, :] = perspective[:4] + M = numpy.dot(M, P) + if translate is not None: + T = numpy.identity(4) + T[:3, 3] = translate[:3] + M = numpy.dot(M, T) + if angles is not None: + R = euler_matrix(angles[0], angles[1], angles[2], 'sxyz') + M = numpy.dot(M, R) + if shear is not None: + Z = numpy.identity(4) + Z[1, 2] = shear[2] + Z[0, 2] = shear[1] + Z[0, 1] = shear[0] + M = numpy.dot(M, Z) + if scale is not None: + S = numpy.identity(4) + S[0, 0] = scale[0] + S[1, 1] = scale[1] + S[2, 2] = scale[2] + M = numpy.dot(M, S) + M /= M[3, 3] + return M + + +def orthogonalization_matrix(lengths, angles): + """Return orthogonalization matrix for crystallographic cell coordinates. + Angles are expected in degrees. + The de-orthogonalization matrix is the inverse. + >>> O = orthogonalization_matrix((10., 10., 10.), (90., 90., 90.)) + >>> numpy.allclose(O[:3, :3], numpy.identity(3, float) * 10) + True + >>> O = orthogonalization_matrix([9.8, 12.0, 15.5], [87.2, 80.7, 69.7]) + >>> numpy.allclose(numpy.sum(O), 43.063229) + True + """ + a, b, c = lengths + angles = numpy.radians(angles) + sina, sinb, _ = numpy.sin(angles) + cosa, cosb, cosg = numpy.cos(angles) + co = (cosa * cosb - cosg) / (sina * sinb) + return numpy.array(( + ( a*sinb*math.sqrt(1.0-co*co), 0.0, 0.0, 0.0), + (-a*sinb*co, b*sina, 0.0, 0.0), + ( a*cosb, b*cosa, c, 0.0), + ( 0.0, 0.0, 0.0, 1.0)), + dtype=numpy.float64) + + +def superimposition_matrix(v0, v1, scaling=False, usesvd=True): + """Return matrix to transform given vector set into second vector set. + v0 and v1 are shape (3, \*) or (4, \*) arrays of at least 3 vectors. + If usesvd is True, the weighted sum of squared deviations (RMSD) is + minimized according to the algorithm by W. Kabsch [8]. Otherwise the + quaternion based algorithm by B. Horn [9] is used (slower when using + this Python implementation). + The returned matrix performs rotation, translation and uniform scaling + (if specified). + >>> v0 = numpy.random.rand(3, 10) + >>> M = superimposition_matrix(v0, v0) + >>> numpy.allclose(M, numpy.identity(4)) + True + >>> R = random_rotation_matrix(numpy.random.random(3)) + >>> v0 = ((1,0,0), (0,1,0), (0,0,1), (1,1,1)) + >>> v1 = numpy.dot(R, v0) + >>> M = superimposition_matrix(v0, v1) + >>> numpy.allclose(v1, numpy.dot(M, v0)) + True + >>> v0 = (numpy.random.rand(4, 100) - 0.5) * 20.0 + >>> v0[3] = 1.0 + >>> v1 = numpy.dot(R, v0) + >>> M = superimposition_matrix(v0, v1) + >>> numpy.allclose(v1, numpy.dot(M, v0)) + True + >>> S = scale_matrix(random.random()) + >>> T = translation_matrix(numpy.random.random(3)-0.5) + >>> M = concatenate_matrices(T, R, S) + >>> v1 = numpy.dot(M, v0) + >>> v0[:3] += numpy.random.normal(0.0, 1e-9, 300).reshape(3, -1) + >>> M = superimposition_matrix(v0, v1, scaling=True) + >>> numpy.allclose(v1, numpy.dot(M, v0)) + True + >>> M = superimposition_matrix(v0, v1, scaling=True, usesvd=False) + >>> numpy.allclose(v1, numpy.dot(M, v0)) + True + >>> v = numpy.empty((4, 100, 3), dtype=numpy.float64) + >>> v[:, :, 0] = v0 + >>> M = superimposition_matrix(v0, v1, scaling=True, usesvd=False) + >>> numpy.allclose(v1, numpy.dot(M, v[:, :, 0])) + True + """ + v0 = numpy.array(v0, dtype=numpy.float64, copy=False)[:3] + v1 = numpy.array(v1, dtype=numpy.float64, copy=False)[:3] + + if v0.shape != v1.shape or v0.shape[1] < 3: + raise ValueError("Vector sets are of wrong shape or type.") + + # move centroids to origin + t0 = numpy.mean(v0, axis=1) + t1 = numpy.mean(v1, axis=1) + v0 = v0 - t0.reshape(3, 1) + v1 = v1 - t1.reshape(3, 1) + + if usesvd: + # Singular Value Decomposition of covariance matrix + u, s, vh = numpy.linalg.svd(numpy.dot(v1, v0.T)) + # rotation matrix from SVD orthonormal bases + R = numpy.dot(u, vh) + if numpy.linalg.det(R) < 0.0: + # R does not constitute right handed system + R -= numpy.outer(u[:, 2], vh[2, :]*2.0) + s[-1] *= -1.0 + # homogeneous transformation matrix + M = numpy.identity(4) + M[:3, :3] = R + else: + # compute symmetric matrix N + xx, yy, zz = numpy.sum(v0 * v1, axis=1) + xy, yz, zx = numpy.sum(v0 * numpy.roll(v1, -1, axis=0), axis=1) + xz, yx, zy = numpy.sum(v0 * numpy.roll(v1, -2, axis=0), axis=1) + N = ((xx+yy+zz, yz-zy, zx-xz, xy-yx), + (yz-zy, xx-yy-zz, xy+yx, zx+xz), + (zx-xz, xy+yx, -xx+yy-zz, yz+zy), + (xy-yx, zx+xz, yz+zy, -xx-yy+zz)) + # quaternion: eigenvector corresponding to most positive eigenvalue + l, V = numpy.linalg.eig(N) + q = V[:, numpy.argmax(l)] + q /= vector_norm(q) # unit quaternion + q = numpy.roll(q, -1) # move w component to end + # homogeneous transformation matrix + M = quaternion_matrix(q) + + # scale: ratio of rms deviations from centroid + if scaling: + v0 *= v0 + v1 *= v1 + M[:3, :3] *= math.sqrt(numpy.sum(v1) / numpy.sum(v0)) + + # translation + M[:3, 3] = t1 + T = numpy.identity(4) + T[:3, 3] = -t0 + M = numpy.dot(M, T) + return M + + +def euler_matrix(ai, aj, ak, axes='sxyz'): + """Return homogeneous rotation matrix from Euler angles and axis sequence. + ai, aj, ak : Euler's roll, pitch and yaw angles + axes : One of 24 axis sequences as string or encoded tuple + >>> R = euler_matrix(1, 2, 3, 'syxz') + >>> numpy.allclose(numpy.sum(R[0]), -1.34786452) + True + >>> R = euler_matrix(1, 2, 3, (0, 1, 0, 1)) + >>> numpy.allclose(numpy.sum(R[0]), -0.383436184) + True + >>> ai, aj, ak = (4.0*math.pi) * (numpy.random.random(3) - 0.5) + >>> for axes in _AXES2TUPLE.keys(): + ... R = euler_matrix(ai, aj, ak, axes) + >>> for axes in _TUPLE2AXES.keys(): + ... R = euler_matrix(ai, aj, ak, axes) + """ + try: + firstaxis, parity, repetition, frame = _AXES2TUPLE[axes] + except (AttributeError, KeyError): + _ = _TUPLE2AXES[axes] + firstaxis, parity, repetition, frame = axes + + i = firstaxis + j = _NEXT_AXIS[i+parity] + k = _NEXT_AXIS[i-parity+1] + + if frame: + ai, ak = ak, ai + if parity: + ai, aj, ak = -ai, -aj, -ak + + si, sj, sk = math.sin(ai), math.sin(aj), math.sin(ak) + ci, cj, ck = math.cos(ai), math.cos(aj), math.cos(ak) + cc, cs = ci*ck, ci*sk + sc, ss = si*ck, si*sk + + M = numpy.identity(4) + if repetition: + M[i, i] = cj + M[i, j] = sj*si + M[i, k] = sj*ci + M[j, i] = sj*sk + M[j, j] = -cj*ss+cc + M[j, k] = -cj*cs-sc + M[k, i] = -sj*ck + M[k, j] = cj*sc+cs + M[k, k] = cj*cc-ss + else: + M[i, i] = cj*ck + M[i, j] = sj*sc-cs + M[i, k] = sj*cc+ss + M[j, i] = cj*sk + M[j, j] = sj*ss+cc + M[j, k] = sj*cs-sc + M[k, i] = -sj + M[k, j] = cj*si + M[k, k] = cj*ci + return M + + +def euler_from_matrix(matrix, axes='sxyz'): + """Return Euler angles from rotation matrix for specified axis sequence. + axes : One of 24 axis sequences as string or encoded tuple + Note that many Euler angle triplets can describe one matrix. + >>> R0 = euler_matrix(1, 2, 3, 'syxz') + >>> al, be, ga = euler_from_matrix(R0, 'syxz') + >>> R1 = euler_matrix(al, be, ga, 'syxz') + >>> numpy.allclose(R0, R1) + True + >>> angles = (4.0*math.pi) * (numpy.random.random(3) - 0.5) + >>> for axes in _AXES2TUPLE.keys(): + ... R0 = euler_matrix(axes=axes, *angles) + ... R1 = euler_matrix(axes=axes, *euler_from_matrix(R0, axes)) + ... if not numpy.allclose(R0, R1): print axes, "failed" + """ + try: + firstaxis, parity, repetition, frame = _AXES2TUPLE[axes.lower()] + except (AttributeError, KeyError): + _ = _TUPLE2AXES[axes] + firstaxis, parity, repetition, frame = axes + + i = firstaxis + j = _NEXT_AXIS[i+parity] + k = _NEXT_AXIS[i-parity+1] + + M = numpy.array(matrix, dtype=numpy.float64, copy=False)[:3, :3] + if repetition: + sy = math.sqrt(M[i, j]*M[i, j] + M[i, k]*M[i, k]) + if sy > _EPS: + ax = math.atan2( M[i, j], M[i, k]) + ay = math.atan2( sy, M[i, i]) + az = math.atan2( M[j, i], -M[k, i]) + else: + ax = math.atan2(-M[j, k], M[j, j]) + ay = math.atan2( sy, M[i, i]) + az = 0.0 + else: + cy = math.sqrt(M[i, i]*M[i, i] + M[j, i]*M[j, i]) + if cy > _EPS: + ax = math.atan2( M[k, j], M[k, k]) + ay = math.atan2(-M[k, i], cy) + az = math.atan2( M[j, i], M[i, i]) + else: + ax = math.atan2(-M[j, k], M[j, j]) + ay = math.atan2(-M[k, i], cy) + az = 0.0 + + if parity: + ax, ay, az = -ax, -ay, -az + if frame: + ax, az = az, ax + return ax, ay, az + + +def euler_from_quaternion(quaternion, axes='sxyz'): + """Return Euler angles from quaternion for specified axis sequence. + >>> angles = euler_from_quaternion([0.06146124, 0, 0, 0.99810947]) + >>> numpy.allclose(angles, [0.123, 0, 0]) + True + """ + return euler_from_matrix(quaternion_matrix(quaternion), axes) + + +def quaternion_from_euler(ai, aj, ak, axes='sxyz'): + """Return quaternion from Euler angles and axis sequence. + ai, aj, ak : Euler's roll, pitch and yaw angles + axes : One of 24 axis sequences as string or encoded tuple + >>> q = quaternion_from_euler(1, 2, 3, 'ryxz') + >>> numpy.allclose(q, [0.310622, -0.718287, 0.444435, 0.435953]) + True + """ + try: + firstaxis, parity, repetition, frame = _AXES2TUPLE[axes.lower()] + except (AttributeError, KeyError): + _ = _TUPLE2AXES[axes] + firstaxis, parity, repetition, frame = axes + + i = firstaxis + j = _NEXT_AXIS[i+parity] + k = _NEXT_AXIS[i-parity+1] + + if frame: + ai, ak = ak, ai + if parity: + aj = -aj + + ai /= 2.0 + aj /= 2.0 + ak /= 2.0 + ci = math.cos(ai) + si = math.sin(ai) + cj = math.cos(aj) + sj = math.sin(aj) + ck = math.cos(ak) + sk = math.sin(ak) + cc = ci*ck + cs = ci*sk + sc = si*ck + ss = si*sk + + quaternion = numpy.empty((4, ), dtype=numpy.float64) + if repetition: + quaternion[i] = cj*(cs + sc) + quaternion[j] = sj*(cc + ss) + quaternion[k] = sj*(cs - sc) + quaternion[3] = cj*(cc - ss) + else: + quaternion[i] = cj*sc - sj*cs + quaternion[j] = cj*ss + sj*cc + quaternion[k] = cj*cs - sj*sc + quaternion[3] = cj*cc + sj*ss + if parity: + quaternion[j] *= -1 + + return quaternion + + +def quaternion_about_axis(angle, axis): + """Return quaternion for rotation about axis. + >>> q = quaternion_about_axis(0.123, (1, 0, 0)) + >>> numpy.allclose(q, [0.06146124, 0, 0, 0.99810947]) + True + """ + quaternion = numpy.zeros((4, ), dtype=numpy.float64) + quaternion[:3] = axis[:3] + qlen = vector_norm(quaternion) + if qlen > _EPS: + quaternion *= math.sin(angle/2.0) / qlen + quaternion[3] = math.cos(angle/2.0) + return quaternion + + +def quaternion_matrix(quaternion): + """Return homogeneous rotation matrix from quaternion. + >>> R = quaternion_matrix([0.06146124, 0, 0, 0.99810947]) + >>> numpy.allclose(R, rotation_matrix(0.123, (1, 0, 0))) + True + """ + q = numpy.array(quaternion[:4], dtype=numpy.float64, copy=True) + nq = numpy.dot(q, q) + if nq < _EPS: + return numpy.identity(4) + q *= math.sqrt(2.0 / nq) + q = numpy.outer(q, q) + return numpy.array(( + (1.0-q[1, 1]-q[2, 2], q[0, 1]-q[2, 3], q[0, 2]+q[1, 3], 0.0), + ( q[0, 1]+q[2, 3], 1.0-q[0, 0]-q[2, 2], q[1, 2]-q[0, 3], 0.0), + ( q[0, 2]-q[1, 3], q[1, 2]+q[0, 3], 1.0-q[0, 0]-q[1, 1], 0.0), + ( 0.0, 0.0, 0.0, 1.0) + ), dtype=numpy.float64) + + +def quaternion_from_matrix(matrix): + """Return quaternion from rotation matrix. + >>> R = rotation_matrix(0.123, (1, 2, 3)) + >>> q = quaternion_from_matrix(R) + >>> numpy.allclose(q, [0.0164262, 0.0328524, 0.0492786, 0.9981095]) + True + """ + q = numpy.empty((4, ), dtype=numpy.float64) + M = numpy.array(matrix, dtype=numpy.float64, copy=False)[:4, :4] + t = numpy.trace(M) + if t > M[3, 3]: + q[3] = t + q[2] = M[1, 0] - M[0, 1] + q[1] = M[0, 2] - M[2, 0] + q[0] = M[2, 1] - M[1, 2] + else: + i, j, k = 0, 1, 2 + if M[1, 1] > M[0, 0]: + i, j, k = 1, 2, 0 + if M[2, 2] > M[i, i]: + i, j, k = 2, 0, 1 + t = M[i, i] - (M[j, j] + M[k, k]) + M[3, 3] + q[i] = t + q[j] = M[i, j] + M[j, i] + q[k] = M[k, i] + M[i, k] + q[3] = M[k, j] - M[j, k] + q *= 0.5 / math.sqrt(t * M[3, 3]) + return q + + +def quaternion_multiply(quaternion1, quaternion0): + """Return multiplication of two quaternions. + >>> q = quaternion_multiply([1, -2, 3, 4], [-5, 6, 7, 8]) + >>> numpy.allclose(q, [-44, -14, 48, 28]) + True + """ + x0, y0, z0, w0 = quaternion0 + x1, y1, z1, w1 = quaternion1 + return numpy.array(( + x1*w0 + y1*z0 - z1*y0 + w1*x0, + -x1*z0 + y1*w0 + z1*x0 + w1*y0, + x1*y0 - y1*x0 + z1*w0 + w1*z0, + -x1*x0 - y1*y0 - z1*z0 + w1*w0), dtype=numpy.float64) + + +def quaternion_conjugate(quaternion): + """Return conjugate of quaternion. + >>> q0 = random_quaternion() + >>> q1 = quaternion_conjugate(q0) + >>> q1[3] == q0[3] and all(q1[:3] == -q0[:3]) + True + """ + return numpy.array((-quaternion[0], -quaternion[1], + -quaternion[2], quaternion[3]), dtype=numpy.float64) + + +def quaternion_inverse(quaternion): + """Return inverse of quaternion. + >>> q0 = random_quaternion() + >>> q1 = quaternion_inverse(q0) + >>> numpy.allclose(quaternion_multiply(q0, q1), [0, 0, 0, 1]) + True + """ + return quaternion_conjugate(quaternion) / numpy.dot(quaternion, quaternion) + + +def quaternion_slerp(quat0, quat1, fraction, spin=0, shortestpath=True): + """Return spherical linear interpolation between two quaternions. + >>> q0 = random_quaternion() + >>> q1 = random_quaternion() + >>> q = quaternion_slerp(q0, q1, 0.0) + >>> numpy.allclose(q, q0) + True + >>> q = quaternion_slerp(q0, q1, 1.0, 1) + >>> numpy.allclose(q, q1) + True + >>> q = quaternion_slerp(q0, q1, 0.5) + >>> angle = math.acos(numpy.dot(q0, q)) + >>> numpy.allclose(2.0, math.acos(numpy.dot(q0, q1)) / angle) or \ + numpy.allclose(2.0, math.acos(-numpy.dot(q0, q1)) / angle) + True + """ + q0 = unit_vector(quat0[:4]) + q1 = unit_vector(quat1[:4]) + if fraction == 0.0: + return q0 + elif fraction == 1.0: + return q1 + d = numpy.dot(q0, q1) + if abs(abs(d) - 1.0) < _EPS: + return q0 + if shortestpath and d < 0.0: + # invert rotation + d = -d + q1 *= -1.0 + angle = math.acos(d) + spin * math.pi + if abs(angle) < _EPS: + return q0 + isin = 1.0 / math.sin(angle) + q0 *= math.sin((1.0 - fraction) * angle) * isin + q1 *= math.sin(fraction * angle) * isin + q0 += q1 + return q0 + + +def random_quaternion(rand=None): + """Return uniform random unit quaternion. + rand: array like or None + Three independent random variables that are uniformly distributed + between 0 and 1. + >>> q = random_quaternion() + >>> numpy.allclose(1.0, vector_norm(q)) + True + >>> q = random_quaternion(numpy.random.random(3)) + >>> q.shape + (4,) + """ + if rand is None: + rand = numpy.random.rand(3) + else: + assert len(rand) == 3 + r1 = numpy.sqrt(1.0 - rand[0]) + r2 = numpy.sqrt(rand[0]) + pi2 = math.pi * 2.0 + t1 = pi2 * rand[1] + t2 = pi2 * rand[2] + return numpy.array((numpy.sin(t1)*r1, + numpy.cos(t1)*r1, + numpy.sin(t2)*r2, + numpy.cos(t2)*r2), dtype=numpy.float64) + + +def random_rotation_matrix(rand=None): + """Return uniform random rotation matrix. + rnd: array like + Three independent random variables that are uniformly distributed + between 0 and 1 for each returned quaternion. + >>> R = random_rotation_matrix() + >>> numpy.allclose(numpy.dot(R.T, R), numpy.identity(4)) + True + """ + return quaternion_matrix(random_quaternion(rand)) + + +class Arcball(object): + """Virtual Trackball Control. + >>> ball = Arcball() + >>> ball = Arcball(initial=numpy.identity(4)) + >>> ball.place([320, 320], 320) + >>> ball.down([500, 250]) + >>> ball.drag([475, 275]) + >>> R = ball.matrix() + >>> numpy.allclose(numpy.sum(R), 3.90583455) + True + >>> ball = Arcball(initial=[0, 0, 0, 1]) + >>> ball.place([320, 320], 320) + >>> ball.setaxes([1,1,0], [-1, 1, 0]) + >>> ball.setconstrain(True) + >>> ball.down([400, 200]) + >>> ball.drag([200, 400]) + >>> R = ball.matrix() + >>> numpy.allclose(numpy.sum(R), 0.2055924) + True + >>> ball.next() + """ + + def __init__(self, initial=None): + """Initialize virtual trackball control. + initial : quaternion or rotation matrix + """ + self._axis = None + self._axes = None + self._radius = 1.0 + self._center = [0.0, 0.0] + self._vdown = numpy.array([0, 0, 1], dtype=numpy.float64) + self._constrain = False + + if initial is None: + self._qdown = numpy.array([0, 0, 0, 1], dtype=numpy.float64) + else: + initial = numpy.array(initial, dtype=numpy.float64) + if initial.shape == (4, 4): + self._qdown = quaternion_from_matrix(initial) + elif initial.shape == (4, ): + initial /= vector_norm(initial) + self._qdown = initial + else: + raise ValueError("initial not a quaternion or matrix.") + + self._qnow = self._qpre = self._qdown + + def place(self, center, radius): + """Place Arcball, e.g. when window size changes. + center : sequence[2] + Window coordinates of trackball center. + radius : float + Radius of trackball in window coordinates. + """ + self._radius = float(radius) + self._center[0] = center[0] + self._center[1] = center[1] + + def setaxes(self, *axes): + """Set axes to constrain rotations.""" + if axes is None: + self._axes = None + else: + self._axes = [unit_vector(axis) for axis in axes] + + def setconstrain(self, constrain): + """Set state of constrain to axis mode.""" + self._constrain = constrain == True + + def getconstrain(self): + """Return state of constrain to axis mode.""" + return self._constrain + + def down(self, point): + """Set initial cursor window coordinates and pick constrain-axis.""" + self._vdown = arcball_map_to_sphere(point, self._center, self._radius) + self._qdown = self._qpre = self._qnow + + if self._constrain and self._axes is not None: + self._axis = arcball_nearest_axis(self._vdown, self._axes) + self._vdown = arcball_constrain_to_axis(self._vdown, self._axis) + else: + self._axis = None + + def drag(self, point): + """Update current cursor window coordinates.""" + vnow = arcball_map_to_sphere(point, self._center, self._radius) + + if self._axis is not None: + vnow = arcball_constrain_to_axis(vnow, self._axis) + + self._qpre = self._qnow + + t = numpy.cross(self._vdown, vnow) + if numpy.dot(t, t) < _EPS: + self._qnow = self._qdown + else: + q = [t[0], t[1], t[2], numpy.dot(self._vdown, vnow)] + self._qnow = quaternion_multiply(q, self._qdown) + + def next(self, acceleration=0.0): + """Continue rotation in direction of last drag.""" + q = quaternion_slerp(self._qpre, self._qnow, 2.0+acceleration, False) + self._qpre, self._qnow = self._qnow, q + + def matrix(self): + """Return homogeneous rotation matrix.""" + return quaternion_matrix(self._qnow) + + +def arcball_map_to_sphere(point, center, radius): + """Return unit sphere coordinates from window coordinates.""" + v = numpy.array(((point[0] - center[0]) / radius, + (center[1] - point[1]) / radius, + 0.0), dtype=numpy.float64) + n = v[0]*v[0] + v[1]*v[1] + if n > 1.0: + v /= math.sqrt(n) # position outside of sphere + else: + v[2] = math.sqrt(1.0 - n) + return v + + +def arcball_constrain_to_axis(point, axis): + """Return sphere point perpendicular to axis.""" + v = numpy.array(point, dtype=numpy.float64, copy=True) + a = numpy.array(axis, dtype=numpy.float64, copy=True) + v -= a * numpy.dot(a, v) # on plane + n = vector_norm(v) + if n > _EPS: + if v[2] < 0.0: + v *= -1.0 + v /= n + return v + if a[2] == 1.0: + return numpy.array([1, 0, 0], dtype=numpy.float64) + return unit_vector([-a[1], a[0], 0]) + + +def arcball_nearest_axis(point, axes): + """Return axis, which arc is nearest to point.""" + point = numpy.array(point, dtype=numpy.float64, copy=False) + nearest = None + mx = -1.0 + for axis in axes: + t = numpy.dot(arcball_constrain_to_axis(point, axis), point) + if t > mx: + nearest = axis + mx = t + return nearest + + +# epsilon for testing whether a number is close to zero +_EPS = numpy.finfo(float).eps * 4.0 + +# axis sequences for Euler angles +_NEXT_AXIS = [1, 2, 0, 1] + +# map axes strings to/from tuples of inner axis, parity, repetition, frame +_AXES2TUPLE = { + 'sxyz': (0, 0, 0, 0), 'sxyx': (0, 0, 1, 0), 'sxzy': (0, 1, 0, 0), + 'sxzx': (0, 1, 1, 0), 'syzx': (1, 0, 0, 0), 'syzy': (1, 0, 1, 0), + 'syxz': (1, 1, 0, 0), 'syxy': (1, 1, 1, 0), 'szxy': (2, 0, 0, 0), + 'szxz': (2, 0, 1, 0), 'szyx': (2, 1, 0, 0), 'szyz': (2, 1, 1, 0), + 'rzyx': (0, 0, 0, 1), 'rxyx': (0, 0, 1, 1), 'ryzx': (0, 1, 0, 1), + 'rxzx': (0, 1, 1, 1), 'rxzy': (1, 0, 0, 1), 'ryzy': (1, 0, 1, 1), + 'rzxy': (1, 1, 0, 1), 'ryxy': (1, 1, 1, 1), 'ryxz': (2, 0, 0, 1), + 'rzxz': (2, 0, 1, 1), 'rxyz': (2, 1, 0, 1), 'rzyz': (2, 1, 1, 1)} + +_TUPLE2AXES = dict((v, k) for k, v in _AXES2TUPLE.items()) + +# helper functions + +def vector_norm(data, axis=None, out=None): + """Return length, i.e. eucledian norm, of ndarray along axis. + >>> v = numpy.random.random(3) + >>> n = vector_norm(v) + >>> numpy.allclose(n, numpy.linalg.norm(v)) + True + >>> v = numpy.random.rand(6, 5, 3) + >>> n = vector_norm(v, axis=-1) + >>> numpy.allclose(n, numpy.sqrt(numpy.sum(v*v, axis=2))) + True + >>> n = vector_norm(v, axis=1) + >>> numpy.allclose(n, numpy.sqrt(numpy.sum(v*v, axis=1))) + True + >>> v = numpy.random.rand(5, 4, 3) + >>> n = numpy.empty((5, 3), dtype=numpy.float64) + >>> vector_norm(v, axis=1, out=n) + >>> numpy.allclose(n, numpy.sqrt(numpy.sum(v*v, axis=1))) + True + >>> vector_norm([]) + 0.0 + >>> vector_norm([1.0]) + 1.0 + """ + data = numpy.array(data, dtype=numpy.float64, copy=True) + if out is None: + if data.ndim == 1: + return math.sqrt(numpy.dot(data, data)) + data *= data + out = numpy.atleast_1d(numpy.sum(data, axis=axis)) + numpy.sqrt(out, out) + return out + else: + data *= data + numpy.sum(data, axis=axis, out=out) + numpy.sqrt(out, out) + + +def unit_vector(data, axis=None, out=None): + """Return ndarray normalized by length, i.e. eucledian norm, along axis. + >>> v0 = numpy.random.random(3) + >>> v1 = unit_vector(v0) + >>> numpy.allclose(v1, v0 / numpy.linalg.norm(v0)) + True + >>> v0 = numpy.random.rand(5, 4, 3) + >>> v1 = unit_vector(v0, axis=-1) + >>> v2 = v0 / numpy.expand_dims(numpy.sqrt(numpy.sum(v0*v0, axis=2)), 2) + >>> numpy.allclose(v1, v2) + True + >>> v1 = unit_vector(v0, axis=1) + >>> v2 = v0 / numpy.expand_dims(numpy.sqrt(numpy.sum(v0*v0, axis=1)), 1) + >>> numpy.allclose(v1, v2) + True + >>> v1 = numpy.empty((5, 4, 3), dtype=numpy.float64) + >>> unit_vector(v0, axis=1, out=v1) + >>> numpy.allclose(v1, v2) + True + >>> list(unit_vector([])) + [] + >>> list(unit_vector([1.0])) + [1.0] + """ + if out is None: + data = numpy.array(data, dtype=numpy.float64, copy=True) + if data.ndim == 1: + data /= math.sqrt(numpy.dot(data, data)) + return data + else: + if out is not data: + out[:] = numpy.array(data, copy=False) + data = out + length = numpy.atleast_1d(numpy.sum(data*data, axis)) + numpy.sqrt(length, length) + if axis is not None: + length = numpy.expand_dims(length, axis) + data /= length + if out is None: + return data + + +def random_vector(size): + """Return array of random doubles in the half-open interval [0.0, 1.0). + >>> v = random_vector(10000) + >>> numpy.all(v >= 0.0) and numpy.all(v < 1.0) + True + >>> v0 = random_vector(10) + >>> v1 = random_vector(10) + >>> numpy.any(v0 == v1) + False + """ + return numpy.random.random(size) + + +def inverse_matrix(matrix): + """Return inverse of square transformation matrix. + >>> M0 = random_rotation_matrix() + >>> M1 = inverse_matrix(M0.T) + >>> numpy.allclose(M1, numpy.linalg.inv(M0.T)) + True + >>> for size in range(1, 7): + ... M0 = numpy.random.rand(size, size) + ... M1 = inverse_matrix(M0) + ... if not numpy.allclose(M1, numpy.linalg.inv(M0)): print size + """ + return numpy.linalg.inv(matrix) + + +def concatenate_matrices(*matrices): + """Return concatenation of series of transformation matrices. + >>> M = numpy.random.rand(16).reshape((4, 4)) - 0.5 + >>> numpy.allclose(M, concatenate_matrices(M)) + True + >>> numpy.allclose(numpy.dot(M, M.T), concatenate_matrices(M, M.T)) + True + """ + M = numpy.identity(4) + for i in matrices: + M = numpy.dot(M, i) + return M + + +def is_same_transform(matrix0, matrix1): + """Return True if two matrices perform same transformation. + >>> is_same_transform(numpy.identity(4), numpy.identity(4)) + True + >>> is_same_transform(numpy.identity(4), random_rotation_matrix()) + False + """ + matrix0 = numpy.array(matrix0, dtype=numpy.float64, copy=True) + matrix0 /= matrix0[3, 3] + matrix1 = numpy.array(matrix1, dtype=numpy.float64, copy=True) + matrix1 /= matrix1[3, 3] + return numpy.allclose(matrix0, matrix1) + + +def _import_module(module_name, warn=True, prefix='_py_', ignore='_'): + """Try import all public attributes from module into global namespace. + Existing attributes with name clashes are renamed with prefix. + Attributes starting with underscore are ignored by default. + Return True on successful import. + """ + try: + module = __import__(module_name) + except ImportError: + if warn: + warnings.warn("Failed to import module " + module_name) + else: + for attr in dir(module): + if ignore and attr.startswith(ignore): + continue + if prefix: + if attr in globals(): + globals()[prefix + attr] = globals()[attr] + elif warn: + warnings.warn("No Python implementation of " + attr) + globals()[attr] = getattr(module, attr) + return True diff --git "a/\345\233\275\351\231\205\344\274\232\350\256\256.md" "b/\345\233\275\351\231\205\344\274\232\350\256\256.md" index 3b6f2033..71bdfc59 100644 --- "a/\345\233\275\351\231\205\344\274\232\350\256\256.md" +++ "b/\345\233\275\351\231\205\344\274\232\350\256\256.md" @@ -5,7 +5,9 @@ IEEE:Piscataway, NJ USENIX:Berkeley,CA +[IEEE 会议模板](https://www.ieee.org/conferences/publishing/templates.html) +[IEEE 期刊模板](https://journals.ieeeauthorcenter.ieee.org/create-your-ieee-article/authoring-tools-and-templates/ieee-article-templates/) # 数据库 diff --git "a/\350\265\204\346\226\231_baiduyun.txt" "b/\350\265\204\346\226\231_baiduyun.txt" new file mode 100644 index 00000000..0a658ee0 --- /dev/null +++ "b/\350\265\204\346\226\231_baiduyun.txt" @@ -0,0 +1,104 @@ + +# SLAM 资料 + + 作者:视觉IMAX + + 1.PnP算法简介与代码解析(视频+PPT课件+代码解析)链接:https://pan.baidu.com/s/1d9e0FaIvK_s8m1pMJvNXtg 密码:hf22 + 2.LeastSquare_and_gps_fusion(视频+PDF)链接:https://pan.baidu.com/s/1hi-fvkGwNM40esUueIDQzQ 密码:upcc + 3.Scan Matching in 2D SLAM(视频+PPT)链接:https://pan.baidu.com/s/1TZkuqp428bQZpnGw5-SiZg 密码:xocd + 4.LSD-SLAM深度解析(视频)链接:https://pan.baidu.com/s/1yKnrkiC-8LS0ahBN5r0UBA 密码:74br + 5.非线性优化与g2o(视频+PPT)链接:https://pan.baidu.com/s/1E3HuhLLrkrMLZGf1ZyNDag 密码:n1oh + 6.COP-SLAM - 杨俊(视频+PPT+其他)链接:https://pan.baidu.com/s/1dxm3xzBTyQ50WPkd0IyjQw 密码:4285 + 7.KinectFusion 和 ElasticFusion 三维重建方法 (视频+PDF)链接:https://pan.baidu.com/s/1cVlvM6bdDXZmqxnjxDeZAQ 密码:23ky + 8.rosbridge的原理和应用-董超(视频+PPT)链接:https://pan.baidu.com/s/1Xgc4y8-C5OnHF0MPXj2D0w 密码:r5tl + 9.优化与求解(视频+PDF)链接:https://pan.baidu.com/s/1wIjg38aOdav1pi-dwwhy9g 密码:kmoz + 10.图像技术在AR中的实践(视频+PDF)链接:https://pan.baidu.com/s/1xGBYrShOcZcDFtKMXg7dlA 密码:ylik + 11.激光SLAM(视频+PDF)链接:https://pan.baidu.com/s/1KGsn8LfZzFxQNiI0f2aHtQ 密码:iw7y + 12.双目视觉里程计(视频+课件+相关论文)链接:https://pan.baidu.com/s/1ckcc5pfmPgkMn9DxrCkVIg 密码:uj7l + 13.MEMS IMU的入门与应用(视频+PPT)链接:https://pan.baidu.com/s/115ZXuku0fH6Rt-mKzusSVQ 密码:6s5z + 14.IMU+动态背景消除(视频+PDF)链接:https://pan.baidu.com/s/1Ya36oenZpLS-6rTyAxEX2Q 密码:yrgu + 15.视觉SLAM中的矩阵李群基础(视频+课件)链接:https://pan.baidu.com/s/1PqiwvyvGSJxx3yKSgeehDA 密码:0n30 + 16.TLS安全网络传输协议简介(视频+PDF)链接:https://pan.baidu.com/s/1lwAd_yd5IuP7sU-Rb-JF-w 密码:g9ky + 17.深度学习及应用-颜沁睿链接:https://pan.baidu.com/s/1G_uSO-xonvWb8jU_c4_J9Q 密码:9c8g + 18.SVO & LSD_SLAM解析(视频+课件+代码)链接:https://pan.baidu.com/s/1D4HxbPwKBLxQWm-1wQxlvw 密码:yhxx + 19.caffe_intro(视频+课件)链接:https://pan.baidu.com/s/1EL4CtnujlCDpnAK-RMy62A 密码:a481 + 20.Robust camera Location Estimation(视频+课件)链接:https://pan.baidu.com/s/1-64qcmp0L9HWYb4GQYI9AQ 密码:ke3s + 21.SLAM中的可视化库介绍(视频+课件+代码)链接:https://pan.baidu.com/s/1PovlM_a5jEDV7wP-ZH242Q 密码:1zrp + 22.g2o简介(视频+课件)链接:https://pan.baidu.com/s/113ThVXOlLKqhjNvZb4cfGw 密码:vr7v + 23.我们如何定位SLAM?——关于技术创新、产品开发和产管理的经验和教训(视频+课件)链接:https://pan.baidu.com/s/1M-imrVR1Pab8xyqrvcXsHA 密码:pzqj + 24.矩阵流形上的优化(视频+课件)链接:https://pan.baidu.com/s/1SghsK6VL9-T7R6su0q6F4w 密码:brpz + 25.里程计视觉融合slam(视频+课件)链接:https://pan.baidu.com/s/1PY06j-a8KjUhiCAlp5Nwmg 密码:ll6t + 26.图匹配相关工作介绍(PPT+论文)链接:https://pan.baidu.com/s/1x-o2Y5mo-UYQm3aJ-AKKkw 密码:39zl + 27.ORB-SLAM2源码详解(视频+课件+源码)链接:https://pan.baidu.com/s/1BWUUsxWw0osfVRz69uraog 密码:uz41 + 28.Absolute Scale Estimation链接:https://pan.baidu.com/s/197hJym21UDWm5z9KHFmoXw 密码:c35w + 29.Structure Light Based 3D Surface Imaging链接:https://pan.baidu.com/s/14j1UFcPIKbZEZQeZp-vaBg 密码:xq0e + 30.视觉场景流链接:https://pan.baidu.com/s/1a4OcCW-dCxXgzsANI2SF2Q 密码:yz85 + 31.Robust Sfm & SLAM in Challenging Environments(视频+代码)链接:https://pan.baidu.com/s/174Xm_DkxTcvoH8EdMdsLsQ 密码:ymi5 + 32.图像特征的非刚性匹配(视频+课件)链接:https://pan.baidu.com/s/1c0UN4cU8Vf7LApcgiCQ30w 密码:3vxu + 33.DVS简介(视频+课件)链接:https://pan.baidu.com/s/1KQQaH_h5jNJhh8Jr8gDM9w 密码:17r8 + 34.Previewing ROSCon2016(视频+课件)链接:https://pan.baidu.com/s/153ZLgxHImvO4D9UQZWYd_Q 密码:cnu5 + 35.Event-based_Camera_VO(视频+课件) 链接:https://pan.baidu.com/s/1VDlBiXD9WuFxclAkS7J9pA 密码:4mnw + 36.build mobile game solvers - Surya(视频+课件)链接:https://pan.baidu.com/s/1h3qUMW8Zltn-Trd9cdRV4Q 密码:tks6 + 37.Template Attack(视频+课件)链接:https://pan.baidu.com/s/1OaYpRa-Wa1_FAJJWlAHv6Q 密码:tmgq + 38.Visual SLAM and Applications_BuShuhui(视频+课件)链接:https://pan.baidu.com/s/1UXEhfXIX05SYgAk2PcK9aQ 密码:ifwh + 39.Calibration for Mobile Robot System(视频+课件)链接:https://pan.baidu.com/s/1OVMeEC8YcyzyVLxyTtlNHA 密码:pw4m + 40.基于生物启发的多机器人协同环航和协同猎捕(视频+课件)链接:https://pan.baidu.com/s/1Cg8Dy9okY_YBHf1t9xLSJQ 密码:wnff + 41.压缩感知与量化表示(视频+PDF)链接:https://pan.baidu.com/s/1GSAOYdCQU7p52ljiNDggVg 密码:2plx + 42.gtsam_tutorial(视频+PDF)链接:https://pan.baidu.com/s/1u2IZnwG37Dsf1FdzpnOXCA 密码:4kf2 + 43.DSO初探(视频+Demo课件)链接:https://pan.baidu.com/s/1cR6R9WgtBvvoMY1shnAHjg 密码:56pv + 44.Planning in Robotics (视频+课件)链接:https://pan.baidu.com/s/13i56kiNCUggrsxtQsGa0Qw 密码:qtec + 45.From SFM SLAM to Autonomous Robots(视频+课件)链接:https://pan.baidu.com/s/19hYJ05KwdlSD4nAX8TRV7A 密码:hncb + 46. Real Time Tracking with DAVIS(课件)链接:https://pan.baidu.com/s/1LEQWSuVtBolraI91wKaj8A 密码:6bow + 47.视觉+惯性传感器的空间定位方法(视频+课件)链接:https://pan.baidu.com/s/1SgwOhN4HpJVMaTr3Ylw_1Q 密码:b7d5 + 48.Invariance Theory EKF SLAM (视频+课件)链接:https://pan.baidu.com/s/1a8uwjKfeC6YsyMubygLkng 密码:55nw + 49.DSO原理详解(视频+总结)链接:https://pan.baidu.com/s/1PQttBOOd--e67pYiUwxRig 密码:7l59 + 50.结构光与双目视觉(视频+课件)链接:https://pan.baidu.com/s/1bplcoAzOBNYPbU_Hbra-gQ 密码:b5uv + 51.Keras Introduction(视频+课件)链接:https://pan.baidu.com/s/1-nZYWvWQmE58h8FMZOHcaw 密码:68sk + 52.三维点云的地面分割算法介绍(视频+课件)链接:https://pan.baidu.com/s/15t4lV7DdXRVD9vB_VaF5Dw 密码:5slm + 53.解密Google Tango(视频+课件)链接:https://pan.baidu.com/s/1t9Xbt43DNNlj2ALnwWNKVg 密码:rikl + 54. Semantic SLAM初探(视频+课件)链接:https://pan.baidu.com/s/1Da1gk3Fn4VFpDOiSr2pgyw 密码:2oaa + 55.A Snapshot of Image guided Robotic Interventions(视频+PPT)链接:https://pan.baidu.com/s/1wJqyiSZvQCSPYV7Hv5aXnw 密码:i3r6 + 56.浅谈波束成形(视频+课件)链接:https://pan.baidu.com/s/1fA2RJKj8OGU-w6AmU0nHWg 密码:589b + 57.Geometry meets deep learning(视频+课件)链接:https://pan.baidu.com/s/1SDzz7rQtUDB0PrL6mD-A3A 密码:clq1 + 58.增强现实AR实战(视频+课件)链接:https://pan.baidu.com/s/1PiBAqGjguNKpPJbaGCuzMw 密码:qikp + 59.2D激光雷达扫描匹配方法及其在轮式移动机器人中的应用(视频+课件)链接:https://pan.baidu.com/s/1g5HBOy8Z1XYygOx-BbHrKA 密码:ow7b + 60.高斯过程在连续时间SLAM与运动规划中的应用(视频+课件)链接:https://pan.baidu.com/s/1iYi6g08bgYsIaVpHIrNYTQ 密码:pb1z + 61.基于单目视觉与惯导融合的定位与建图(视频+课件)链接:https://pan.baidu.com/s/1b3U6eDjKRjiWMqluOrN72g 密码:9gv7 + 62.移动AR产品如何做好性能优化(课件)链接:https://pan.baidu.com/s/17oEp3UpBsKmi67CPHOy1kw 密码:s7q0 + 63.图匹配概述(视频+课件)链接:https://pan.baidu.com/s/1PeZQ2ooEpuj70Z32BFP2gQ 密码:z07t + 64.ImageNet冠军模型SE(视频+课件)链接:https://pan.baidu.com/s/1QfrfNEddbVY9Bs27__mLSQ 密码:4dyj + 65.ARkit上手教程(视频+教程PPT)链接:https://pan.baidu.com/s/12ZmoAfqgiDPoBSuYyE_VkA 密码:00w9 + 66.多相机视觉SLAM介绍(视频+课件)链接:https://pan.baidu.com/s/1HFxFF-69U_nG6Bye6GvNzg 密码:j8uv + 67.Deep2Dvision(视频+课件)链接:https://pan.baidu.com/s/1iuD-FHLJlF9fj_0v-3YgRA 密码:5bgk + 68. 深度相机在计算机视觉中的应用(视频+课件)链接:https://pan.baidu.com/s/1gL2dJRycky-yUcaLFImObA 密码:72gn + 69. 路径规划-王超群链接:https://pan.baidu.com/s/1wbOp2AKqc-vDhUm1m2D7-g 密码:zcpz + 70. 工业相机选型及介绍-刘富强链接:https://pan.baidu.com/s/11xbAtxB1TFRCj9Lq9WOQ6g 密码:7xhc + 71. 摄像机自标定算法 - 张明链接:https://pan.baidu.com/s/1fEsshpS2MoGXokoQt3g-tw 密码:6v0n + 72. 邱强_机械臂运动规划链接:https://pan.baidu.com/s/1mRKoolkGOGOsxzDQvYO-OA 密码:reyl + 73.何安莉_硅谷文化与创业链接:https://pan.baidu.com/s/13LN2qx3bhSQgKbDZ3MCifg 密码:u0qc + 74. TLS安全网络传输协议简介-侯涛链接:https://pan.baidu.com/s/12IpTgbPzIRmVK25VjM2n0w 密码:n6m7 + + +# 机器视觉 资料 + + 1 图像处理软件的学习:https://pan.baidu.com/s/1MXGbr89rmMsCNt2eyO2_Ew 密码:jrkr + OpenCV视觉处理核心课程 + 点云库PCL学习教程 + + 2 计算机视觉&图像信号处理【课程视频合集】 + https://pan.baidu.com/s/1OWXwECQSgS8roYg-huB65g 密码:vz31 + + 3 数学【课程录像合集】 + https://pan.baidu.com/s/1ytbNq9Kf3WXgt_OfeGQaVg 密码:t34 + + 4 编程【电子书】 + https://pan.baidu.com/s/1YoMVTS5Mm7pdngUATC3qMA 密码:qz8m + + 5 计算机视觉【电子书】 + https://pan.baidu.com/s/17Yd0goJXpJN1walwobJHAQ 密码:qxij + + 6 机器学习与深度学习【视频】 + https://pan.baidu.com/s/1_NKHqOG4_AWqsdLhD06yXw 密码:5wuz + + +