質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

2188閲覧

C++のfftを用いたofdmのプログラムで2の累乗でないものを0つめして2の累乗にしてから計算するとセグメントエラーが出る。

aqufiz

総合スコア70

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2019/05/07 06:43

前提・実現したいこと

C++のfftを用いたofdmのプログラムで2の累乗でないものを0つめして2の累乗にしてから計算するとセグメントエラーが発生しました。
入力データが元から2の累乗だとエラーは出ません。
0つめはqpskで変調した後、IFFTの直前で行なっています。

発生している問題・エラーメッセージ

セグメントエラー

試したこと

0つめが2累乗の個数までできていないのかと思い、確認しましたができていました。

該当のソースコード

C++

1#include<iostream> 2#include<stdlib.h> 3#include<math.h> 4#include<time.h> 5#include<fstream> 6#include<complex> 7#include<algorithm> 8#include<vector> 9 10using namespace std; 11 12#define PI acos(double(-1.0)) 13#define L 1024 /*送信データbit数*/ 14#define SNR_STEP 40/*SN比をいくつまで調べるか*/ 15 16 17typedef struct{ 18 vector<int> dat; 19 vector<complex<double> > sig; 20}TX_SIGNALS; 21 22typedef struct{ 23 vector<int> dat; 24 vector<complex<double> > sig; 25 vector<complex<double> > noise; 26}RX_SIGNALS; 27 28 29 30void _randData(TX_SIGNALS *d){ 31 int i; 32 double x; 33 for(i=0;i<L;i++){ 34 x = drand48(); /*ランダムデータ発生*/ 35 if(x >=0.5) 36 d->dat[i] =1.0; 37 else 38 d->dat[i] =0.0; 39 } 40} 41 42void _qpskMod(TX_SIGNALS *s){ 43 int i,co; 44 s->sig.resize(L/2); 45 double c=1.0/sqrt(2.0); 46 if ((s->sig.size()*2) != (s->dat.size())){ 47 cout<<"Error: _qpskMod, 長さが一致しません"<<endl; /*QPSK変調器(送信)*/ 48 exit(1); 49 } 50 else { 51 for(i=0;i<s->sig.size();i++){ 52 co = 2*i; 53 complex<double>z(c * ((s->dat[co])-0.5)*2.0,c * ((s->dat[co+1])-0.5)*2.0); 54 s->sig[i] =z; 55 } 56 } 57} 58 59int Ifour(TX_SIGNALS *tx,int isign){ 60 unsigned long n,mmax,m,j,istep,i,res,exs; 61 double wtemp,wr,wpr,wpi,wi,theta,tempr,tempi; 62 63 res=1; 64 exs=L; 65 if ((exs & (exs - 1)) != 0) { 66 while (exs > 0) { 67 res <<= 1; exs >>= 1; 68 } 69 tx->sig.resize(res/2); 70 for (i = 0; i < (res - L)/2; i++) { 71 const complex<double> add(0.0, 0.0); 72 tx->sig.push_back(add); 73 } 74 } 75 else{ 76 res=L; 77 } 78 n = res/2; 79 80 j=0; 81 for(i=0;i<n;i++){ 82 if(j>i){ 83 swap(tx->sig[j],tx->sig[i]); 84 } 85 m=n >>1; 86 while (m >= 1 && j >=m){ 87 j -=m; 88 m >>=1; 89 } 90 j+= m; 91 } 92 mmax=1; 93 while(n >mmax){ 94 istep=mmax <<1; 95 theta=isign*(2*PI/istep); 96 wtemp=sin(0.5*theta); 97 wpr = -2.0*wtemp*wtemp; 98 wpi=sin(theta); 99 wr=1.0; 100 wi=0.0; 101 for(m=0;m<mmax;m++){ 102 for(i=m;i<=n;i+=istep){ 103 j=i+mmax; 104 tempr=wr*(tx->sig[j].real())-wi*(tx->sig[j].imag()); 105 tempi=wr*(tx->sig[j].imag())+wi*(tx->sig[j].real()); 106 complex<double> a((tx->sig[i].real())-tempr,(tx->sig[i].imag())-tempi); 107 tx->sig[j]=a; 108 complex<double> b((tx->sig[i].real())+tempr,(tx->sig[i].imag())+tempi); 109 tx->sig[i]=b; 110 111 } 112 wr=(wtemp=wr)*wpr-wi*wpi+wr; 113 wi=wi*wpr+wtemp*wpi+wi; 114 } 115 mmax=istep; 116 } 117 for(i=0;i<tx->sig.size();i++){ 118 tx->sig[i]/=(double)(tx->sig.size()); 119 } 120 121 /*fstream file3; 122 file3.open("ofIFFT.txt",ios::out); 123 for(i=0;i<tx->sig.size();i++){ 124 file3<<(tx->sig[i]).real()<<" "<<(tx->sig[i]).imag()<<endl; 125 126 } 127 file3.close();*/ 128 129 return(res); 130 131} 132 133 134double _SNRdBNP(double c_dB){ 135 return pow(10,(-1)*c_dB/10); /*雑音電力計算*/ 136} 137 138 139void _awgn(RX_SIGNALS *n,TX_SIGNALS *m, double Pn,double ave,double sigma){ 140 double B1,B2,B; 141 int i; 142 n->noise.resize(m->sig.size()); 143 for(i=0;i<(n->noise.size());i++){ 144 145 B1 =ave+ sigma*sqrt(-2.0*log(drand48()))*cos(2.0*PI*drand48()); /*Box Muller法*/ 146 B2 =ave+ sigma*sqrt(-2.0*log(drand48()))*sin(2.0*PI*drand48()); 147 148 complex<double>B(B1* sqrt(Pn/2),B2* sqrt(Pn/2)); /*AWGN発生*/ 149 150 151 n->noise[i]=B; 152 } 153 /*fstream file4; 154 file4.open("noise.txt",ios::out); 155 for(i=0;i<n->noise.size();i++){ 156 file4<<n->noise[i]<<endl; 157 } 158 159 file4.close();*/ 160} 161 162void _vectorSum(RX_SIGNALS *a,TX_SIGNALS *b){ 163 int i; 164 a->sig.resize(b->sig.size()); 165 if(a->sig.size() != b->sig.size() || b->sig.size() != a->noise.size()){ 166 cout<<"Error: _vectorSum, 長さが一致しません"<<endl; /*ベクトル加算(系列と系列の加算)*/ 167 exit(1); 168 } 169 else{ 170 for(i=0;i<(a->sig.size());i++){ 171 complex<double> H(1+pow(10,-0.25)*cos(2*PI*5*pow(10.0,-6.0)*i),-pow(10,-0.25)*sin(2*PI*5*pow(10.0,-6.0)*i)); 172 a->sig[i] = H*(b->sig[i]) + a->noise[i]; 173 } 174 } 175} 176 177void four(RX_SIGNALS *rx,int isign,int nn){ 178 unsigned long n,mmax,m,j,istep,i,res,exs; 179 double wtemp,wr,wpr,wpi,wi,theta,tempr,tempi; 180 181 n=nn/2; 182 183 j=0; 184 for(i=0;i<n;i++){ 185 if(j>i){ 186 swap(rx->sig[j],rx->sig[i]); 187 } 188 m=n >>1; 189 while (m >= 1 && j >=m){ 190 j -=m; 191 m >>=1; 192 } 193 j+= m; 194 } 195 mmax=1; 196 while(n >mmax){ 197 istep=mmax <<1; 198 theta=isign*(2*PI/istep); 199 wtemp=sin(0.5*theta); 200 wpr = -2.0*wtemp*wtemp; 201 wpi=sin(theta); 202 wr=1.0; 203 wi=0.0; 204 for(m=0;m<mmax;m++){ 205 for(i=m;i<=n;i+=istep){ 206 j=i+mmax; 207 tempr=wr*(rx->sig[j].real())-wi*(rx->sig[j].imag()); 208 tempi=wr*(rx->sig[j].imag())+wi*(rx->sig[j].real()); 209 complex<double> a((rx->sig[i].real())-tempr,(rx->sig[i].imag())-tempi); 210 rx->sig[j]=a; 211 complex<double> b((rx->sig[i].real())+tempr,(rx->sig[i].imag())+tempi); 212 rx->sig[i]=b; 213 214 } 215 wr=(wtemp=wr)*wpr-wi*wpi+wr; 216 wi=wi*wpr+wtemp*wpi+wi; 217 } 218 mmax=istep; 219 } 220 221} 222 223 224void zero(RX_SIGNALS *d){ 225 int i; 226 for(i=0;i<(d->sig.size());i++){ 227 complex<double> H(1.0+pow(10.0,-0.25)*cos(2.0*PI*5.0*0.000001*i),-pow(10.0,-0.25)*sin(2.0*PI*5.0*0.000001*i)); 228 d->sig[i]=d->sig[i]/H; 229 } 230} 231 232void _qpskDem(RX_SIGNALS *rx){ 233 int i,co; 234 for(i=0;i<rx->dat.size();i++) 235 rx->dat[i] = 0.0; 236 for(i=0;i<rx->sig.size();i++){ 237 co = 2*i; 238 if((rx->sig[i]).real()>=0.0) /*QPSK復調器(受信)*/ 239 rx->dat[co]=1; 240 if((rx->sig[i]).imag()>=0.0) 241 rx->dat[co+1]=1; 242 } 243} 244 245 246double _BER(TX_SIGNALS *tx,RX_SIGNALS *rx){ 247 int i,sum=0; 248 double BER; 249 if(tx->dat.size() != rx->dat.size()){ 250 cout<<"Error: _BER() 長さが一致しません"<<endl; /*BER計算*/ 251 return 1; 252 } 253 else{ 254 for(i=0;i<tx->dat.size();i++) 255 if((tx->dat[i]) - (rx->dat[i])!=0){ 256 sum++; 257 } 258 259 BER = (double)sum/(tx->dat.size()); 260 } 261 return(BER); 262} 263 264void _BERprint(int snr_step, double *SNRdB, double *BER){ 265 int i; 266 fstream file1; 267 file1.open("OFDMBER.txt",ios::out); /*BERをファイルに書き出す*/ 268 269 270 for(i=0;i<snr_step;i++){ 271 272 file1<<*(SNRdB+i)<<" "<<*(BER+i)<<endl; 273 } 274 file1.close(); 275} 276 277 278 279int main(){ 280 TX_SIGNALS tx; 281 RX_SIGNALS rx; 282 double BER[SNR_STEP],SNRdB[SNR_STEP]; 283 int i,y,news; 284 /*init_rtx(&tx,&rx); TX_SIGNALS,RX_SIGNALSのメンバ初期化*/ 285 286 tx.dat.resize(L); 287 tx.sig.resize(L/2); /*txのメモリの確保*/ 288 rx.dat.resize(L); 289 rx.sig.resize(L/2); 290 rx.noise.resize(L/2); /*rxのメモリの確保*/ 291 srand48(123); 292 for(i=0;i<SNR_STEP;i++){ 293 SNRdB[i]=(double)i; 294 } 295 for(i=0;i<SNR_STEP;i++){ 296 _randData(&tx); /*ランダムデータ発生*/ 297 _qpskMod(&tx); /*QPSK変調器(送信)*/ 298 news=Ifour(&tx,-1); /*Ifft*/ 299 _awgn(&rx,&tx,_SNRdBNP(SNRdB[i]),0.0,1.0); /*AWGN発生*/ 300 _vectorSum(&rx,&tx); /*ベクトル加算(系列と系列の加算)*/ 301 four(&rx,1,news); /*fft*/ 302 zero(&rx); /*等化*/ 303 _qpskDem(&rx); /*QPSK復調器(受信)*/ 304 BER[i]=_BER(&tx,&rx); /*BER計算*/ 305 } 306 _BERprint(SNR_STEP,SNRdB,BER); 307 return 0; 308}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

