Closed kmyk closed 2 years ago
push_back
が変数を更新することを考慮してないのが原因ぽい
新しい issue を立てるつもりでしたがここの話と同じような気がしてきたのでここに書きます。
def f(n: int) -> int:
a = 0
b = 1
for _ in range(n):
c = (a + b) % 1000000007
a = b
b = c
return a
def solve(n: int) -> int:
return f(n)
上記のコードを変換した際に、MoveSemantics
を コメントアウトした 状態だと
// ...
int64_t solve(int64_t n_0) {
int64_t x1_4 = 1;
int64_t x1_5 = 0;
for (int32_t i2 = 0; i2 < int32_t(n_0); ++ i2) {
int64_t x6 = jikka::mod::plus(jikka::modmat::floormod<2>(std::array<int64_t, 2>{x1_4, x1_5}, 1000000007)[1], jikka::modmat::floormod<2>(std::array<int64_t, 2>{x1_4, x1_5}, 1000000007)[0], 1000000007);
int64_t x7 = x1_4;
x1_4 = x6;
x1_5 = x7;
}
return x1_5;
}
// ...
と正しいコードが得られるのに対し、 コメントアウトしていない 状態だと
// ...
int64_t solve(int64_t n_0) {
int64_t x1_4 = 1;
int64_t x1_5 = 0;
for (int32_t i2 = 0; i2 < int32_t(n_0); ++ i2) {
int64_t x6 = jikka::mod::plus(jikka::modmat::floormod<2>(std::array<int64_t, 2>{x1_4, x1_5}, 1000000007)[1], jikka::modmat::floormod<2>(std::array<int64_t, 2>{x1_4, x1_5}, 1000000007)[0], 1000000007);
x1_4 = x6;
x1_5 = x1_4;
}
return x1_5;
}
// ...
と正しくないコードが得られることを確認しました。
$ git log --oneline -1
2edaccd Merge pull request #165 from riantkb/153-add-temporary-variable
たとえば
vector<int> func(vector<int> a) { for (int i = 0; i < n - 1; ++ i) { vector<int> b = a; b[i + 1] = a[i]; a = b; } return a; }
を
vector<int> func(vector<int> a) { for (int i = 0; i < n - 1; ++ i) { a[i + 1] = a[i]; } return a; }
に変換しないとだめなのだけど、これ無理じゃない? core から C++ への変換のときに情報が落ちてしまってて、その状態で添字の解析をやるのはしんどすぎるし、ある程度はやれたとしても不可能ケースが残ってしまう。 UnpackTuples.hs や MoveSemantics.hs の中身をすべて ToCore.hs に埋め込んで、core から C++ への変換のときにすべてを同時に最適にやるしかなさそう
https://github.com/kmyk/Jikka/pull/168#issuecomment-894584836
実装方針ミスが発覚したときの顔をしています 😇
確かに core 言語で書かれたコードを等価でない cpp に変換してから頑張る、というのはかなり筋が悪そうな気がするので、core を cpp に変換するタイミングで頑張るしかなさそうですね…… 😇
MoveSemantics.hs が以下のような C++ について
これを間違えて
に変換してるぽい
Originally posted by @kmyk in https://github.com/kmyk/Jikka/issues/153#issuecomment-893423374