Closed usuyuki closed 9 months ago
これ返り値は来てるわけだから,printDoubleで型キャスト事故ってる気がする.
いや,
Serial.print("cos(0.0)");
Serial.println(cos(0.0));
Serial.print("cos(1.0)");
Serial.println(cos(1.0));
でやった方は
cos(0.0)1.00
cos(1.0)0.54
ちゃんと出てるので,違う?
オーバーロードしまくりマクロ使用なので実際どうなってるかわかりにくい.
if (arduino::cos(1.0) != 0.00) {
serial::println("cos(1.0)is not 0.00 ");
}
でserial::println("cos(1.0)is not 0.00 ");
に到達したので,結果自体は正しく取れてそう.
serial::print("print ");
serial::println("println");
serial::println("print UTF-8 : 𰻞𰻞麺");
serial::println("print UTF-8 : 🍆");
serial::print("printInt(10):");
serial::print_int(10);
serial::println("");
serial::print("printLong(3147483647):");
// int32の最大値2147483647を超えた値を入れてみる
serial::print_long(3147483647);
serial::println("");
serial::print("printFloat(1.1111):");
serial::print_float(1.1111);
serial::println("");
serial::print("printDouble(1.123456789012345678901):");
// float32の最大値
serial::print_double(1.123456789012345678901);
serial::println("");
Project Mahiwa : WebAssembly launch
print println
print UTF-8 : 𰻞𰻞麺
print UTF-8 : 🍆
printInt(10):10
printLong(3147483647):-1147483649
printFloat(1.1111):1.11
printDouble(1.123456789012345678901):1.12
Project Mahiwa : WebAssembly done
Longが壊れている,floatとdoubleも結果が丸められている.
printDouble(1.123456789012345678901):はある程度は取れてるので,sinの結果が正しいことと矛盾する.なぜ.
Serial.print(String(num, 10));
にしたら
printInt(10):10
printLong(3147483647):-1147483649
printFloat(1.1111):1.1110999584
printDouble(1.123456789012345678901):1.1234567890
確かに取れてるが,壊れているところは壊れる. ありのままをプリントしたい.
arduinoではsprintfでfloatとか出せないらしい
ESP32版のArduinoにはprintfが入っているらしい
dtostrfを組み合わせるとできそう.ちょっと厄介だが.
dtostrfはデフォで入ってるはずが入ってない.
実行時に桁数も指定するのが良さそう.
serial::print_double(1.123456789012345678901, 30);
↓
printDouble(1.123456789012345678901):1.123456789012345691247674039914
後ろの値が壊れている……doubleなので読めるはずだが.
Longのオーバーフローは謎
→謎だが,仕様でintとlongの最大値は同じらしい https://learn.microsoft.com/ja-jp/cpp/c-language/cpp-integer-limits?view=msvc-170
明らかにおかしいが,仕様なのでしょうがない.
fn _start() {
// Arduino関数の動作確認
/*
* Serial
*/
serial::print("print ");
serial::println("println");
serial::println("print UTF-8 : 𰻞𰻞麺");
serial::println("print UTF-8 : 🍆");
// intとlongで表せる範囲が同じ.←直感と反するが仕様である
serial::print("printInt(10):");
serial::print_int(10);
serial::println("");
serial::print("printLong(1000):");
serial::print_long(1000);
serial::println("");
serial::print("printLong(2247483647)❌:");
// longの最大値2147483647を超えた値を入れてみる(オーバーフロー)
serial::print_long(2247483647);
serial::println("");
serial::print("printFloat(1.1111):");
serial::print_float(1.1111, 4);
serial::println("");
serial::print("printFloat(1.123456789012345)❌:");
// float32の最大値を超えた値を入れてみる
serial::print_float(1.123456789012345, 15);
serial::println("");
serial::print("printDouble(1.123456789012345):");
serial::print_double(1.123456789012345, 15);
serial::println("");
}
Project Mahiwa : WebAssembly launch
print println
print UTF-8 : 𰻞𰻞麺
print UTF-8 : 🍆
printInt(10):10
printLong(1000):1000
printLong(2247483647)❌:-2047483649
printFloat(1.1111):1.1111
printFloat(1.123456789012345)❌:1.123456835746765
printDouble(1.123456789012345):1.123456789012345
Project Mahiwa : WebAssembly done
ちゃんとオーバーフローが期待できる場所はオーバーフローしてて問題なさそうに修正できた.
新しく作っても結果変わらず
cos(0.0): 0.000000
cos(1.0): 0.000000
sin(1.0): 0.000000
sin(0.0): 0.000000
tan(1.0): 0.000000
tan(1.1): 0.000000
本当の定義をメソッドジャンプしてみると
extern double sin (double);
とdouble,doubleになっており,型も問題なさそう.
未解決.
Goではちゃんとcosの値が取れた.ただし直後にpanicする
cos(1.0):0.540302Guru Meditation Error: Core 1 panic'ed (Double exception).
これはprint側に問題がありそう
printFloat(1.1111):1.1111Guru Meditation Error: Core 1 panic'ed (Unhandled debug exception).
Debug exception reason: Stack canary watchpoint triggered (wasm3)
https://github.com/wasm3/wasm3/issues/102#issuecomment-586643752
これっぽい
This means that the interpreter has run out of the (native) stack. One option is to run an interpreter in a separate task with a larger stack size.
floatが入らないレベルでスタックサイズが小さいってこと?
let cos2 = arduino::cos(1.0);
let cos2x100 = (cos2 * 100.0) as i32;
serial::print_int(cos2x100);
の結果が
cos(1.0): 0
やはりarudino::cosの返り値がおかしい 一方でgoでは取れているのでbackendの実装は壊れてなさそう
どちらもf64 f64なので型には問題ないが……
最悪f64の受け取りはそのままで、内部的にはいったんintに変えて、backendでfloatに戻すとかもありかも……
おそらくWebAssemblyが間に挟まってることで起きるのだが、そこは見れないので難しい。
goでは動いていることを踏まえて、backendの実装ミスではないので、一旦保留する。
🐛 概要
mahiwa-backendで直接読んだ場合は
のようになるが,Rustから呼ぶと
になる.
原因
備考