moredeep

2019/05/07 07:29

エラーが出た時にどの行でエラーが発生したか表示されていませんか?
aqufiz

2019/05/07 07:57 編集

すみません、セグメントエラーなので表示されてないです。
aqufiz

2019/05/07 07:58

各関数が終わった時にコメントを表示させるようにした時、fftのところで止まっているので、fftのプログラムに問題があるのかもしれないです。
moredeep

2019/05/07 08:45 編集

すみませんがちょっとよくわからないんです。 ・入力データとはどれのことを指していますか? ・0つめとは何のことですか?何を目的としてどのような処理を行おうとしていますか? ・提示のコードで動くことを確認しましたか? →exs=L;←Lが定数(1024)なので、その直後のifは必ず偽です。 →その下のwhile内のifの条件(i<=n)、tx->sigのサイズとnはたぶん同じです。iがnと一致してしまうと、tx->sig[tx->sig.size()]と同じ意味になり、out of rangeです。iはm(初回は0)から、nは512、iStepはmmax(初回は1)+1なので、必ず1ループ目にエラーです。 他にもあれ?と思うようなところがあり、でも全てを見たわけではないのでもしかしたら正常かもしれないと、恐らく全体を把握しないと判断が難しいのですが、さすがにこのレベルのコード全部は見ていられないです。。
episteme

