SIMDFxpConverter.cs 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. using FxpConvert.Common;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Numerics;
  6. using System.Runtime.CompilerServices;
  7. using System.Runtime.Intrinsics;
  8. using System.Text;
  9. using System.Threading.Tasks;
  10. namespace SIMDFxpConvert
  11. {
  12. public unsafe sealed class SIMDFxpConverter : IFxpConvert
  13. {
  14. public bool IsSupport => true;
  15. public void DoubleConvertToDxp(ref double value, NiFpga_FxpTypeInfo dxpinfo, ref ulong fxp, uint count)
  16. {
  17. if (count == 0) return;
  18. double pow = (1ul << (dxpinfo.wordLength - dxpinfo.integerWordLength));
  19. uint onecount = (uint)(512 / (Unsafe.SizeOf<double>() * 8));
  20. uint c = count / onecount;
  21. ref var source = ref Unsafe.As<double, System.Runtime.Intrinsics.Vector512<double>>(ref value);
  22. Vector512<double> max = Vector512<double>.One * dxpinfo.Max;
  23. Vector512<double> min = Vector512<double>.One * dxpinfo.Min;
  24. ulong* fxpptr = (ulong*)Unsafe.AsPointer(ref fxp);
  25. for (int i = 0; i < c; i++)
  26. {
  27. var temp = Unsafe.Add(ref source, i);
  28. temp = Vector512.Max(min, temp);
  29. temp = Vector512.Min(max, temp);
  30. temp *= pow;
  31. if (dxpinfo.isSigned)
  32. {
  33. for (int j = 0; j < onecount; j++)
  34. {
  35. fxpptr[i * onecount + j] = dxpinfo.wordLength > 32 ? (((ulong)(long)temp[j]) << (64 - dxpinfo.wordLength)) : ((ulong)(long)temp[j]);
  36. }
  37. }
  38. else
  39. {
  40. for (int j = 0; j < onecount; j++)
  41. {
  42. fxpptr[i * onecount + j] = dxpinfo.wordLength > 32 ? (((ulong)temp[j]) << (64 - dxpinfo.wordLength)) : ((ulong)temp[j]);
  43. }
  44. }
  45. }
  46. uint c1 = count % onecount;
  47. if (c1 != 0)
  48. {
  49. uint start = c * onecount;
  50. for (uint i = 0; i < c1; i++)
  51. {
  52. double temp = Math.Clamp(Unsafe.Add(ref value, start + i),dxpinfo.Min,dxpinfo.Max);
  53. if (dxpinfo.isSigned)
  54. {
  55. ref long templ = ref Unsafe.As<ulong, long>(ref Unsafe.Add(ref fxp, start + i));
  56. templ = dxpinfo.wordLength > 32 ? (((long)(temp * pow)) << (64 - dxpinfo.wordLength)) : ((long)(temp * pow));
  57. }
  58. else
  59. {
  60. ref ulong tempu = ref Unsafe.Add(ref fxp, start + i);
  61. tempu = dxpinfo.wordLength > 32 ? (((ulong)(temp * pow)) << (64 - dxpinfo.wordLength)) : ((ulong)(temp * pow));
  62. }
  63. }
  64. }
  65. }
  66. public void FloatConvertToDxp(ref float value, NiFpga_FxpTypeInfo dxpinfo, ref ulong fxp, uint count)
  67. {
  68. if (count == 0) return;
  69. float pow = (1ul << (dxpinfo.wordLength - dxpinfo.integerWordLength));
  70. uint onecount = (uint)(512 / (Unsafe.SizeOf<float>() * 8));
  71. uint c = count / onecount;
  72. ref var source = ref Unsafe.As<float, System.Runtime.Intrinsics.Vector512<float>>(ref value);
  73. ulong* fxpptr = (ulong*)Unsafe.AsPointer(ref fxp);
  74. Vector512<float> max = Vector512<float>.One * (float)dxpinfo.Max;
  75. Vector512<float> min = Vector512<float>.One * (float)dxpinfo.Min;
  76. for (int i = 0; i < c; i++)
  77. {
  78. var temp = Unsafe.Add(ref source, i);
  79. temp = Vector512.Max(min, temp);
  80. temp = Vector512.Min(max, temp);
  81. temp *= pow;
  82. if (dxpinfo.isSigned)
  83. {
  84. for (int j = 0; j < onecount; j++)
  85. {
  86. fxpptr[i * onecount + j] = dxpinfo.wordLength>32?(((ulong)(long)temp[j])<<(64-dxpinfo.wordLength)): ((ulong)(long)temp[j]) ;
  87. }
  88. }
  89. else
  90. {
  91. for (int j = 0; j < onecount; j++)
  92. {
  93. fxpptr[i * onecount + j] =dxpinfo.wordLength>32?(((ulong)temp[j])<<(64-dxpinfo.wordLength)) : ((ulong)temp[j]) ;
  94. }
  95. }
  96. }
  97. uint c1 = count % onecount;
  98. if (c1 != 0)
  99. {
  100. uint start = c * onecount;
  101. for (uint i = 0; i < c1; i++)
  102. {
  103. float temp =Math.Clamp(Unsafe.Add(ref value, start + i),(float)dxpinfo.Min,(float)dxpinfo.Max);
  104. if (dxpinfo.isSigned)
  105. {
  106. ref long templ = ref Unsafe.As<ulong, long>(ref Unsafe.Add(ref fxp, start + i));
  107. templ = dxpinfo.wordLength>32?(((long)(temp * pow))<<(64-dxpinfo.wordLength)) : ((long)(temp * pow)) ;
  108. }
  109. else
  110. {
  111. ref ulong tempu = ref Unsafe.Add(ref fxp, start + i);
  112. tempu = dxpinfo.wordLength > 32 ? (((ulong)(temp * pow)) << (64 - dxpinfo.wordLength)) : ((ulong)(temp * pow)) ;
  113. }
  114. }
  115. }
  116. }
  117. public void FxpConvertToDouble(ref ulong fxp, NiFpga_FxpTypeInfo dxpinfo, ref double value, uint count)
  118. {
  119. if (count == 0) return;
  120. double delta = Math.Pow(2, dxpinfo.integerWordLength - dxpinfo.wordLength);
  121. ulong mask = dxpinfo.wordLength == 64 ? ulong.MaxValue : ((1ul << dxpinfo.wordLength) - 1);
  122. if (dxpinfo.isSigned)
  123. {
  124. ulong signedmask = 1ul << (dxpinfo.wordLength - 1);
  125. for (int i = 0; i < count; i++)
  126. {
  127. ref double resultref = ref Unsafe.Add(ref value, i);
  128. ref ulong tempfxpref = ref Unsafe.Add(ref fxp, i);
  129. ulong tempdata = 0;
  130. if (dxpinfo.wordLength > 32)
  131. {
  132. tempdata = (tempfxpref >> (64 - dxpinfo.wordLength)) & mask;
  133. }
  134. else tempdata = tempfxpref & mask;
  135. if ((tempdata & signedmask) != 0)
  136. {
  137. long signeddata = (long)(tempdata ^ mask);
  138. signeddata = (signeddata + 1) * -1;
  139. resultref = signeddata * delta;
  140. }
  141. else resultref = delta * tempdata;
  142. }
  143. }
  144. else
  145. {
  146. for (int i = 0; i < count; i++)
  147. {
  148. ref double resultref = ref Unsafe.Add(ref value, i);
  149. ref ulong tempfxpref = ref Unsafe.Add(ref fxp, i);
  150. ulong tempdata = (dxpinfo.wordLength > 32 ? (tempfxpref >> (64 - dxpinfo.wordLength)) : tempfxpref) & mask;
  151. resultref = delta * tempdata;
  152. }
  153. }
  154. }
  155. public void FxpConvertToFloat(ref ulong fxp, NiFpga_FxpTypeInfo dxpinfo, ref float value, uint count)
  156. {
  157. if (count == 0) return;
  158. float delta = MathF.Pow(2, dxpinfo.integerWordLength - dxpinfo.wordLength);
  159. ulong mask = dxpinfo.wordLength == 64 ? ulong.MaxValue : ((1ul << dxpinfo.wordLength) - 1);
  160. if (dxpinfo.isSigned)
  161. {
  162. ulong signedmask = 1ul << (dxpinfo.wordLength - 1);
  163. for (int i = 0; i < count; i++)
  164. {
  165. ref float resultref = ref Unsafe.Add(ref value, i);
  166. ref ulong tempfxpref = ref Unsafe.Add(ref fxp, i);
  167. ulong tempdata = 0;
  168. if (dxpinfo.wordLength>32)
  169. {
  170. tempdata = (tempfxpref>>(64-dxpinfo.wordLength)) & mask;
  171. }
  172. else tempdata = tempfxpref & mask;
  173. if ((tempdata & signedmask) != 0)
  174. {
  175. long signeddata = (long)(tempdata ^ mask);
  176. signeddata = (signeddata + 1) * -1;
  177. resultref = signeddata * delta;
  178. }
  179. else resultref = delta * tempdata;
  180. }
  181. }
  182. else
  183. {
  184. for (int i = 0; i < count; i++)
  185. {
  186. ref float resultref = ref Unsafe.Add(ref value, i);
  187. ref ulong tempfxpref = ref Unsafe.Add(ref fxp, i);
  188. ulong tempdata = (dxpinfo.wordLength>32?(tempfxpref>>(64-dxpinfo.wordLength)): tempfxpref) & mask;
  189. resultref = delta * tempdata;
  190. }
  191. }
  192. }
  193. }
  194. }