sin関数の計算結果がGR-SAKURAと違う?

ド素人ですw。以前にGR-SAKURAのフォーラムで「8×8×8のLED-CUBEを作ったけど、うまく動かない」で助けて頂いた者です。

https://japan.renesasrulz.com/gr_user_forum_japanese/f/gr-sakura/3717/thread

同じLED-CUBEをとある事情で、SAKURA->秋月で買ったRX621ボードへの移植をしてます。(せっかくかわいいSAKURAボードは、他の用事に使おうかとw)

e2studioで作ってます。なんとかほぼ動くようになったのですが、sinを使ってる所でSAKURAとLEDの表示が違います…。

SAKURAの方のプログラムの該当部分は、

1 :  void ripples(int times, int repeat)
2 :  {
3 :    int i,j,k,z;
4 :    float distance,ztemp;
5 :    clearData();

6 :    for(k=0;k<=repeat;++k) {
7 :      for(i=0;i<=3;++i) {
8 :        for(j=0;j<=3;++j) {
9 :          distance=sqrt((3.5-(float)i)*(3.5-(float)i)+(3.5-(float)j)*(3.5-(float)j));
10:          ztemp=3.5+sin(distance/1.3+(float)k/3.14159)*3.5;
11:          z=(int)(ztemp+0.5);
12:          bitSet(dispData[z][i],j);
13:          bitSet(dispData[z][7-i],j);
14:          bitSet(dispData[z][i],7-j);
15:          bitSet(dispData[z][7-i],7-j);
16:        }
17:      }
18:      LEDDisp(times);
19:      clearData();
20:    }
21:  }

LED表示用配列の辺は見ないで頂いて(移植に伴いbitsetー>ビットシフトに変えてます)、9~11行目の式で、がじぇるねのwebコンパイラでビルドしたSAKURAと、e2studioでビルドしたRX621ボードとで、計算結果が異なる原因が何かあるでしょうか…?

sqrtとsinをsqrtfとsinfに変えてみたりとか、型指定を外してみたりとかしても、変わらない様です。

(printfで計算結果を確認しようとしたのですがうまくいかないので、ほんとに計算結果が違うかどうかは確認できていません…)