2019/05/07 09:43

> 入力データが元から2の累乗だとエラーは出ません。 0で埋めた直後、データ数が確かに2のベキになってるかは確認済なんですよね?
aqufiz

2019/05/07 11:37

>>moredeepさん ・入力データは送信データビット数のLを示しています. ・fftは2の累乗でないと計算できないため,足りないデータ数の分のところに0を代入して数合わせをしています ・Lは送信ビット数でいろいろな値に変えたりしています. ・i=nのときout of rangeになってしまっていました,ありがとうございます. 説明不足ですみません.お忙しい中,助言をしてくださってありがとうございます.
aqufiz

2019/05/07 11:38

>>episteme 確認済みです.
episteme

2019/05/07 12:17

↑だとするとデータ数がハナっから2^Nなときと0詰めしたときとでは何かが違うってことやね...
aqufiz

2019/05/07 12:19 編集

そうですね、データに0が入っていること以外同じはずなのですが、なぜかセグメントエラーが出てしまいます。
aqufiz

2019/05/07 12:42

i=nのときout of rangeになってしまっていたところをIFFTだけでなく,FFTでも修正したところコンパイルが通り,結果も直っていましたありがとうございます. moredeepさんを回答してくれた方にしたいので,回答の方にコメントしていただけると助かります.
episteme

