将特定位置的位收集为新值

2024-01-04

我有一个大小为 N 个字符的位掩码,它是静态已知的(即可以在编译时计算,但它不是单个常量,所以我不能只是写下来),位设置为 1 表示“想要”的位。我有一个相同大小的值,该值只有在运行时才知道。我想按顺序从该值收集“想要的”位到新值的开头。为了简单起见,我们假设所需的位数

完全未优化的参考代码希望具有正确的行为:

template<int N, const char mask[N]>
unsigned gather_bits(const char* val)
{
    unsigned result   = 0;
    char*    result_p = (char*)&result;
    int      pos      = 0;
    for (int i = 0; i < N * CHAR_BIT; i++)
    {
        if (mask[i/CHAR_BIT] & (1 << (i % CHAR_BIT)))
        {
            if (val[i/CHAR_BIT] & (1 << (i % CHAR_BIT)))
            {
                if (pos < sizeof(unsigned) * CHAR_BIT)
                {
                    result_p[pos/CHAR_BIT] |= 1 << (pos % CHAR_BIT);
                } 
                else
                {
                    abort();
                }
            }
            pos += 1;
        }
    }
    return result;
}

尽管我不确定该公式是否实际上允许在编译时访问掩码的内容。但无论如何,它是可用的,也许是constexpr功能或其他东西会是一个更好的主意。我在这里寻找的不是必要的 C++ 魔法(我会弄清楚的),只是算法。

为清楚起见,使用 16 位值和虚数二进制表示法的输入/输出示例:

mask   = 0b0011011100100110
val    = 0b0101000101110011
--
wanted = 0b__01_001__1__01_ // retain only those bits which are set in the mask
result = 0b0000000001001101 // bring them to the front
                   ^ gathered bits begin here

我的问题是:

  • 执行此操作最有效的方法是什么? (是否有任何硬件说明可以提供帮助?)

  • 如果掩码和值都被限制为怎么办?unsigned,那么一个单词,而不是一个无界的字符数组?那么可以通过固定的、简短的指令序列来完成吗?


这里将pext(并行位提取)这正是您在 Intel Haswell 中想要的。我不知道该指令的性能如何,但可能比其他指令更好。此操作也称为“compress-right”或简称“compress”,Hacker's Delight 的实现是这样的:

