SIMDCalc.cs 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062
  1. using FFTW.NET;
  2. using FxpConvert.Common;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Numerics;
  7. using System.Runtime.CompilerServices;
  8. using System.Runtime.Intrinsics;
  9. using System.Text;
  10. using System.Threading.Tasks;
  11. namespace SIMDFxpConvert
  12. {
  13. public sealed class SIMDCalc : ICalc
  14. {
  15. public IAdd Add { get; } = new SIMDAdd();
  16. public ISubtract Subtract { get; } = new SIMDSubtract();
  17. public IMultiply Multiply { get; } = new SIMDMultiply();
  18. public IDivision Division { get; } = new SIMDDivision();
  19. public IFFT FFT { get; } = new SIMDFFT();
  20. public IArraySum Sum { get; } = new SIMDArraySum();
  21. public unsafe void Fill(ref float result, float value, uint count)
  22. {
  23. if (count == 0) return;
  24. ref var source = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref result);
  25. var desc = Vector512<float>.One * value;
  26. uint onecount = (uint)(512 / (Unsafe.SizeOf<float>() * 8));
  27. uint c = count / onecount;
  28. uint c1 = count % onecount;
  29. uint start = c * onecount;
  30. for (int i = 0; i < c; i++)
  31. {
  32. ref var tempdesc = ref Unsafe.Add(ref source, i);
  33. tempdesc = desc;
  34. }
  35. if (c1 > 0)
  36. {
  37. float* resultptr = (float*)Unsafe.AsPointer(ref result);
  38. for (int i = 0; i < c1; i++)
  39. {
  40. resultptr[start + i] = value;
  41. }
  42. }
  43. }
  44. public unsafe void Fill(ref double result, double value, uint count)
  45. {
  46. if (count == 0) return;
  47. ref var source = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref result);
  48. var desc = Vector512<double>.One * value;
  49. uint onecount = (uint)(512 / (Unsafe.SizeOf<double>() * 8));
  50. uint c = count / onecount;
  51. uint c1 = count % onecount;
  52. uint start = c * onecount;
  53. for (int i = 0; i < c; i++)
  54. {
  55. ref var tempdesc = ref Unsafe.Add(ref source, i);
  56. tempdesc = desc;
  57. }
  58. if (c1 > 0)
  59. {
  60. double* resultptr = (double*)Unsafe.AsPointer(ref result);
  61. for (int i = 0; i < c1; i++)
  62. {
  63. resultptr[start + i] = value;
  64. }
  65. }
  66. }
  67. }
  68. public sealed class SIMDArraySum : IArraySum
  69. {
  70. public unsafe float Rms(ref float value, uint count)
  71. {
  72. if (count == 0) return 0;
  73. if (count == 1) return value;
  74. float temp = 0;
  75. float* ptr = (float*)Unsafe.AsPointer(ref value);
  76. uint onecount = (uint)(512 / (Unsafe.SizeOf<float>() * 8));
  77. uint c = count / onecount;
  78. uint c1 = count % onecount;
  79. uint start = c * onecount;
  80. ref var refvalue = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref value);
  81. for (int i = 0; i < c; i++)
  82. {
  83. ref var tempref = ref Unsafe.Add(ref refvalue, i);
  84. var t = tempref * tempref;
  85. for (int j = 0; j < onecount; j++)
  86. {
  87. temp += t[j];
  88. }
  89. }
  90. if (c1 > 0)
  91. {
  92. for (int i = 0; i < c1; i++)
  93. {
  94. temp += (ptr[start + i] * ptr[start + i]);
  95. }
  96. }
  97. return MathF.Sqrt(temp / count);
  98. }
  99. public unsafe double Rms(ref double value, uint count)
  100. {
  101. if (count == 0) return 0;
  102. if (count == 1) return value;
  103. double temp = 0;
  104. double* ptr = (double*)Unsafe.AsPointer(ref value);
  105. uint onecount = (uint)(512 / (Unsafe.SizeOf<double>() * 8));
  106. uint c = count / onecount;
  107. uint c1 = count % onecount;
  108. uint start = c * onecount;
  109. ref var refvalue = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref value);
  110. for (int i = 0; i < c; i++)
  111. {
  112. ref var tempref = ref Unsafe.Add(ref refvalue, i);
  113. tempref *= tempref;
  114. for (int j = 0; j < onecount; j++)
  115. {
  116. temp += tempref[j];
  117. }
  118. }
  119. if (c1 > 0)
  120. {
  121. for (int i = 0; i < c1; i++)
  122. {
  123. temp += (ptr[start + i] * ptr[start + i]);
  124. }
  125. }
  126. return Math.Sqrt(temp / count);
  127. }
  128. public unsafe float Sum(ref float value, uint count)
  129. {
  130. if (count == 0) return 0;
  131. if (count == 1) return value;
  132. float* ptr = (float*)Unsafe.AsPointer(ref value);
  133. float temp = value;
  134. for (int i = 1; i < count; i++)
  135. {
  136. temp += ptr[i];
  137. }
  138. return temp;
  139. }
  140. public unsafe double Sum(ref double value, uint count)
  141. {
  142. if (count == 0) return 0;
  143. if (count == 1) return value;
  144. double* ptr = (double*)Unsafe.AsPointer(ref value);
  145. double temp = value;
  146. for (int i = 1; i < count; i++)
  147. {
  148. temp += ptr[i];
  149. }
  150. return temp;
  151. }
  152. }
  153. public sealed class SIMDFFT : IFFT
  154. {
  155. public SIMDFFT()
  156. {
  157. FFTW.NET.FftwInterop.Initialize();
  158. }
  159. public void FFT(double[] real, double[] imaginary)
  160. {
  161. var result = FFTW.NET.DFT.FFT(real, imaginary);
  162. var tempreal = result.Select(x => x.Real).ToArray();
  163. var tempimg = result.Select(x => x.Imaginary).ToArray();
  164. Unsafe.CopyBlock(ref Unsafe.As<double, byte>(ref real[0]), ref Unsafe.As<double, byte>(ref tempreal[0]), (uint)(real.Length * Unsafe.SizeOf<double>()));
  165. Unsafe.CopyBlock(ref Unsafe.As<double, byte>(ref imaginary[0]), ref Unsafe.As<double, byte>(ref tempimg[0]), (uint)(real.Length * Unsafe.SizeOf<double>()));
  166. }
  167. public void FFT(float[] real, float[] imaginary)
  168. {
  169. var result = FFTW.NET.DFT.FFT(real.Select(x=> (double)x).ToArray(), imaginary.Select(x=> (double)x).ToArray());
  170. var tempreal = result.Select(x => (float)x.Real).ToArray();
  171. var tempimg = result.Select(x => (float)x.Imaginary).ToArray();
  172. Unsafe.CopyBlock(ref Unsafe.As<float, byte>(ref real[0]), ref Unsafe.As<float, byte>(ref tempreal[0]), (uint)(real.Length * Unsafe.SizeOf<float>()));
  173. Unsafe.CopyBlock(ref Unsafe.As<float, byte>(ref imaginary[0]), ref Unsafe.As<float, byte>(ref tempimg[0]), (uint)(real.Length * Unsafe.SizeOf<float>()));
  174. }
  175. public void IFFT(double[] real, double[] imaginary)
  176. {
  177. var result = FFTW.NET.DFT.IFFT(real, imaginary);
  178. var tempreal = result.Select(x => x.Real).ToArray();
  179. var tempimg = result.Select(x => x.Imaginary).ToArray();
  180. Unsafe.CopyBlock(ref Unsafe.As<double, byte>(ref real[0]), ref Unsafe.As<double, byte>(ref tempreal[0]), (uint)(real.Length * Unsafe.SizeOf<double>()));
  181. Unsafe.CopyBlock(ref Unsafe.As<double, byte>(ref imaginary[0]), ref Unsafe.As<double, byte>(ref tempimg[0]), (uint)(real.Length * Unsafe.SizeOf<double>()));
  182. }
  183. public void IFFT(float[] real, float[] imaginary)
  184. {
  185. var result = FFTW.NET.DFT.IFFT(real.Select(x => (double)x).ToArray(), imaginary.Select(x => (double)x).ToArray());
  186. var tempreal = result.Select(x => (float)x.Real).ToArray();
  187. var tempimg = result.Select(x => (float)x.Imaginary).ToArray();
  188. Unsafe.CopyBlock(ref Unsafe.As<float, byte>(ref real[0]), ref Unsafe.As<float, byte>(ref tempreal[0]), (uint)(real.Length * Unsafe.SizeOf<float>()));
  189. Unsafe.CopyBlock(ref Unsafe.As<float, byte>(ref imaginary[0]), ref Unsafe.As<float, byte>(ref tempimg[0]), (uint)(real.Length * Unsafe.SizeOf<float>()));
  190. }
  191. }
  192. public unsafe sealed class SIMDAdd : IAdd
  193. {
  194. public void Add(ref float left, float right, uint count, ref float result)
  195. {
  196. if (count == 0) return;
  197. ref var source = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref left);
  198. ref var desc = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref result);
  199. uint onecount = (uint)(512 / (Unsafe.SizeOf<float>() * 8));
  200. uint c = count / onecount;
  201. uint c1 = count % onecount;
  202. uint start = c * onecount;
  203. var rightarray = Enumerable.Repeat(right, (int)onecount).ToArray();
  204. ref var tempright = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref rightarray[0]);
  205. for (int i = 0; i < c; i++)
  206. {
  207. ref var tempdesc = ref Unsafe.Add(ref desc, i);
  208. tempdesc = Unsafe.Add(ref source, i) + tempright;
  209. }
  210. if (c1 > 0)
  211. {
  212. float* leftptr = (float*)Unsafe.AsPointer(ref left);
  213. float* resultptr = (float*)Unsafe.AsPointer(ref result);
  214. for (int i = 0; i < c1; i++)
  215. {
  216. resultptr[start + i] = leftptr[start + i] + right;
  217. }
  218. }
  219. }
  220. public void Add(ref float left, ref float right, uint count, ref float result)
  221. {
  222. if (count == 0) return;
  223. ref var source = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref left);
  224. ref var desc = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref result);
  225. uint onecount = (uint)(512 / (Unsafe.SizeOf<float>() * 8));
  226. uint c = count / onecount;
  227. uint c1 = count % onecount;
  228. uint start = c * onecount;
  229. ref var tempright = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref right);
  230. for (int i = 0; i < c; i++)
  231. {
  232. ref var tempdesc = ref Unsafe.Add(ref desc, i);
  233. tempdesc = Unsafe.Add(ref source, i) + Unsafe.Add(ref tempright, i);
  234. }
  235. if (c1 > 0)
  236. {
  237. float* leftptr = (float*)Unsafe.AsPointer(ref left);
  238. float* resultptr = (float*)Unsafe.AsPointer(ref result);
  239. float* rightptr = (float*)Unsafe.AsPointer(ref right);
  240. for (int i = 0; i < c1; i++)
  241. {
  242. resultptr[start + i] = leftptr[start + i] + rightptr[start + i];
  243. }
  244. }
  245. }
  246. public void Add(ref float left, float right, uint count)
  247. {
  248. if (count == 0) return;
  249. ref var source = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref left);
  250. uint onecount = (uint)(512 / (Unsafe.SizeOf<float>() * 8));
  251. uint c = count / onecount;
  252. uint c1 = count % onecount;
  253. uint start = c * onecount;
  254. var rightarray = Enumerable.Repeat(right, (int)onecount).ToArray();
  255. ref var tempright = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref rightarray[0]);
  256. for (int i = 0; i < c; i++)
  257. {
  258. ref var tempdesc = ref Unsafe.Add(ref source, i);
  259. tempdesc += tempright;
  260. }
  261. if (c1 > 0)
  262. {
  263. float* leftptr = (float*)Unsafe.AsPointer(ref left);
  264. for (int i = 0; i < c1; i++)
  265. {
  266. leftptr[start + i] += right;
  267. }
  268. }
  269. }
  270. public void Add(ref float left, ref float right, uint count)
  271. {
  272. if (count == 0) return;
  273. ref var source = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref left);
  274. uint onecount = (uint)(512 / (Unsafe.SizeOf<float>() * 8));
  275. uint c = count / onecount;
  276. uint c1 = count % onecount;
  277. uint start = c * onecount;
  278. ref var tempright = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref right);
  279. for (int i = 0; i < c; i++)
  280. {
  281. ref var tempdesc = ref Unsafe.Add(ref source, i);
  282. tempdesc += Unsafe.Add(ref tempright, i);
  283. }
  284. if (c1 > 0)
  285. {
  286. float* leftptr = (float*)Unsafe.AsPointer(ref left);
  287. float* rightptr = (float*)Unsafe.AsPointer(ref right);
  288. for (int i = 0; i < c1; i++)
  289. {
  290. leftptr[start + i] += rightptr[start + i];
  291. }
  292. }
  293. }
  294. public void Add(ref double left, double right, uint count, ref double result)
  295. {
  296. if (count == 0) return;
  297. ref var source = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref left);
  298. ref var desc = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref result);
  299. uint onecount = (uint)(512 / (Unsafe.SizeOf<double>() * 8));
  300. uint c = count / onecount;
  301. uint c1 = count % onecount;
  302. uint start = c * onecount;
  303. var rightarray = Enumerable.Repeat(right, (int)onecount).ToArray();
  304. ref var tempright = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref rightarray[0]);
  305. for (int i = 0; i < c; i++)
  306. {
  307. ref var tempdesc = ref Unsafe.Add(ref desc, i);
  308. tempdesc = Unsafe.Add(ref source, i) + tempright;
  309. }
  310. if (c1 > 0)
  311. {
  312. double* leftptr = (double*)Unsafe.AsPointer(ref left);
  313. double* resultptr = (double*)Unsafe.AsPointer(ref result);
  314. for (int i = 0; i < c1; i++)
  315. {
  316. resultptr[start + i] = leftptr[start + i] + right;
  317. }
  318. }
  319. }
  320. public void Add(ref double left, ref double right, uint count, ref double result)
  321. {
  322. if (count == 0) return;
  323. ref var source = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref left);
  324. ref var desc = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref result);
  325. uint onecount = (uint)(512 / (Unsafe.SizeOf<double>() * 8));
  326. uint c = count / onecount;
  327. uint c1 = count % onecount;
  328. uint start = c * onecount;
  329. ref var tempright = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref right);
  330. for (int i = 0; i < c; i++)
  331. {
  332. ref var tempdesc = ref Unsafe.Add(ref desc, i);
  333. tempdesc = Unsafe.Add(ref source, i) + Unsafe.Add(ref tempright, i);
  334. }
  335. if (c1 > 0)
  336. {
  337. double* leftptr = (double*)Unsafe.AsPointer(ref left);
  338. double* resultptr = (double*)Unsafe.AsPointer(ref result);
  339. double* rightptr = (double*)Unsafe.AsPointer(ref right);
  340. for (int i = 0; i < c1; i++)
  341. {
  342. resultptr[start + i] = leftptr[start + i] + rightptr[start + i];
  343. }
  344. }
  345. }
  346. public void Add(ref double left, double right, uint count)
  347. {
  348. if (count == 0) return;
  349. ref var source = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref left);
  350. uint onecount = (uint)(512 / (Unsafe.SizeOf<double>() * 8));
  351. uint c = count / onecount;
  352. uint c1 = count % onecount;
  353. uint start = c * onecount;
  354. var rightarray = Enumerable.Repeat(right, (int)onecount).ToArray();
  355. ref var tempright = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref rightarray[0]);
  356. for (int i = 0; i < c; i++)
  357. {
  358. ref var tempdesc = ref Unsafe.Add(ref source, i);
  359. tempdesc += tempright;
  360. }
  361. if (c1 > 0)
  362. {
  363. double* leftptr = (double*)Unsafe.AsPointer(ref left);
  364. for (int i = 0; i < c1; i++)
  365. {
  366. leftptr[start + i] += right;
  367. }
  368. }
  369. }
  370. public void Add(ref double left, ref double right, uint count)
  371. {
  372. if (count == 0) return;
  373. ref var source = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref left);
  374. uint onecount = (uint)(512 / (Unsafe.SizeOf<double>() * 8));
  375. uint c = count / onecount;
  376. uint c1 = count % onecount;
  377. uint start = c * onecount;
  378. ref var tempright = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref right);
  379. for (int i = 0; i < c; i++)
  380. {
  381. ref var tempdesc = ref Unsafe.Add(ref source, i);
  382. tempdesc += Unsafe.Add(ref tempright, i);
  383. }
  384. if (c1 > 0)
  385. {
  386. double* leftptr = (double*)Unsafe.AsPointer(ref left);
  387. double* rightptr = (double*)Unsafe.AsPointer(ref right);
  388. for (int i = 0; i < c1; i++)
  389. {
  390. leftptr[start + i] += rightptr[start + i];
  391. }
  392. }
  393. }
  394. }
  395. public unsafe sealed class SIMDSubtract : ISubtract
  396. {
  397. public void Subtract(ref float left, float right, uint count, ref float result)
  398. {
  399. if (count == 0) return;
  400. ref var source = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref left);
  401. ref var desc = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref result);
  402. uint onecount = (uint)(512 / (Unsafe.SizeOf<float>() * 8));
  403. uint c = count / onecount;
  404. uint c1 = count % onecount;
  405. uint start = c * onecount;
  406. var rightarray = Enumerable.Repeat(right, (int)onecount).ToArray();
  407. ref var tempright = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref rightarray[0]);
  408. for (int i = 0; i < c; i++)
  409. {
  410. ref var tempdesc = ref Unsafe.Add(ref desc, i);
  411. tempdesc = Unsafe.Add(ref source, i) - tempright;
  412. }
  413. if (c1 > 0)
  414. {
  415. float* leftptr = (float*)Unsafe.AsPointer(ref left);
  416. float* resultptr = (float*)Unsafe.AsPointer(ref result);
  417. for (int i = 0; i < c1; i++)
  418. {
  419. resultptr[start + i] = leftptr[start + i] - right;
  420. }
  421. }
  422. }
  423. public void Subtract(ref float left, ref float right, uint count, ref float result)
  424. {
  425. if (count == 0) return;
  426. ref var source = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref left);
  427. ref var desc = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref result);
  428. uint onecount = (uint)(512 / (Unsafe.SizeOf<float>() * 8));
  429. uint c = count / onecount;
  430. uint c1 = count % onecount;
  431. uint start = c * onecount;
  432. ref var tempright = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref right);
  433. for (int i = 0; i < c; i++)
  434. {
  435. ref var tempdesc = ref Unsafe.Add(ref desc, i);
  436. tempdesc = Unsafe.Add(ref source, i) - Unsafe.Add(ref tempright, i);
  437. }
  438. if (c1 > 0)
  439. {
  440. float* leftptr = (float*)Unsafe.AsPointer(ref left);
  441. float* resultptr = (float*)Unsafe.AsPointer(ref result);
  442. float* rightptr = (float*)Unsafe.AsPointer(ref right);
  443. for (int i = 0; i < c1; i++)
  444. {
  445. resultptr[start + i] = leftptr[start + i] - rightptr[start + i];
  446. }
  447. }
  448. }
  449. public void Subtract(ref float left, float right, uint count)
  450. {
  451. if (count == 0) return;
  452. ref var source = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref left);
  453. uint onecount = (uint)(512 / (Unsafe.SizeOf<float>() * 8));
  454. uint c = count / onecount;
  455. uint c1 = count % onecount;
  456. uint start = c * onecount;
  457. var rightarray = Enumerable.Repeat(right, (int)onecount).ToArray();
  458. ref var tempright = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref rightarray[0]);
  459. for (int i = 0; i < c; i++)
  460. {
  461. ref var tempdesc = ref Unsafe.Add(ref source, i);
  462. tempdesc -= tempright;
  463. }
  464. if (c1 > 0)
  465. {
  466. float* leftptr = (float*)Unsafe.AsPointer(ref left);
  467. for (int i = 0; i < c1; i++)
  468. {
  469. leftptr[start + i] -= right;
  470. }
  471. }
  472. }
  473. public void Subtract(ref float left, ref float right, uint count)
  474. {
  475. if (count == 0) return;
  476. ref var source = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref left);
  477. uint onecount = (uint)(512 / (Unsafe.SizeOf<float>() * 8));
  478. uint c = count / onecount;
  479. uint c1 = count % onecount;
  480. uint start = c * onecount;
  481. ref var tempright = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref right);
  482. for (int i = 0; i < c; i++)
  483. {
  484. ref var tempdesc = ref Unsafe.Add(ref source, i);
  485. tempdesc -= Unsafe.Add(ref tempright, i);
  486. }
  487. if (c1 > 0)
  488. {
  489. float* leftptr = (float*)Unsafe.AsPointer(ref left);
  490. float* rightptr = (float*)Unsafe.AsPointer(ref right);
  491. for (int i = 0; i < c1; i++)
  492. {
  493. leftptr[start + i] -= rightptr[start + i];
  494. }
  495. }
  496. }
  497. public void Subtract(ref double left, double right, uint count, ref double result)
  498. {
  499. if (count == 0) return;
  500. ref var source = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref left);
  501. ref var desc = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref result);
  502. uint onecount = (uint)(512 / (Unsafe.SizeOf<double>() * 8));
  503. uint c = count / onecount;
  504. uint c1 = count % onecount;
  505. uint start = c * onecount;
  506. var rightarray = Enumerable.Repeat(right, (int)onecount).ToArray();
  507. ref var tempright = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref rightarray[0]);
  508. for (int i = 0; i < c; i++)
  509. {
  510. ref var tempdesc = ref Unsafe.Add(ref desc, i);
  511. tempdesc = Unsafe.Add(ref source, i) - tempright;
  512. }
  513. if (c1 > 0)
  514. {
  515. double* leftptr = (double*)Unsafe.AsPointer(ref left);
  516. double* resultptr = (double*)Unsafe.AsPointer(ref result);
  517. for (int i = 0; i < c1; i++)
  518. {
  519. resultptr[start + i] = leftptr[start + i] - right;
  520. }
  521. }
  522. }
  523. public void Subtract(ref double left, ref double right, uint count, ref double result)
  524. {
  525. if (count == 0) return;
  526. ref var source = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref left);
  527. ref var desc = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref result);
  528. uint onecount = (uint)(512 / (Unsafe.SizeOf<double>() * 8));
  529. uint c = count / onecount;
  530. uint c1 = count % onecount;
  531. uint start = c * onecount;
  532. ref var tempright = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref right);
  533. for (int i = 0; i < c; i++)
  534. {
  535. ref var tempdesc = ref Unsafe.Add(ref desc, i);
  536. tempdesc = Unsafe.Add(ref source, i) - Unsafe.Add(ref tempright, i);
  537. }
  538. if (c1 > 0)
  539. {
  540. double* leftptr = (double*)Unsafe.AsPointer(ref left);
  541. double* resultptr = (double*)Unsafe.AsPointer(ref result);
  542. double* rightptr = (double*)Unsafe.AsPointer(ref right);
  543. for (int i = 0; i < c1; i++)
  544. {
  545. resultptr[start + i] = leftptr[start + i] - rightptr[start + i];
  546. }
  547. }
  548. }
  549. public void Subtract(ref double left, double right, uint count)
  550. {
  551. if (count == 0) return;
  552. ref var source = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref left);
  553. uint onecount = (uint)(512 / (Unsafe.SizeOf<double>() * 8));
  554. uint c = count / onecount;
  555. uint c1 = count % onecount;
  556. uint start = c * onecount;
  557. var rightarray = Enumerable.Repeat(right, (int)onecount).ToArray();
  558. ref var tempright = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref rightarray[0]);
  559. for (int i = 0; i < c; i++)
  560. {
  561. ref var tempdesc = ref Unsafe.Add(ref source, i);
  562. tempdesc -= tempright;
  563. }
  564. if (c1 > 0)
  565. {
  566. double* leftptr = (double*)Unsafe.AsPointer(ref left);
  567. for (int i = 0; i < c1; i++)
  568. {
  569. leftptr[start + i] -= right;
  570. }
  571. }
  572. }
  573. public void Subtract(ref double left, ref double right, uint count)
  574. {
  575. if (count == 0) return;
  576. ref var source = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref left);
  577. uint onecount = (uint)(512 / (Unsafe.SizeOf<double>() * 8));
  578. uint c = count / onecount;
  579. uint c1 = count % onecount;
  580. uint start = c * onecount;
  581. ref var tempright = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref right);
  582. for (int i = 0; i < c; i++)
  583. {
  584. ref var tempdesc = ref Unsafe.Add(ref source, i);
  585. tempdesc -= Unsafe.Add(ref tempright, i);
  586. }
  587. if (c1 > 0)
  588. {
  589. double* leftptr = (double*)Unsafe.AsPointer(ref left);
  590. double* rightptr = (double*)Unsafe.AsPointer(ref right);
  591. for (int i = 0; i < c1; i++)
  592. {
  593. leftptr[start + i] -= rightptr[start + i];
  594. }
  595. }
  596. }
  597. }
  598. public unsafe sealed class SIMDMultiply : IMultiply
  599. {
  600. public void Multiply(ref float left, float right, uint count, ref float result)
  601. {
  602. if (count == 0) return;
  603. ref var source = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref left);
  604. ref var desc = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref result);
  605. uint onecount = (uint)(512 / (Unsafe.SizeOf<float>() * 8));
  606. uint c = count / onecount;
  607. uint c1 = count % onecount;
  608. uint start = c * onecount;
  609. for (int i = 0; i < c; i++)
  610. {
  611. ref var tempdesc = ref Unsafe.Add(ref desc, i);
  612. tempdesc = Unsafe.Add(ref source, i) * right;
  613. }
  614. if (c1 > 0)
  615. {
  616. float* leftptr = (float*)Unsafe.AsPointer(ref left);
  617. float* resultptr = (float*)Unsafe.AsPointer(ref result);
  618. for (int i = 0; i < c1; i++)
  619. {
  620. resultptr[start + i] = leftptr[start + i] * right;
  621. }
  622. }
  623. }
  624. public void Multiply(ref float left, ref float right, uint count, ref float result)
  625. {
  626. if (count == 0) return;
  627. ref var source = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref left);
  628. ref var desc = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref result);
  629. uint onecount = (uint)(512 / (Unsafe.SizeOf<float>() * 8));
  630. uint c = count / onecount;
  631. uint c1 = count % onecount;
  632. uint start = c * onecount;
  633. ref var tempright = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref right);
  634. for (int i = 0; i < c; i++)
  635. {
  636. ref var tempdesc = ref Unsafe.Add(ref desc, i);
  637. tempdesc = Unsafe.Add(ref source, i) * Unsafe.Add(ref tempright, i);
  638. }
  639. if (c1 > 0)
  640. {
  641. float* leftptr = (float*)Unsafe.AsPointer(ref left);
  642. float* resultptr = (float*)Unsafe.AsPointer(ref result);
  643. float* rightptr = (float*)Unsafe.AsPointer(ref right);
  644. for (int i = 0; i < c1; i++)
  645. {
  646. resultptr[start + i] = leftptr[start + i] * rightptr[start + i];
  647. }
  648. }
  649. }
  650. public void Multiply(ref float left, float right, uint count)
  651. {
  652. if (count == 0) return;
  653. ref var source = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref left);
  654. uint onecount = (uint)(512 / (Unsafe.SizeOf<float>() * 8));
  655. uint c = count / onecount;
  656. uint c1 = count % onecount;
  657. uint start = c * onecount;
  658. for (int i = 0; i < c; i++)
  659. {
  660. ref var tempdesc = ref Unsafe.Add(ref source, i);
  661. tempdesc *= right;
  662. }
  663. if (c1 > 0)
  664. {
  665. float* leftptr = (float*)Unsafe.AsPointer(ref left);
  666. for (int i = 0; i < c1; i++)
  667. {
  668. leftptr[start + i] *= right;
  669. }
  670. }
  671. }
  672. public void Multiply(ref float left, ref float right, uint count)
  673. {
  674. if (count == 0) return;
  675. ref var source = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref left);
  676. uint onecount = (uint)(512 / (Unsafe.SizeOf<float>() * 8));
  677. uint c = count / onecount;
  678. uint c1 = count % onecount;
  679. uint start = c * onecount;
  680. ref var tempright = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref right);
  681. for (int i = 0; i < c; i++)
  682. {
  683. ref var tempdesc = ref Unsafe.Add(ref source, i);
  684. tempdesc *= Unsafe.Add(ref tempright, i);
  685. }
  686. if (c1 > 0)
  687. {
  688. float* leftptr = (float*)Unsafe.AsPointer(ref left);
  689. float* rightptr = (float*)Unsafe.AsPointer(ref right);
  690. for (int i = 0; i < c1; i++)
  691. {
  692. leftptr[start + i] *= rightptr[start + i];
  693. }
  694. }
  695. }
  696. public void Multiply(ref double left, double right, uint count, ref double result)
  697. {
  698. if (count == 0) return;
  699. ref var source = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref left);
  700. ref var desc = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref result);
  701. uint onecount = (uint)(512 / (Unsafe.SizeOf<double>() * 8));
  702. uint c = count / onecount;
  703. uint c1 = count % onecount;
  704. uint start = c * onecount;
  705. for (int i = 0; i < c; i++)
  706. {
  707. ref var tempdesc = ref Unsafe.Add(ref desc, i);
  708. tempdesc = Unsafe.Add(ref source, i) * right;
  709. }
  710. if (c1 > 0)
  711. {
  712. double* leftptr = (double*)Unsafe.AsPointer(ref left);
  713. double* resultptr = (double*)Unsafe.AsPointer(ref result);
  714. for (int i = 0; i < c1; i++)
  715. {
  716. resultptr[start + i] = leftptr[start + i] * right;
  717. }
  718. }
  719. }
  720. public void Multiply(ref double left, ref double right, uint count, ref double result)
  721. {
  722. if (count == 0) return;
  723. ref var source = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref left);
  724. ref var desc = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref result);
  725. uint onecount = (uint)(512 / (Unsafe.SizeOf<double>() * 8));
  726. uint c = count / onecount;
  727. uint c1 = count % onecount;
  728. uint start = c * onecount;
  729. ref var tempright = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref right);
  730. for (int i = 0; i < c; i++)
  731. {
  732. ref var tempdesc = ref Unsafe.Add(ref desc, i);
  733. tempdesc = Unsafe.Add(ref source, i) * Unsafe.Add(ref tempright, i);
  734. }
  735. if (c1 > 0)
  736. {
  737. double* leftptr = (double*)Unsafe.AsPointer(ref left);
  738. double* resultptr = (double*)Unsafe.AsPointer(ref result);
  739. double* rightptr = (double*)Unsafe.AsPointer(ref right);
  740. for (int i = 0; i < c1; i++)
  741. {
  742. resultptr[start + i] = leftptr[start + i] * rightptr[start + i];
  743. }
  744. }
  745. }
  746. public void Multiply(ref double left, double right, uint count)
  747. {
  748. if (count == 0) return;
  749. ref var source = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref left);
  750. uint onecount = (uint)(512 / (Unsafe.SizeOf<double>() * 8));
  751. uint c = count / onecount;
  752. uint c1 = count % onecount;
  753. uint start = c * onecount;
  754. for (int i = 0; i < c; i++)
  755. {
  756. ref var tempdesc = ref Unsafe.Add(ref source, i);
  757. tempdesc *= right;
  758. }
  759. if (c1 > 0)
  760. {
  761. double* leftptr = (double*)Unsafe.AsPointer(ref left);
  762. for (int i = 0; i < c1; i++)
  763. {
  764. leftptr[start + i] *= right;
  765. }
  766. }
  767. }
  768. public void Multiply(ref double left, ref double right, uint count)
  769. {
  770. if (count == 0) return;
  771. ref var source = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref left);
  772. uint onecount = (uint)(512 / (Unsafe.SizeOf<double>() * 8));
  773. uint c = count / onecount;
  774. uint c1 = count % onecount;
  775. uint start = c * onecount;
  776. ref var tempright = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref right);
  777. for (int i = 0; i < c; i++)
  778. {
  779. ref var tempdesc = ref Unsafe.Add(ref source, i);
  780. tempdesc *= Unsafe.Add(ref tempright, i);
  781. }
  782. if (c1 > 0)
  783. {
  784. double* leftptr = (double*)Unsafe.AsPointer(ref left);
  785. double* rightptr = (double*)Unsafe.AsPointer(ref right);
  786. for (int i = 0; i < c1; i++)
  787. {
  788. leftptr[start + i] *= rightptr[start + i];
  789. }
  790. }
  791. }
  792. }
  793. public unsafe sealed class SIMDDivision : IDivision
  794. {
  795. public void Division(ref float left, float right, uint count, ref float result)
  796. {
  797. if (count == 0) return;
  798. ref var source = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref left);
  799. ref var desc = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref result);
  800. uint onecount = (uint)(512 / (Unsafe.SizeOf<float>() * 8));
  801. uint c = count / onecount;
  802. uint c1 = count % onecount;
  803. uint start = c * onecount;
  804. for (int i = 0; i < c; i++)
  805. {
  806. ref var tempdesc = ref Unsafe.Add(ref desc, i);
  807. tempdesc = Unsafe.Add(ref source, i) / right;
  808. }
  809. if (c1 > 0)
  810. {
  811. float* leftptr = (float*)Unsafe.AsPointer(ref left);
  812. float* resultptr = (float*)Unsafe.AsPointer(ref result);
  813. for (int i = 0; i < c1; i++)
  814. {
  815. resultptr[start + i] = leftptr[start + i] / right;
  816. }
  817. }
  818. }
  819. public void Division(ref float left, ref float right, uint count, ref float result)
  820. {
  821. if (count == 0) return;
  822. ref var source = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref left);
  823. ref var desc = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref result);
  824. uint onecount = (uint)(512 / (Unsafe.SizeOf<float>() * 8));
  825. uint c = count / onecount;
  826. uint c1 = count % onecount;
  827. uint start = c * onecount;
  828. ref var tempright = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref right);
  829. for (int i = 0; i < c; i++)
  830. {
  831. ref var tempdesc = ref Unsafe.Add(ref desc, i);
  832. tempdesc = Unsafe.Add(ref source, i) / Unsafe.Add(ref tempright, i);
  833. }
  834. if (c1 > 0)
  835. {
  836. float* leftptr = (float*)Unsafe.AsPointer(ref left);
  837. float* resultptr = (float*)Unsafe.AsPointer(ref result);
  838. float* rightptr = (float*)Unsafe.AsPointer(ref right);
  839. for (int i = 0; i < c1; i++)
  840. {
  841. resultptr[start + i] = leftptr[start + i] / rightptr[start + i];
  842. }
  843. }
  844. }
  845. public void Division(ref float left, float right, uint count)
  846. {
  847. if (count == 0) return;
  848. ref var source = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref left);
  849. uint onecount = (uint)(512 / (Unsafe.SizeOf<float>() * 8));
  850. uint c = count / onecount;
  851. uint c1 = count % onecount;
  852. uint start = c * onecount;
  853. for (int i = 0; i < c; i++)
  854. {
  855. ref var tempdesc = ref Unsafe.Add(ref source, i);
  856. tempdesc /= right;
  857. }
  858. if (c1 > 0)
  859. {
  860. float* leftptr = (float*)Unsafe.AsPointer(ref left);
  861. for (int i = 0; i < c1; i++)
  862. {
  863. leftptr[start + i] /= right;
  864. }
  865. }
  866. }
  867. public void Division(ref float left, ref float right, uint count)
  868. {
  869. if (count == 0) return;
  870. ref var source = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref left);
  871. uint onecount = (uint)(512 / (Unsafe.SizeOf<float>() * 8));
  872. uint c = count / onecount;
  873. uint c1 = count % onecount;
  874. uint start = c * onecount;
  875. ref var tempright = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref right);
  876. for (int i = 0; i < c; i++)
  877. {
  878. ref var tempdesc = ref Unsafe.Add(ref source, i);
  879. tempdesc /= Unsafe.Add(ref tempright, i);
  880. }
  881. if (c1 > 0)
  882. {
  883. float* leftptr = (float*)Unsafe.AsPointer(ref left);
  884. float* rightptr = (float*)Unsafe.AsPointer(ref right);
  885. for (int i = 0; i < c1; i++)
  886. {
  887. leftptr[start + i] /= rightptr[start + i];
  888. }
  889. }
  890. }
  891. public void Division(ref double left, double right, uint count, ref double result)
  892. {
  893. if (count == 0) return;
  894. ref var source = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref left);
  895. ref var desc = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref result);
  896. uint onecount = (uint)(512 / (Unsafe.SizeOf<double>() * 8));
  897. uint c = count / onecount;
  898. uint c1 = count % onecount;
  899. uint start = c * onecount;
  900. for (int i = 0; i < c; i++)
  901. {
  902. ref var tempdesc = ref Unsafe.Add(ref desc, i);
  903. tempdesc = Unsafe.Add(ref source, i) / right;
  904. }
  905. if (c1 > 0)
  906. {
  907. double* leftptr = (double*)Unsafe.AsPointer(ref left);
  908. double* resultptr = (double*)Unsafe.AsPointer(ref result);
  909. for (int i = 0; i < c1; i++)
  910. {
  911. resultptr[start + i] = leftptr[start + i] / right;
  912. }
  913. }
  914. }
  915. public void Division(ref double left, ref double right, uint count, ref double result)
  916. {
  917. if (count == 0) return;
  918. ref var source = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref left);
  919. ref var desc = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref result);
  920. uint onecount = (uint)(512 / (Unsafe.SizeOf<double>() * 8));
  921. uint c = count / onecount;
  922. uint c1 = count % onecount;
  923. uint start = c * onecount;
  924. ref var tempright = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref right);
  925. for (int i = 0; i < c; i++)
  926. {
  927. ref var tempdesc = ref Unsafe.Add(ref desc, i);
  928. tempdesc = Unsafe.Add(ref source, i) / Unsafe.Add(ref tempright, i);
  929. }
  930. if (c1 > 0)
  931. {
  932. double* leftptr = (double*)Unsafe.AsPointer(ref left);
  933. double* resultptr = (double*)Unsafe.AsPointer(ref result);
  934. double* rightptr = (double*)Unsafe.AsPointer(ref right);
  935. for (int i = 0; i < c1; i++)
  936. {
  937. resultptr[start + i] = leftptr[start + i] / rightptr[start + i];
  938. }
  939. }
  940. }
  941. public void Division(ref double left, double right, uint count)
  942. {
  943. if (count == 0) return;
  944. ref var source = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref left);
  945. uint onecount = (uint)(512 / (Unsafe.SizeOf<double>() * 8));
  946. uint c = count / onecount;
  947. uint c1 = count % onecount;
  948. uint start = c * onecount;
  949. for (int i = 0; i < c; i++)
  950. {
  951. ref var tempdesc = ref Unsafe.Add(ref source, i);
  952. tempdesc /= right;
  953. }
  954. if (c1 > 0)
  955. {
  956. double* leftptr = (double*)Unsafe.AsPointer(ref left);
  957. for (int i = 0; i < c1; i++)
  958. {
  959. leftptr[start + i] /= right;
  960. }
  961. }
  962. }
  963. public void Division(ref double left, ref double right, uint count)
  964. {
  965. if (count == 0) return;
  966. ref var source = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref left);
  967. uint onecount = (uint)(512 / (Unsafe.SizeOf<double>() * 8));
  968. uint c = count / onecount;
  969. uint c1 = count % onecount;
  970. uint start = c * onecount;
  971. ref var tempright = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref right);
  972. for (int i = 0; i < c; i++)
  973. {
  974. ref var tempdesc = ref Unsafe.Add(ref source, i);
  975. tempdesc /= Unsafe.Add(ref tempright, i);
  976. }
  977. if (c1 > 0)
  978. {
  979. double* leftptr = (double*)Unsafe.AsPointer(ref left);
  980. double* rightptr = (double*)Unsafe.AsPointer(ref right);
  981. for (int i = 0; i < c1; i++)
  982. {
  983. leftptr[start + i] /= rightptr[start + i];
  984. }
  985. }
  986. }
  987. }
  988. }