2019/05/07 13:07

「ハナっから2^Nならちゃんと動く」を説明できるんですかその↑修正?
aqufiz

2019/05/07 15:59

ご指摘の通りだと思います。一応動いていますが求めてる動作ではないです。しかし、今回の質問ではセグメントエラーの解決を目指していたので解決としました。
aqufiz

2019/05/07 16:27 編集

2^Nの時も求めた結果ではなかったのですが、2^Nでないデータを入れた時に結果すら見れなくなってしまったので、まずそこを修正してからより深い、白色雑音の大きさなどの中身の修正をしていきたいと思い今回の質問をさせていただきました。
aqufiz

2019/05/07 16:28

こんな情報も少なく曖昧な質問に答えていただきありがとうございました。
episteme

2019/05/07 19:31

fftを実装することが目的でないのなら出来合いのFFTWあたりを使っちゃうのもテかも。老婆心ながら。
guest

回答1

0

ベストアンサー

本当に根本から解決できたかは置いておき、とりあえずエラーが出なくなったとのことで、お役に立てて良かったです。

他にも問題と思しき箇所、例えば

if ((exs & (exs - 1)) != 0) { while (exs > 0) { res <<= 1; exs >>= 1; } tx->sig.resize(res/2); // ←これ for (i = 0; i < (res - L)/2; i++) { const complex<double> add(0.0, 0.0); tx->sig.push_back(add); // ←これ } }

入力Lが6のとき、whileの後resは8であると思います。
tx->sigのサイズはres / 2で4ですよね。
その後に(res - L) / 2回((8-6)/2で1回)push_backすると、最終的にはtx->sigのサイズは5です。これは意図した動きではないのではないかと思います。
(どんな入力の時にこうなってほしいとかが曖昧なのでちょっと自信ないですが。)

兎に角、一度関数毎のIOをチェックしてみるのが良いと思います。

投稿2019/05/08 00:51

moredeep

総合スコア1507

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

aqufiz

2019/05/08 03:14

tx->sig.resize(res/2); は必要なかったので削除しました。 ここからは関数の動作を一つずつ確認していきたいと思います。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問