unsigned compress(unsigned x, unsigned m) {
   unsigned mk, mp, mv, t; 
   int i; 

   x = x & m;           // Clear irrelevant bits. 
   mk = ~m << 1;        // We will count 0's to right. 

   for (i = 0; i < 5; i++) {
      mp = mk ^ (mk << 1);             // Parallel prefix. 
      mp = mp ^ (mp << 2); 
      mp = mp ^ (mp << 4); 
      mp = mp ^ (mp << 8); 
      mp = mp ^ (mp << 16); 
      mv = mp & m;                     // Bits to move. 
      m = m ^ mv | (mv >> (1 << i));   // Compress m. 
      t = x & mv; 
      x = x ^ t | (t >> (1 << i));     // Compress x. 
      mk = mk & ~mp; 
   } 
   return x; 
} 
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将特定位置的位收集为新值 的相关文章

  • ROWNUM 的 OracleType 是什么

    我试图参数化所有现有的 sql 但以下代码给了我一个问题 command CommandText String Format SELECT FROM 0 WHERE ROWNUM lt maxRecords command CommandT
  • 属性对象什么时候创建?

    由于属性实际上只是附加到程序集的元数据 这是否意味着属性对象仅根据请求创建 例如当您调用 GetCustomAttributes 时 或者它们是在创建对象时创建的 或者 前两个的组合 在由于 CLR 的属性扫描而创建对象时创建 从 CLR
  • 自动从 C# 代码进行调试过程并读取寄存器值

    我正在寻找一种方法来读取某个地址的 edx 注册表 就像这个问题中所问的那样 读取eax寄存器 https stackoverflow com questions 16490906 read eax register 虽然我的解决方案需要用
  • Func 方法参数的首选命名约定是什么?

    我承认这个问题是主观的 但我对社区的观点感兴趣 我有一个缓存类 它采用类型的缓存加载器函数Func
  • 模板类的不明确多重继承

    我有一个真实的情况 可以总结为以下示例 template lt typename ListenerType gt struct Notifier void add listener ListenerType struct TimeListe
  • C++ 求二维数组每一行的最大值

    我已经设法用这个找到我的二维数组的每一行的最小值 void findLowest int A Cm int n int m int min A 0 0 for int i 0 i lt n i for int j 0 j lt m j if
  • fgets() 和 Ctrl+D,三次才能结束?

    I don t understand why I need press Ctrl D for three times to send the EOF In addition if I press Enter then it only too
  • Cygwin 下使用 CMake 编译库

    我一直在尝试使用 CMake 来编译 TinyXML 作为一种迷你项目 尝试学习 CMake 作为补充 我试图将其编译成动态库并自行安装 以便它可以工作 到目前为止 我已经设法编译和安装它 但它编译成 dll 和 dll a 让它工作的唯一
  • 如何在我的应用程序中使用 Windows Key

    Like Windows Key E Opens a new Explorer Window And Windows Key R Displays the Run command 如何在应用程序的 KeyDown 事件中使用 Windows
  • C# 中值类型和引用类型有什么区别? [复制]

    这个问题在这里已经有答案了 我知道一些差异 值类型存储在堆栈上 而引用类型存储在托管堆上 值类型变量直接包含它们的值 而引用变量仅包含对托管堆上创建的对象位置的引用 我错过了任何其他区别吗 如果是的话 它们是什么 请阅读 堆栈是一个实现细节
  • C# 中可空类型是什么?

    当我们必须使用nullable输入 C net 任何人都可以举例说明 可空类型 何时使用可空类型 https web archive org web http broadcast oreilly com 2010 11 understand
  • 使用 C# 在 WinRT 中获取可用磁盘空间

    DllImport kernel32 dll SetLastError true static extern bool GetDiskFreeSpaceEx string lpDirectoryName out ulong lpFreeBy
  • 写入和读取文本文件 - C# Windows 通用平台应用程序 Windows 10

    有用 但在显示任何内容之前 您必须在文本框中输入内容 我想那是因为我使用了 TextChanged 事件处理程序 如果我希望它在没有用户交互的情况下显示文本文件的内容 我应该使用哪个事件处理程序 因此 我想在按下按钮时将一些数据写入 C W
  • 在 ASP.Net Core 2.0 中导出到 Excel

    我曾经使用下面的代码在 ASP NET MVC 中将数据导出到 Excel Response AppendHeader content disposition attachment filename ExportedHtml xls Res
  • 初始化变量的不同方式

    在 C 中初始化变量有多种方法 int z 3 与 int 相同z 3 Is int z z 3 same as int z z 3 您可以使用 int z z 3 Or just int z 3 Or int z 3 Or int z i
  • C 中的位移位

    如果与有符号整数对应的位模式右移 则 1 vacant bit will be filled by the sign bit 2 vacant bit will be filled by 0 3 The outcome is impleme
  • 如何在内存中存储分子?

    我想将分子存储在内存中 这些可以是简单的分子 Methane CH4 C H bond length 108 7 pm H H angle 109 degrees But also more complex molecules like p
  • ListDictionary 类是否有通用替代方案?

    我正在查看一些示例代码 其中他们使用了ListDictionary对象来存储少量数据 大约 5 10 个对象左右 但这个数字可能会随着时间的推移而改变 我使用此类的唯一问题是 与我所做的其他所有事情不同 它不是通用的 这意味着 如果我在这里
  • GDK3/GTK3窗口更新的精确定时

    我有一个使用 GTK 用 C 语言编写的应用程序 尽管该语言对于这个问题可能并不重要 这个应用程序有全屏gtk window与单个gtk drawing area 对于绘图区域 我已经通过注册了一个刻度回调gtk widget add ti
  • 方法参数内的变量赋值

    我刚刚发现 通过发现错误 你可以这样做 string s 3 int i int TryParse s hello out i returns false 使用赋值的返回值是否合法 Obviously i is but is this th