どなたかご助言頂けると助かります。

  • koheiさん、こんにちは。NoMaYです。

    まず、コンパイラはGNURXでしょうか?CC-RXでしょうか?また、バージョンは幾つでしょうか?それと、GNURXの場合は、ライブラリはOPTLIB(古いe2 studioのデフォルト)でしょうか?NEWLIB(最近のe2 studioのデフォルト)でしょうか?さらに、以前のスレッドを見直してみたのですが、GR-SAKURAでのコンパイラに何を使われていたのか不明でしたので、その情報も必要かな、と思います。WEBコンパイラ?(時期は?)、IDE4GR同梱コンパイラ?(IDE4GRのバージョンは?)、です。

    sin関数の計算結果が違うらしい、ということで思い浮かぶのは、RX63NとRX621ではソフトウェアライブラリによる近似計算ですので、ライブラリの違いによって微妙な差が出る可能性はあると思います。(あくまで可能性です。) あと、C言語仕様では、float型はdouble型にキャストされて関数に引き渡されますけど、コンパイラオプションでキャストを抑止出来たりしますので、その辺りのコンパイラオプションが異なっている可能性も考えられます。(今のところ可能性です。) あと、引数が2πを超えた時の挙動がどうなっているかも気になります。

    コンパイラの情報が不明ですので次の手には移れませんが、その辺りが明確になれば、ハードを持たない私がやれる手としてはシミュレータでデバッグして計算結果の違いを調べることになるかと思います。

    他方、もしハードを持っていれば、printfで確認するのが手っ取り早そうかな、とも思います。ただ、浮動小数点数のprintfは落とし穴もそれなりに予想されますので、事前の試行錯誤は必要かも知れないかな(まるっきり最初からprintfを信用して使うのは危ないかも)、とも思います。

    ちなみに、koheiさんがprintfで計算結果を確認しようとしてうまく行かなかったのは、どんな点でしょうか?

  • 「ド素人です」とお断りしたのにww。全然ズレた返答をしたらごめんなさいw。(あと、画像がキレイに貼れなかったらごめんなさい。)

    コンパイラとバージョンは…、

    この画面の

    ツーツチェーン:Renesas CCRX

    バージョン:v3.02.00

    の事でしょうか…。

     

    ライブラリーは…、

    この画面の事ではなさそうですね…

     

    printfは、ビルドで何かエラーが出て通らなかったのですが、

    別のサンプルプログラム作ってビルドしたら、そちらはエラー無しで通りました…。どこが違うのか、これから考えます…w。

    そもそもprintfは…どこに出力されるのでしょう?試してみた他のボード(例えばnucleoのSTM32F411)では、COMポートに認識されてTeraTermとかで受け取れたのですが、それはnucleoボードのST-LINKが複雑な通信を肩代わりしてくれてるだけで、普通のボードはSerial通信を定義してあげたりしないと、パソコン側とのデータやりとりはできないのかな…?(E2エミュレータみたいなものを持ってないと、確認しながらのデバッグはできないのかな…)

     

    型変換の罠か、「sinは何も書かないとラジアンじゃなくて度よ」とか、何か「そりゃそうよ」的な単純な罠があるのでは?と質問させて頂いたのですが、そうでもないのでしょうか。

    WEBコンパイラーは…、今日見ると「2018-12-19 Version 3.00」と書いてありますw。いつコンパイルしたか忘れましたが、多分今日ビルドしても同じ結果と思います。

     今晩・明日ちょっと忙しいので、日曜中にもう一度SAKURAに差し替えしてみて、LEDの表示が「結果としてどう違うのか」、動画を取りたいと思います。

  • sin や sqrt 等数学関数は math.h をインクルードしないと正常動作しませんがされてますか
  • もちろん、エラーが出ずにビルド・書き込み・実物実行してるので、インクルードしてます。
    (今見たら…、sin・sqrtとsinf・sqrtfと、どちらを使うべきなのか分からないので、math.hとmathf.hと両方インクルードしてたつもりだったのですが、LibraryGeneratorの「構成」の画面(先ほどのrepに張り付けてる)でmathf.hにチェック入れてるけど、インクルードはmath.hしか記述してませんでした。)
  • > もちろん、エラーが出ずにビルド・書き込み・実物実行してるので、

    関数プロトタイプが含まれるヘッダファイルのインクルードを忘れてもエラーとはならずに警告が出るだけだと思いますが一つの警告も出ていないでしょうか?
  • インクルードはしてるつもりなのですが…。警告は「W0561017:The evaluation period has expired」というのが1つ出てるようですが…。
  • > 警告は「W0561017:The evaluation period has expired」というのが1つ

    「お試し期間終わったから金払え」ということですがとりあえず無視して良いです。
  • あ、そのヤツか~ww。プログラムのサイズ制限があるんだったかしら?(辞書引いても分からなかったw)
    ありがとです~。(「変数やユーザー定義関数の評価をせー」とかいう意味かと思ったw。)
  • koheiさん、こんにちは。NoMaYです。

    > 「ド素人です」とお断りしたのにww。全然ズレた返答をしたらごめんなさいw。

    ああっ、ごめんなさい、でもちゃんとイイ感じでリプライされていると思いますよ。GR-SAKURAでは、printf出力(というかSerial.writeでしたっけ?)することは出来そうですか? それから、念の為、e2 studioのバージョンも教えて下さい。

    それが出来るのであれば、koheiさんの主たる関心事(たぶんデバッグ力の向上は対象外かな)と私の好奇心を鑑みて、ひとまず以下の手はどうかなと思いました。

    koheiさん

    ・GR-SAKURAで値を出力して、その結果を投稿して頂く。(ripples関数のrepeat引数の値も。3にしとけば良いのかな?)



    ・くだんの関数をシミュレータで実行して、koheiさんの結果と突き合わせたものを投稿する。

    それで、私がそれを試すのに以下のファイルが欲しいのですが、zipファイルに固めて添付して投稿して頂けるとうれしいです。(リプライする時に Use rich formatting のところをクリックすると、ファイル添付が可能な画面モードになります。)

    欲しいファイル

    ・プロジェクトフォルダにある .cproject というファイル

  • がじぇるね岡宮です。

    #すみません、コードの中で、for文のkの演算が足りてないですね。つねに0で計算しているため、不十分です。

    CCRXと、Webコンパイラで使っているGCCで違いが出るか、GR-SAKURAで試してみましたが、結果としては一緒でした。

    for文2個で4回ずつ計16回ループしているため、かなり限定的な演算の比較なので、どれくらいsinの結果が一致してるかは未検証です。できれば、どういった差分が出るのか教えていただけるとありがたいです。

     

    ■Renesas CCRX V3.02.00

    (新規プロジェクト作成で、FITモジュールのbspのみ適用、LibGenでmath.hを追加)

    コード

    #include <stdio.h>
    #include <math.h>
    void main(void)
    {
    int i,j,k,z;
    float distance,ztemp;
    for(i=0;i<=3;++i) {
    for(j=0;j<=3;++j) {
    distance=sqrt((3.5-(float)i)*(3.5-(float)i)+(3.5-(float)j)*(3.5-(float)j));
    ztemp=3.5+sin(distance/1.3+(float)k/3.14159)*3.5;
    z=(int)(ztemp+0.5);
    printf("%d",z);printf(",");printf("%d",i);printf(",");printf("%d",j);
    printf("\r\n");
    printf("%d",z);printf(",");printf("%d",7-i);printf(",");printf("%d",j);
    printf("\r\n");
    printf("%d",z);printf(",");printf("%d",i);printf(",");printf("%d",7-j);
    printf("\r\n");
    printf("%d",z);printf(",");printf("%d",7-i);printf(",");printf("%d",7-j);
    printf("\r\n");
    printf("\r\n");
    }
    }
    while(1) {

    // TODO: add application code here
    }

    }

    結果

    1,0,0
    1,7,0
    1,0,7
    1,7,7

    3,0,1
    3,7,1
    3,0,6
    3,7,6

    4,0,2
    4,7,2
    4,0,5
    4,7,5

    5,0,3
    5,7,3
    5,0,4
    5,7,4

    3,1,0
    3,6,0
    3,1,7
    3,6,7

    5,1,1
    5,6,1
    5,1,6
    5,6,6

    6,1,2
    6,6,2
    6,1,5
    6,6,5

    7,1,3
    7,6,3
    7,1,4
    7,6,4

    4,2,0
    4,5,0
    4,2,7
    4,5,7

    6,2,1
    6,5,1
    6,2,6
    6,5,6

    7,2,2
    7,5,2
    7,2,5
    7,5,5

    7,2,3
    7,5,3
    7,2,4
    7,5,4

    5,3,0
    5,4,0
    5,3,7
    5,4,7

    7,3,1
    7,4,1
    7,3,6
    7,4,6

    7,3,2
    7,4,2
    7,3,5
    7,4,5

    5,3,3
    5,4,3
    5,3,4
    5,4,4

     

    ■Webコンパイラ(KPIT GNURX-ELF Toolchain 14.03.. ちょっと古くて恐縮ですが、Mac版IDE for GRと合わせるためバージョン変更してません)

    (mathはNewlib prebuild使用)

    コード

    void setup()
    {
    Serial.begin(9600);
    delay(1000);
    int i,j,k,z;
    float distance,ztemp;
    for(i=0;i<=3;++i) {
    for(j=0;j<=3;++j) {
    distance=sqrt((3.5-(float)i)*(3.5-(float)i)+(3.5-(float)j)*(3.5-(float)j));
    ztemp=3.5+sin(distance/1.3+(float)k/3.14159)*3.5;
    z=(int)(ztemp+0.5);
    Serial.print(z);Serial.print(",");Serial.print(i);Serial.print(",");Serial.print(j);
    Serial.println();
    Serial.print(z);Serial.print(",");Serial.print(7-i);Serial.print(",");Serial.print(j);
    Serial.println();
    Serial.print(z);Serial.print(",");Serial.print(i);Serial.print(",");Serial.print(7-j);
    Serial.println();
    Serial.print(z);Serial.print(",");Serial.print(7-i);Serial.print(",");Serial.print(7-j);
    Serial.println();
    Serial.println();
    delay(100);
    }
    }

    }

    void loop(){
    }

     

    結果

    1,0,0
    1,7,0
    1,0,7
    1,7,7

    3,0,1
    3,7,1
    3,0,6
    3,7,6

    4,0,2
    4,7,2
    4,0,5
    4,7,5

    5,0,3
    5,7,3
    5,0,4
    5,7,4

    3,1,0
    3,6,0
    3,1,7
    3,6,7

    5,1,1
    5,6,1
    5,1,6
    5,6,6

    6,1,2
    6,6,2
    6,1,5
    6,6,5

    7,1,3
    7,6,3
    7,1,4
    7,6,4

    4,2,0
    4,5,0
    4,2,7
    4,5,7

    6,2,1
    6,5,1
    6,2,6
    6,5,6

    7,2,2
    7,5,2
    7,2,5
    7,5,5

    7,2,3
    7,5,3
    7,2,4
    7,5,4

    5,3,0
    5,4,0
    5,3,7
    5,4,7

    7,3,1
    7,4,1
    7,3,6
    7,4,6

    7,3,2
    7,4,2
    7,3,5
    7,4,5

    5,3,3
    5,4,3
    5,3,4
    5,4,4