function rsa_key_generate (
$p,
$q
){
if ($p == $q) {
return false;
}
$n = (string)gmp_mul($p, $q); //mul-> 乗算
$n_ gmp_mul(gmp_sub($p, '1'), gmp_sub($q, '1')); // 減算(p-1)(q-1)
$rand = gmp_random_range(0, gmp_sub($n_, '1')); // random_range -> ランダムな数 0 ~ (n')
while(true) {
$coprime_numbers = (string)gmp_gcd($rand, $_n); // gcd -> 最大公約数を返す
// 最大公約数が1なら互いに素な数
if($coprime_numbers === '1') {
$e = (string)$rand;
break;
}
// 非互に素な数減算し再計算
$rand = gmp_sub($rand, '1');
}
$d = (string)gmp_invert($e, $n_); // n'を法としたeの逆数
// 秘密鍵:d 公開鍵:n, e
return [$d, $n, $e];
}
function rsa_encryption (
$a, //暗号化対象の平文
$n, //公開鍵1
$e //公開鍵2
){
$b = [];
foreach ($a as $value) {
// aの一つを2乗
$a_e = gmp_pow($value, $e);
// e乗した値をnで割った余りを格納
$b[] = (string)gmp_div_r($a_e, $n);
}
return $b;
}
function composite (
$b, // 暗号文
$d, // 秘密鍵
$n // 公開鍵
){
$a = [];
foreach ($b as $value) {
// bの一つをd乗する
$b_d = gmp_pow($value, $d); //
// d乗した値をnで割った余りを格納
$a[] = (string)gmp_div_r($b_d, $n);
}
return $a;
}
return $b;
}
// 平文を数値配列に変換
function convert_string_to_integer(
$str
){
// 初期配列
$ord_array = [];
for ($i = 0; $i < mb_strlen($str); $i ++) {
$value = mb_substr($str, $i, 1);
$ord_array[] = mb_ord($value);
}
return $ord_array;
}
// 数値配列を文字列に変換
function convert_integer_to_string (
$int_array
) {
// 初期文字列
$chr = '';
// 配列の数値を全て文字列に変換
foreach ($int_array as $value){
// 数値を文字列に
$chr .= mb_char($value);
}
return $chr;
}
【ChatGPT】PHPでリクエストを送ってみる
$input_json = file_get_contents('php://input');
$post = json_decode( $input_json, true );
$req_question = $post['prompt'];
$result = array();
// APIキー
$apiKey = '***';
//openAI APIエンドポイント
$endpoint = 'https://api.openai.com/v1/chat/completions';
$headers = array(
'Content-Type: application/json',
'Authorization: Bearer ' . $apiKey
);
// リクエストのペイロード
$data = array(
'model' => 'gpt-3.5-turbo',
'messages' => [
[
"role" => "system",
"content" => "新宿はどんな所ですか?"
],
// [
// "role" => "user",
// "content" => $req_question
// ]
]
);
// cURLリクエストを初期化
$ch = curl_init();
// cURLオプションを設定
curl_setopt($ch, CURLOPT_URL, $endpoint);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// APIにリクエストを送信
$response = curl_exec($ch);
// cURLリクエストを閉じる
curl_close($ch);
// 応答を解析
$result = json_decode($response, true);
// 生成されたテキストを取得
$text = $result['choices'][0]['message']['content'];
var_dump($result);
レスポンスは返ってくるが、時間がかかりますね。
$ php index.php
array(6) {
[“id”]=>
string(38) “chatcmpl-7jHpzpu5LnjqM2dbxoBQrx0Nrp0DQ”
[“object”]=>
string(15) “chat.completion”
[“created”]=>
int(1691027683)
[“model”]=>
string(18) “gpt-3.5-turbo-0613”
[“choices”]=>
array(1) {
[0]=>
array(3) {
[“index”]=>
int(0)
[“message”]=>
array(2) {
[“role”]=>
string(9) “assistant”
[“content”]=>
string(1323) “新宿は東京都内で最も繁華なエリアの一つです。駅周辺には高層ビルが立ち並び、多くの人が行き交います。新宿駅は日本でも最も利用者が多い駅の一つで、多くの鉄道路線が交差し、バスターミナルもあるため、アクセスが非常に便利です。
新宿には大型商業施設やデパート、ショッピングモールが集まっており、様々なショップやレストランがあります。また、歌舞伎町という繁華街もあり、夜になると多くの人々で賑わいます。歓楽街として知られており、多くの居酒屋、バー、クラブがあります。
また、新宿は文化施設も充実しており、新宿御苑や東京都庁舎、新宿中央公園などの公共の場所で自然に触れることもできます。さらに、新宿の西側には高層ビルが連なる都市の景色が楽しめる新宿西口地区もあります。
新宿はまた、交通の要所としても知られており、多くの人々が通勤や買い物などで訪れます。そのため、駅周辺は常に混雑していることが多いですが、多くの施設やイベントが盛り上がっているため、観光客や地元の人々にとっても魅力的な場所です。”
}
[“finish_reason”]=>
string(4) “stop”
}
}
[“usage”]=>
array(3) {
[“prompt_tokens”]=>
int(18)
[“completion_tokens”]=>
int(490)
[“total_tokens”]=>
int(508)
}
}
ChatGPTを動かしてみる
$ pip install openapi
import openapi
openai.api_key = '***'
response = openai.ChatCompletion.create(
mmodel="gtp-3.5-turbo",
messages=[
{"role": "system", "content": "You are an assistant that knows a lot about animals."},
{"role": "user", "content": "Tell me about elephants."},
]
)
print(response['choices'][0]['message']['content'])
うーむ、なんか上手くいかんな
Rust 実行速度
use std::os::raw::c_int;
#[link(name="mylib", kind="static")]
extern "C" {
fn twice(n: c_int) -> c_int;
}
fn main() {
let n = 12;
unsafe {
println!("{}の2倍は{}", n, twice(n));
}
}
use std::time::Instant;
fun main() {
i16func();
i64func();
}
fn i16func(){
let mut v:16 = 0;
let start = Instant::now();
for _ in 0..1000 {
for _ in 0..10000 {
v = v + 1;
}
v = v - 10000;
}
let elepse = start.elapsed();
println!("i16={:?}", v);
}
fn i64func() {
let mut v:i64 = 0;
let start = Instant::now();
for _ in 0..1000 {
for _ in 0..10000 {
v = v + 1;
}
v = v- 10000;
}
let elepse = start.elapsed();
println!("i64={:?}", v);
println!("{}ミリ秒", elepse.as_millis());
}
use std::time::Instant;
fn main() {
f32func();
f64func();
}
fn f32func() {
const NDATA:usize = 10000;
let mut a:[f32; NDATA] = [0.0; NDATA];
for i in 0..NDATA {
a[i] = (NDATA - i) as f32;
}
println!("並び替えスタート");
let start = Instant::now();
for i in 0..NDATA{
for j in 0..NDATA {
if a[i] < a[j] {
let tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
}
}
let elepse = start.elapsed();
println!("並べ替え終了");
println!("{}ミリ秒", elepse.as_millis());
}
fn f64func() {
const NDATA:usize = 10000;
let mut a:[f64; NDATA] = [0.0; NDATA];
for i in 0..NDATA {
a[i] = (NDATA - i) as f64;
}
let start = Instant::now();
for i in 0..NDATA {
for j in 0..NDATA {
if a[i] < a[j] {
let tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
}
}
let elepse = start.elapsed();
println!("並び替え終了");
println!("{}ミリ秒", elepse.as_millis());
}
Rust パニックとアサート
プログラムの実行が継続できないような重大な問題をパニックという
パニックは他の言語の例外処理に似ている
Cargo.tomlファイルのpanic=’abort’で異常終了する
let f = File::open("sample.txt");
let f = match f {
Ok(file) => file,
Err(error) => {
panic!("ファイル開けません: {:?}", error)
}
}
アサートはプログラムの途中で値が妥当であるか調べる
assert_eq!(left, right);
let f = 3.7_f64;
assert_eq!(f.floor(), 3.0);
println!("f={}", f);
### メモリ管理
メモリはランタイムが管理するので考える必要はない
Box: std::boxed::Boxを使うことでヒープにメモリを確保することができる
struct Point {
x: i32,
y: i32,
}
impl Clone for Poin {
fn clone(&self) -> Self {
Point {
x: self.x.clone(),
y: self.y.clone(),
}
}
}
fn main() {
let p1 = Point {x: 12, y:25};
let p2: Box<Point> = Box::new(Point {x: 23, y: 45});
println!("{:?}", type_of(p1.clone()));
println!("{:?}", type_of(p2.clone()));
println!("{}, {}", p1.x, p1.y);
println!("{}, {}", p2.x, p2.y);
}
fn type_of<T>(_: T) -> &'static str {
std::any::type_name::<T>()
}
use std::mem;
struct Point {
x: i32,
y: i32,
}
fn main() {
let p = Point {x: 12, y: 25};
let a = [1,2,3,4,5,6,7,8,9];
println!("pのサイズ={}", mem::size_of_val(&p));
println!("aのサイズ={}", mem::size_of_val(&a));
}
Rust ネットワーク
TCPというプロトコルを使って情報を受け渡すサーバとクライアント
サーバ側
use std::net::{TcpListener,TcpStream};
use std::thread;
use std::io::{Read,Write,Error};
fn handle_data(mut stream: TcpStream) -> Result<(), Error> {
println!("Connection from: {}", stream.peer_addr()?);
let mut buf = [0; 512];
loop {
let byte_read = stream.read(&mut buf)?;
for i in 0..byte_read {
if buf[i] > 0x60 {
buf[i] = buf[i] - 0x20;
}
}
if byte_read == 0 {return Ok(());}
stream.write(&buf[..byte_read])?;
}
}
fn main() {
let coninfo = "localhost:8000";
let listener = TcpListener::bind(coninfo).expect("バインドできません。");
for steam in listener.incoming(){
match stream {
Err(e) => {eprintln!("failed: {}", e)}
Ok(stream) => {
thread::spawn(move || {
handle_data(stream).
unwrap_or_else(|error| eprintln!("{:?}", error));
});
}
}
}
}
クライアント側
use std::net::{TcpStream};
use std::str;
use std::io::{self,BufRead,BufReader,Write};
fn main() {
let coinfo = "localhost:8000";
let mut stream = TcpStream::connect(coinfo).expect("サーバに接続できません。");
loop {
let mut input = String::new();
io::stdin().read_line(&mut input).expect("標準入力からの入力エラー");
stream.write(input.as_bytes()).expect("サーバに送れません。");
let mut reader = BufReader::new(&stream);
reader.read_until(b'¥n', &mut buffer).expect("サーバから受け取れません");
print!("{}", str::from_utf8(&buffer).expect("テキストを表示できません"));
}
}
じゃんけんサーバ
use std::net::{TcpListener, TcpStream};
use std::thread;
use std::io::{Read,Write,Error};
use rand::{thread_rng, Rng};
fn handle_data(mut stream: TcpStream) -> Result<(), Error> {
println!("Connection from: {}", stream.peer_addr()?);
let mut buf = [0; 512];
loop {
let mut userte = false;
let mut cpmsg = String::new();
let mut msg = String::from("");
let byte_read = stream.read(&mut buf)?;
if byte_read == 0 {return Ok(());}
let mut rng = thread_rng();
let x: u16 = rng.gen_range(0, 3);
match x {
0 => cpmsg.insert_str(0, "私はグー"),
1 => cpmsg.insert_str(0, "私はチョキ"),
2 => cpmsg.insert_str(0, "私はパー"),
_ => cpmsg.insert_str(0, ""),
}
let client_msg = String::from_utf8(buf.to_vec()).unwrap();
msg.insert_str(0, &cpmsg);
if client_msg.starts_with("グー") {
userte=true;
match x {
0 => msg.push_str(":あいこ¥n");
1 => msg.push_str(":あなたの勝ち¥n");
2 => msg.push_str(":あなたの負け¥n");
_ => ();
}
} else if client_msg.starts_with("チョキ"){
userte=true;
match x {
0 => msg.push_str(":あなたの負け¥n");
1 => msg.push_str(":あいこ¥n");
2 => msg.push_str(":あなたの勝ち¥n");
_ => ();
}
} else if client_msg.starts_with("パー"){
userte=true;
match x {
0 => msg.push_str(":あなたの勝ち¥n");
1 => msg.push_str(":あなたの負け¥n");
2 => msg.push_str(":あいこ¥n");
_ => ();
}
} if userte {
let bytes = msg.as_bytes();
let len = bytes.len();
stream.write(&bytes[..len])?;
} else {
stream.write(&buf[..byte_read])?;
}
stream.flush()?;
}
}
fn main() {
let coninfo = "localhost:8000";
let listener = TcpListener::bind(coninfo).expect("バインドできません。");
for stream in listenr.incoming() {
match stream {
Err (e) => {eprintln!("failed: {}", e)}
Ok(stream) => {
thread::spawn(move || {
handle_data(stream).
unwrap_or_else(|error| eprintln!("{:?}", error));
});
}
}
}
}
Rust ファイル入出力
単純なファイル入出力はstd::fsやstd::ioにある関数を使う
std::fs::read(), std::fs::read_dir(), std::fs::read_to_string(), std::fs_write()
use std::fs;
fn main() {
let result = fs::read_to_string("sample.txt");
println!("{:?}", result);
}
use std::fs;
fn main() {
match fs::read_to_string("sample.txt"){
Ok(result) => println!("{}", result),
Err(msg) => println!("エラー:{}", msg),
}
}
use std::io::BufReader;
use std::io::prelude::*;
use std::fs::File;
fn main() -> std::io::Result<()> {
let f = File::open("sample.txt")?;
let reader = BufReader::new(f);
for line in reader.lines() {
println!("{}", line?);
}
Ok(())
}
use std::io;
use std::io::prelude::*;
use std::fs::File;
fn main() -> std::io::Result<()> {
let mut f = File::open("sample.txt")?;
let mut buffer = [0; 1000];
let n = f.read(&mut buffer)?;
println!("{:?}", &buffer[..n]);
Ok(())
}
use std::fs::File;
use std::io::Write;
fn main() -> std::io::Result<()> {
let txt = "こんにちは¥nHappy Rust¥n";
let mut file = File::create("test.txt")?;
write!(file, "{}", txt)?;
file.flush()?;
Ok(())
}
use std::fs::File;
use std::io::{Write, BufWriter};
fn main() -> std::io::Result<()> {
let file = File::create("sample2.txt")?;
let mut writer = BufWrite::new(file);
let data:&str = "Hello¥nHappy Dogs";
writer.write_all(data.as_bytes())?;
writer.flush()?;
Ok(())
}
use qrcode::QrCode;
use image::Luma;
fn main() {
let code = QrCode::new(b"A0023213").unwrap();
let image = code.render::<Luma<u8>>().build();
image.save("sample.png").unwrap();
}
Rust ファイル操作
Rustのファイルシステムにアクセスするときは、std::fsモジュールにある関数を使うことができる
canonicalize(), copy(), create_dir(), create_dir_all(), hard_link(), metadata(), read_link(), remove_dir(), remove_dir_all(), remove_file(), rename(), set_permissions(), soft_link(), symlink_metadata()
pub fn copy
use std::env;
use std::fs;
fn main() -> std::io::Result<()> {
let argv: Vec<String> = env::args().collect();
let argc = argv.len();
if argc < 3 {
println!("引数を2個指定ください。");
std::process::exit(1);
}
let src = &argv[1];
let dest = &argv[2];
fs::copy(src, dest)?;
Ok(())
}
use std::fs;
fn main() -> std::io::Result<()> {
fs::create_dir("./misc/subdir")?;
Ok(())
}
use std::fs;
use std::path::PathBuf;
fn main() {
let srcdir = PathBuf::from("./src");
println!("{:?}", fs::canonicalize(&srcdir));
}
Rust 非同期実行
関数を非同期実行することができる
async/awaitは、時間のかかる処理をするときに、処理が終わるまでのスレッドを別のタスクの処理に使うことができる機能を提供する
use futures::executor::block_on;
fn wait() -> f64 {
let mut x:f64 = 0.0;
for _ in 1..10000 {
for _ in 1..10000 {
x = x * 1.001;
}
}
x
}
async fn print_dot(){
println!(".");
}
async fn print_plus(){
plusfunc().await;
}
async fn print_minus() {
wait();
println!("-");
}
async fn plusfunc(){
wait();
println!("+");
}
async fn async_main() {
let f1 = print_plus();
let f2 = print_minus();
let f3 = print_dot();
println!("Hello");
futures::join!(f1, f2, f3);
}
fn main(){
block_on(async_main());
}
Rust スレッド間通信、排他制御
並列で実行されているスレッド間で情報を受け渡す
グローバルなstatic変数を使うか、チャンネルを使う
チャンネルではメインスレッドとスレッドとの間で特定の型の値を受け渡す通信機構を提供する
let (tx, rx) = mpsc::channel();
tx.send(count).unwrap();
use std::thread;
use std::time::Duration;
use std::sync::mpsc;
fn main(){
let (tx, rx) = mpsc::channel();
let th = thread::spawn(move || {
let mut count = 0;
for _i in 1..11 {
count = count + 1;
tx.send(count).unwrap();
}
});
let mut cnt = 0;
for _i in 1..11 {
cnt = cnt + 1;
thread::sleep(Duration::from_millis(100));
}
th.join().unwrap();
let val = rx.recv().unwrap();
println!("カウンタ={}", cnt + val);
println!("プログラム終了");
}
### 排他制御
複数のスレッドが同じ変数にアクセスすることを避ける方法
std::syncにあるっミューテックスという方法を使って、他のスレッドが変数の値を変更しないようにする
let counter = Arc::new(Mutex::new(0));
use std::thread;
use std::time::Duration;
use std::sync::{Mutex, Arc};
fn main(){
let counter = Arc::new(Mutex::new(0));
let counter1 = Arc::clone(&counter);
let th1 = thread::spawn(mmove || {
for _i in 1..11 {
print("+");
let mut num = counter1.lock().unwrap();
*num += 1;
thread::sleep(Duration::from_millis(100));
}
});
let counter2 = Arc::clone(&counter);
let th2 = thread::spawn(move || {
for _i in 1..11 {
let mut num = counter2.lock().unwrap();
*num += 1;
print!("-");
thread::sleep(Duration::from_millis(100));
}
});
th1.join().unwrap();
th2.join().unwrap();
println!("\ncounter={:?}", counter);
}
アトミック
use std::thread;
use std::time::Duration;
use std::sync::atomic::{self, AtomicU32, Ordering};
static COUNTER: AtopmicU32 = AtomicU32::new(0);
fn count_up(){
COUNTER.fetch_add(1, atomic::Ordering::SeqCst);
}
fn get_count() -> u32 {
return COUNTER.load(Ordering::SeqCst);
}
fn main(){
let th1 = thread::spawn(mmove || {
for _i in 1..11 {
print("+");
count_up();
thread::sleep(Duration::from_millis(100));
}
});
let th2 = thread::spawn(move || {
for _i in 1..11 {
print!("-");
count_up();
thread::sleep(Duration::from_millis(100));
}
});
th1.join().unwrap();
th2.join().unwrap();
println!("\ncounter={}", get_count());
}