随机推荐

  • Android Studio 没有显示任何错误?

    我不知道发生了什么事但是当我复制粘贴代码或写一些东西时 没有显示错误 See the picture below in which i copied a code but no imports yet But Android studio
  • python:使用多处理共享巨大的字典

    我正在使用多重处理处理存储在字典中的大量数据 基本上我所做的就是加载一些存储在字典中的签名 从中构建一个共享的 dict 对象 获取 Manager dict 返回的 代理 对象 并将此代理作为参数传递给具有在多处理中执行 只是为了澄清 s
  • JAX-RS MessageBodyReader

    我正在从提供者那里了解 MessageBodyReader 方法的工作原理 我看到该方法返回一个对象 但我不确定如何从服务访问该对象 我可以获得有关如何从 reader 类返回对象的解释吗 这将帮助我为所有 DTO 应用读取规则 提前致谢
  • 头部与身体之间的间距

    我有一个简单的 html 表 如下所示 table thead tr th Column 1 th th Column 2 th tr thead tbody tr class odd first row td Value 1 td td
  • 如何在不使用 super() 的情况下访问父类的重写方法?

    如下所示 我尝试将子类的对象强制转换为其父类的对象 进展顺利 但是 当我尝试访问父类的重写方法时 它不会发生 相反 调用子类中的重写方法 我知道我可以使用 super 关键字来做到这一点 但我只是想知道为什么这不能通过强制转换来完成 这是父
  • IE10 中的 Angular UI Bootstrap 进度条

    我正在使用 Angular UI Bootstrap 来显示进度条 在 IE 中我的网站出现问题后 我用 IE 查看了Angular UI Bootstrap 网站 http angular ui github io bootstrap 并
  • 如何处理对话框中的后退按钮?

    我正在开发一个应用程序 当按下按钮时 它会打开一个带有 确定 和 取消 按钮的对话框 效果很好 当用户按下后退按钮时 我按如下方式处理 public boolean onKeyDown int keyCode KeyEvent event
  • 使用 AVPlayer 返回“非多路径连接”错误

    我正在使用 AVKit 播放 YouTube URL 我在按钮操作中有这段代码 IBAction func trailerButtonAction sender Any guard let youtubeUrl youtubeURL els
  • 具有访问权限的 Excel VBA 不会在此代码上关闭

    你好 我几分钟前刚刚发帖 有人回答了我关于 Excel 未关闭的问题 我正在使用访问权限打开工作表并添加表格 Excel 不会关闭 这会导致问题 因为当我在另一个函数中再次获取 Excel 对象时 我正在使用的工作表将无法打开 也不会对其进
  • Javascript 和 CSS 之间保持 DRY

    假设您有一个可以通过按钮切换打开和关闭的菜单 我的标准方法是为关闭的菜单编写 CSS 并编写指定 或动画 打开菜单状态的 Javascript 最近我开始接触 Active js 一个客户端 MVC 框架 它为视图类提供了用于制作 DOM
  • 将 JSON 解组为映射/字符串列表

    我想将 Json 解组到映射 字符串列表 例如 Map gt 这是我的输入 pointsOfSale pointOfSale href pointsOfSale UUID 0abc2aca 7930 4c9e 9f38 8af3d0692e
  • Spark Window函数最后一个非空值

    我们有一个用户事件的时间序列数据库 如下所示 timestamp user id event ticke type error type 2019 06 06 14 33 31 user a choose ticket ticke b NU
  • 在 MySQL 中存储 0.00001

    我有一个赚取网站 我希望用户每次点击赚取 0 00001 我知道它低于 1p 我可以使用什么类型的色谱柱 我努力了int and float但两者都不起作用 Use DECIMAL http dev mysql com doc refman
  • 将勾号 (✔) 添加到 string.xml

    我在字符串消息上添加勾号 strings xml 但是当我在移动设备上显示它时 我得到一个 框 而不是刻度线 我已直接将符号粘贴到我的字符串消息上 我们有什么办法可以处理吗 我们需要使用 unicode 值吗 添加unicode符号 u27
  • 如何使用 Perl 进行批量搜索和替换?

    我有以下脚本 它接受输入文件 输出文件和 将输入文件中的字符串替换为其他字符串并写出 输出文件 我想更改脚本以遍历文件目录 即 脚本不应提示输入和输出文件 而应采用 作为参数的目录路径 例如 C temp allFilesTobeRepla
  • Angular 8 通用服务器端渲染

    我正在关注这个教程https blog angular university io angular universal https blog angular university io angular universal 但我无法执行第一个
  • 微服务:工作者角色、API 或两者兼而有之?

    我见过微服务的混合示例 它们实现为工作角色处理队列中的请求和 或 API REST 支持异步场景 可以利用队列 通过简单的哑队列侦听器将请求转发到微服务 REST API 而同步场景将直接调用 REST API 我认为微服务这个术语的定义很
  • Vuejs 子组件中的 Prop 值无法绑定到元素属性

    我正在使用 Vuetify 在 Vuejs 中开发一个管理应用程序 并且表单中有三个字段供用户选择十六进制颜色值 为了让用户更容易 我实现了一个基于的颜色选择器这个代码笔 https codepen io Brownsugar pen Na
  • JQuery 通过 IFrame 进行可拖动和可调整大小(解决方案)

    我最近在使用 JQuery Draggable 和 Resizing 插件时遇到了一些麻烦 在寻找解决方案时 我在许多不同的地方发现了一些非常零碎的代码 最后归档到一个干净的解决方案 该解决方案似乎对我来说几乎完美 我想我会与其他人分享我的
  • 将特定位置的位收集为新值

    我有一个大小为 N 个字符的位掩码 它是静态已知的 即可以在编译时计算 但它不是单个常量 所以我不能只是写下来 位设置为 1 表示 想要 的位 我有一个相同大小的值 该值只有在运行时才知道 我想按顺序从该值收集 想要的 位到新值的开头 为了