MATLAB C++语言编写MEX函数示例:求解本源根

作为一种提升运行效率的手段,MATLAB的MEX函数最初支持C语言编写,从2018a才开始支持基于C++11的“现代”C++编写MEX,并实现更多现代特性(尤其是程序安全性方面)。目前,MATLAB官方已不推荐继续用传统C语言编写新的MEX函数:C Matrix API - MATLAB & Simulink - MathWorks 中国。我这里就展示一个搜索质数本源根的程序,详细说明如何把C++代码嵌入MEX函数中。

首先说明什么是本源根:本源根是离散数学上的一个概念,考虑对一个质数 p p p,若正整数 a a a的各次幂除以 p p p的余数正好可以产生 1 1 1 p − 1 p-1 p1的所有整数,即 a mod  p a \text{ mod } p a mod p a 2 mod  p a^2 \text{ mod } p a2 mod p、…、 a p − 1 mod  p a^{p-1} \text{ mod } p ap1 mod p各不相同,那么 a a a就是 p p p的一个本源根。本源根在密码学上非常有用,而且显而易见,对于大质数,搜索出全部本源根是个需要穷举的过程,这种穷举就非常适合通过C/C++编程来优化。

首先给出代码:

#include "mex.hpp"
#include "mexAdapter.hpp"using namespace matlab::data;
using matlab::mex::ArgumentList;class MexFunction : public matlab::mex::Function {
public:void operator()(ArgumentList outputs, ArgumentList inputs) {std::shared_ptr<matlab::engine::MATLABEngine> matlabPtr = getEngine();ArrayFactory factory;// Validate argumentscheckArguments(outputs, inputs);TypedArray<double> inputArray = std::move(inputs[0]);int num =(int)inputArray[0];if (num <= 2){matlabPtr->feval(u"error", 0, std::vector<Array>({ factory.createScalar("Input must be an integer larger than 2") }));}// 算法实现int i, j, cur_num;int search_list[num];bool isPriRoot;std::vector<int> vec_priroots;for (i=2; i<num-1; i++){isPriRoot = true;for (j=0; j<num; j++) search_list[j] = 0;cur_num = i;for (j=0; j<num - 1; j++){search_list[cur_num]++;if (search_list[cur_num] >= 2) {isPriRoot = false;break;}cur_num = (cur_num * i) % num;}if (isPriRoot) vec_priroots.push_back(i);}// Assign outputsTypedArray<double> pri_root_Array = factory.createArray<double>({vec_priroots.size(),1});for (i=0; i<vec_priroots.size(); i++){pri_root_Array[i] = vec_priroots[i];}outputs[0] = pri_root_Array;}void checkArguments(ArgumentList outputs, ArgumentList inputs) {std::shared_ptr<matlab::engine::MATLABEngine> matlabPtr = getEngine();ArrayFactory factory;if (inputs[0].getType() != ArrayType::DOUBLE ||inputs[0].getType() == ArrayType::COMPLEX_DOUBLE ||inputs[0].getNumberOfElements() != 1){matlabPtr->feval(u"error", 0, std::vector<Array>({ factory.createScalar("Input must be an integer larger than 2") }));}if (outputs.size() > 1) {matlabPtr->feval(u"error", 0, std::vector<Array>({ factory.createScalar("Only one output is returned") }));}}
};

从头看起,MEX C++严格来说不是在编写函数, 而是在编写一个名为MexFunction的类,继承自matlab::mex::Function,然后重载这个类的括号运算符operator()

void operator()(ArgumentList outputs, ArgumentList inputs)

与C语言的MEX接口不同,这里通过两个matlab::mex::ArgumentList容器,分别传入函数的输入inputs和输出outputs,注意,它们都是引用的容器,我们很快就能看到这一点。它们传入的数据类型为TypedArray<T>,所以,在检验输入数据符合算法要求后(checkArguments(outputs, inputs);),就用std::move接收输入数据的引用,然后将第一个数据取出,就是我们算法的输入,即待求本源根的质数 p p p

TypedArray<double> inputArray = std::move(inputs[0]);
int num =(int)inputArray[0];

这里需要说明,如果输入参数不止一个,可以用C++11的迭代器逐个访问类型为TypedArray<double>的输入数据中的参数,如以下官方示例:

TypedArray<double> doubleArray = std::move(inputs[0]);
for (auto& elem : doubleArray) {// do something with elem, the type of elem is double
}

再之后的算法实现就是搜索每一个小于 p p p的整数的各次幂余数是否重复,这个过程很简单,我也就用C语言实现,不多赘述。

代码声明了两个变量:

std::shared_ptr<matlab::engine::MATLABEngine> matlabPtr = getEngine();
ArrayFactory factory;

其中matlabPtr 主要的作用是通过feval方法调用MATLAB的函数,在本段代码中只用于输出错误信息;matlab::data::ArrayFactory类可以通过模板产生类型为TypedArray<T>的数据,故我们在最后调用该类组装输出数据:

TypedArray<double> pri_root_Array = factory.createArray<double>({vec_priroots.size(),1});
for (i=0; i<vec_priroots.size(); i++){pri_root_Array[i] = vec_priroots[i];
}

最后,通过

outputs[0] = pri_root_Array;

将组装的数据交给输出容器的第一个数,大功告成。可以看到,MATLAB通过引用的容器向MEX函数(对象)传入传出数据,我们在编写c++代码的时候,只要能从ArgumentList inputs取出输入数据,再把输出结果放进ArgumentList outputs,其他的实现和我们平时编写C++代码没有任何区别。特别值得说明的是,各种C++11的标准库容器(比如std::vector)都可以在MEX函数中使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/51836.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【qt小系统】传感器云平台3D散点图(附源码)

摘要&#xff1a;本文主要使用QT5&#xff0c;实现了一个传感器云平台的小示例&#xff0c;模拟的是各类传感器的添加&#xff0c;例如&#xff1a;热成像传感器、温度传感器、超声波传感器&#xff0c;模拟添加完成后&#xff0c;会自动将此传感器的三维坐标增加到3D散点图上&…

Vmware安装openstack

安装虚拟机 创建完成后&#xff0c;点击开启虚拟机 稍等执行成功后 上传压缩包到指定目录。将yoga_patch.tar.gz包上传至/root目录下&#xff0c;将stack3_without_data.tar.gz包使用WinSCP上传至/opt目录下 vim run_yoga.sh #/bin/bash cd /root sudo apt-get update tar -xzv…

添加好友

目录 添加好友的思路&#xff1a; 1.假设A添加B a.如果B在线 b.如果B不在线 添加好友的思路&#xff1a; 1.假设A添加B A给服务端发送要添加B的消息&#xff0c;服务端接受后&#xff0c;先把A添加B的信息存入数据库&#xff0c;再去个人信息表查看B是否在线 a.如果B在线…

「问题解决」jdk高版本导致请求返回对象转换报错

报错&#xff1a;Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected native java.lang.Object java.lang.Object.clone() throws java.lang.CloneNotSupportedException accessible: module java.base does not “opens java.lang” to unn…

UnityShaderUI编辑器扩展

前言&#xff1a; 当我们在制作通用Shader的时候&#xff0c;避免不了许多参数混杂在一起&#xff0c;尽管在材质面板已经使用过Header标签来区分&#xff0c;但是较长的Shader参数就会导致冗余&#xff0c;功能块不够简约明了&#xff0c;如图&#xff1a; 对于Shader制作者来…

FPGA开发——蜂鸣器的控制

一、概述 在项目开发的过程当中&#xff0c;我会通常会需要一个东西就行报警显示&#xff0c;有使用语音报警&#xff0c;信息报警等注入此类的方式&#xff0c;但最为简单使用的还是蜂鸣器的使用&#xff0c;蜂鸣器控制简单&#xff0c;成本低&#xff0c;是最为常用的模块之…

测试面试宝典(三十七)—— 接口测试中的加密参数如何处理?

1&#xff09;先了解接口使用的加密方式(md5、rsa...) 2&#xff09;检查接口测试工具是否支持这种加密方式&#xff0c;如果支持的话&#xff0c;直接使用对应功能就行了(比如Jmeter支持md5)&#xff1b;如果加密方式是公司内部特有的算法&#xff0c;可以在接口测试工具中调…

柯尔莫哥洛夫-阿诺德网络

柯尔莫哥洛夫-阿诺德网络&#xff08;Kolmogorov-Arnold Network&#xff0c;简称KAN&#xff09;是一个理论框架&#xff0c;主要用于描述高维函数如何通过一组低维函数的组合来近似表示。这个理论的基础源自安德烈柯尔莫哥洛夫和弗拉基米尔阿诺德在函数逼近理论中的工作&…

NSSRound#4 Team

[NSSRound#4 SWPU]1zweb 考察&#xff1a;phar的反序列化 1.打开环境&#xff0c;审计代码 1.非预期解 直接用file伪协议读取flag,或直接读取flag file:///flag /flag 2.正常解法 用读取文件读取index.php,upload.php的源码 index.php: <?php class LoveNss{publi…

3. Docker的数据管理与持久化

在Docker容器化应用中&#xff0c;数据的持久化和管理是一个关键问题。容器的生命周期短暂&#xff0c;容器的停止和删除会导致数据丢失。因此&#xff0c;了解Docker的数据卷&#xff08;Volumes&#xff09;和挂载&#xff08;Mounts&#xff09;的管理方式&#xff0c;对保障…

环境搭建-Docker搭建ClickHouse

Docker搭建ClickHouse 一、前言二、ClickHouse安装2.1 拉取镜像运行ClickHouse服务 三、测试安装3.1 进入clickhouse容器3.2 命令补充说明 四、测试连接五、设置CK的用户名密码 一、前言 本文使用的Docker使用Windows搭建&#xff0c;Linux版本的搭建方式一样。 Windows系统搭…

Data Race: 并发编程中的数据竞争问题

Data Race: 并发编程中的数据竞争问题 &#x1f50d; &#x1f680; Data Race: 并发编程中的数据竞争问题 &#x1f50d;摘要引言正文内容一、什么是数据竞争&#xff1f; &#x1f914;1.1 数据竞争的定义1.2 数据竞争的特征 二、数据竞争的原因和影响 &#x1f6a8;2.1 原因…

Redis学习笔记——第18章 发布与订阅

第18章 发布与订阅 18.1 频道的订阅与退订 订阅关系保存在字典中&#xff0c;Key为频道&#xff0c;value为订阅该频道的客户端链表 18.2 模式的订阅与退订 可以使用通配符&#xff0c;如果订阅了news.*类型的频道&#xff0c;则会将news.*保存为一个Key&#xff0c;value为…

SpringBoot2整合Kafka

引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency><groupId>org.springframework.kafka</groupId><artifactId>s…

小主机SSD固态硬盘选购攻略,希捷酷鱼 530 SSD固态硬盘表现优秀【附系统无损迁移教程】

小主机SSD固态硬盘选购攻略&#xff0c;希捷酷鱼 530 SSD固态硬盘表现优秀【附系统无损迁移教程】 哈喽小伙伴们好&#xff0c;我是Stark-C~ 这几年随着以零刻为首的小主机市场的兴起&#xff0c;小主机相关的配置周边需求也是越来越大&#xff0c;就比如说SSD固态硬盘就是其…

《Windows API每日一练》22.3 SHE异常

本节我们将讲述单线程到多线程的演进过程&#xff0c;以及进程与线程的区别。 本节必须掌握的知识点&#xff1a; SHE异常 第170练&#xff1a;SEH异常处理程序 第171练&#xff1a;setjmp和longjmp进行异常捕获与处理 22.3.1 SHE异常 在C语言中&#xff0c;Windows平台提供…

定制数据流:在Mojo模型中打造个性化数据预处理

定制数据流&#xff1a;在Mojo模型中打造个性化数据预处理 数据预处理是机器学习工作流程中的关键步骤&#xff0c;它直接影响到模型的性能和训练效率。Mojo模型&#xff0c;作为一个先进的机器学习框架&#xff0c;提供了强大的扩展性来支持自定义数据预处理。本文将深入探讨…

代码随想录算法训练营Day54|| 图论part04

图论部分就先不手写代码了。能理解就很花时间了&#xff0c;先看懂逻辑和代码&#xff0c;关键基础部分写写吧。 卡玛网110字符串接龙&#xff1a;相当于求无向图的最短路径&#xff0c;广搜最合适&#xff0c;因为广搜第一次找到路径一定最短。 广搜就要利用队列&#xff0c;代…

JavaScript while 循环

JavaScript while 循环 JavaScript 中的 while 循环是一种基本的循环控制结构&#xff0c;它重复执行一段代码&#xff0c;直到指定的条件不再满足为止。这种循环结构在处理不确定次数的循环时非常有用&#xff0c;尤其是当循环的次数依赖于某些运行时条件时。 基本语法 whi…