TEST_F( FftwTest, directFourierTransformComplex) { MultidimArray< std::complex< double > > FFT1, complxDouble; FourierTransformer transformer1; typeCast(mulDouble, complxDouble); transformer1.FourierTransform(complxDouble, FFT1, false); transformer1.inverseFourierTransform(); transformer1.inverseFourierTransform(); MultidimArray<std::complex<double> > auxFFT; auxFFT.resize(3,3); DIRECT_A2D_ELEM(auxFFT,0,0) = std::complex<double>(2.77778,0); DIRECT_A2D_ELEM(auxFFT,0,1) = std::complex<double>(-0.0555556,0.096225); DIRECT_A2D_ELEM(auxFFT,0,2) = std::complex<double>(-0.0555556,-0.096225); DIRECT_A2D_ELEM(auxFFT,1,0) = std::complex<double>(-0.388889,0.673575) ; DIRECT_A2D_ELEM(auxFFT,1,1) = std::complex<double>(-0.388889,-0.096225); DIRECT_A2D_ELEM(auxFFT,1,2) = std::complex<double>(-0.0555556,-0.288675); DIRECT_A2D_ELEM(auxFFT,2,0) = std::complex<double>(-0.388889,-0.673575) ; DIRECT_A2D_ELEM(auxFFT,2,1) = std::complex<double>(-0.0555556,0.288675) ; DIRECT_A2D_ELEM(auxFFT,2,2) = std::complex<double>(-0.388889,0.096225) ; EXPECT_EQ(FFT1,auxFFT); transformer1.cleanup(); }
// local variable declartion vector<string> CodeGenerator::varDecl(vector<Node>::iterator& it) { vector<string> varDeclCode; stringstream line; it = it + 2; string type = it->symbol; // save the Type it = it + 2; string id = it->symbol; // save the id it = it + 2; if (it->symbol == ";") { // variable line << "%" << id << " = alloca " <<typeCast(type) << "\n"; } else if (it->symbol == "[") { // array it = it + 2; line << "%" << id << " = alloca [" << it->symbol << " x " << typeCast(type) << "]\n"; } varDeclCode.push_back(line.str()); return varDeclCode; }
// global variable or function define vector<string> CodeGenerator::declaration(vector<Node>::iterator& it) { vector<string> declCode; it = it + 2; string type = it->symbol; // save the Type it = it + 2; string id = it->symbol; it = it + 2; stringstream line; if (it->symbol == "VarDecl'") { // global variable/array declaration it++; if (it->symbol == ";") { // global variable if (type == "int") line << "@" << id << " = global "<< typeCast(type)<<" 0\n"; else if (type == "double") line << "@" << id << " = global "<< typeCast(type) << " 0.000000e+00\n"; else if (type == "char") line << "@" << id << " = global "<< typeCast(type)<<" 0\n"; } else if (it->symbol == "[") { // global array it = it + 2; line << "@" << id << " = global [" << it->symbol << " x " << typeCast(type) << "] zeroinitializer\n"; } } else if (it->symbol == "FunDecl") { // function declaration it = it + 3; if (it->symbol == "epsilon") // No parameters line << "define " << typeCast(type) << " @" << id << "() "; else { // with parameters line << "define " << typeCast(type) << " @" << id << "("; for (; it->symbol != ")"; it++) { if (it->symbol == "ParamDecl") { it = it + 2; line << typeCast(it->symbol) << " "; it = it + 2; line << "%" << it->symbol; } else if (it->symbol == ",") line << ","; } line << ")"; } } declCode.push_back(line.str()); return declCode; }
TEST( MultidimTest, typeCastComplex) { MultidimArray<std::complex <double> > mdTarget; MultidimArray<double> mSource(2,2); mSource(0,0) = 1; mSource(0,1) = 2; mSource(1,0) = 3; mSource(1,1) = 4; typeCast(mSource,mdTarget); EXPECT_EQ(DIRECT_MULTIDIM_ELEM(mSource, 0),DIRECT_MULTIDIM_ELEM(mdTarget,0).real()); EXPECT_EQ(DIRECT_MULTIDIM_ELEM(mSource, 1),DIRECT_MULTIDIM_ELEM(mdTarget,1).real()); EXPECT_EQ(DIRECT_MULTIDIM_ELEM(mSource, 2),DIRECT_MULTIDIM_ELEM(mdTarget,2).real()); EXPECT_EQ(DIRECT_MULTIDIM_ELEM(mSource, 3),DIRECT_MULTIDIM_ELEM(mdTarget,3).real()); EXPECT_EQ(0,DIRECT_MULTIDIM_ELEM(mdTarget,0).imag()) ; EXPECT_EQ(0,DIRECT_MULTIDIM_ELEM(mdTarget,1).imag()) ; EXPECT_EQ(0,DIRECT_MULTIDIM_ELEM(mdTarget,2).imag()) ; EXPECT_EQ(0,DIRECT_MULTIDIM_ELEM(mdTarget,3).imag()) ; }
vector<string> CodeGenerator::handleExpr(vector<Symbol> expr) { vector<string> exprCode; stringstream line; stack<Symbol> s; Symbol operand1, operand2, result; for (auto sym : expr) { if (sym.type != "op") { s.push(sym); } else { operand2 = s.top(); s.pop(); if (operand2.isFunction) { // TODO: handle expr in function } else if (operand2.isArray) { // TODO: handle expr in array } else if (operand2.type == "") { // it is constant operand2.isConstant = true; if (operand2.symbol.find(".", 0) == string::npos) { // it is // int operand2.type = "int"; instruction++; line << "%" << instruction << " = add i32 0, " << operand2.symbol << "\n"; exprCode.push_back(line.str()); line.str(""); operand2.symbol = "%" + to_string(instruction); } else { // need to cast to LLVM double type operand2.type = "double"; instruction++; line << "%" << instruction << " = fadd double 0.0, " << scientific << stod(operand2.symbol) << "\n"; exprCode.push_back(line.str()); line.str(""); operand2.symbol = "%" + to_string(instruction); } } else { // variable if (operand2.scope == 0) { // global variable instruction++; line << "%" << instruction << " = load " << typeCast(operand2.type) << "* @"<<operand2.symbol<<"\n"; exprCode.push_back(line.str()); line.str(""); operand2.symbol = "%" + to_string(instruction); } else { // local variable instruction++; line << "%" << instruction << " = load " << typeCast(operand2.type) << "* %" << operand2.symbol << "\n"; exprCode.push_back(line.str()); line.str(""); operand2.symbol = "%" + to_string(instruction); } } operand1 = s.top(); s.pop(); if (operand1.isFunction) { // TODO: handle expr in function } else if (operand1.isArray) { // TODO: handle expr in array } else if (operand1.type == "") { // it is constant operand1.isConstant = true; if (operand1.symbol.find(".", 0) == string::npos) { // it is // int operand1.type = "int"; instruction++; line << "%" << instruction << " = add i32 0, " << operand1.symbol << "\n"; exprCode.push_back(line.str()); line.str(""); operand1.symbol = "%" + to_string(instruction); } else { operand1.type = "double"; // need to cast to LLVM double type instruction++; line << "%" << instruction << " = fadd double 0.0, " << scientific << stod(operand1.symbol) << "\n"; exprCode.push_back(line.str()); line.str(""); operand1.symbol = "%" + to_string(instruction); } } else if (sym.symbol != "=") { // variable if (operand1.scope == 0) { // global variable instruction++; line << "%" << instruction << " = load " << typeCast(operand1.type) << "* @" << operand1.symbol << "\n"; exprCode.push_back(line.str()); line.str(""); operand1.symbol = "%" + to_string(instruction); } else { // local variable instruction++; line << "%" << instruction << " = load " << typeCast(operand1.type) << "* %" << operand1.symbol << "\n"; exprCode.push_back(line.str()); line.str(""); operand1.symbol = "%" + to_string(instruction); } } // type conversion if needed if (operand1.type != operand2.type && sym.symbol != "=") { if (operand1.type == "int") { // operand1 type conversion instruction++; line << "%" << instruction << " = sitofp i32 " << operand1.symbol <<" to double\n"; exprCode.push_back(line.str()); line.str(""); operand1.symbol = "%" + to_string(instruction); operand1.type = "double"; } else if (operand2.type == "int") { // operand2 type conversion instruction++; line << "%" << instruction << " = sitofp i32 " << operand2.symbol <<" to double\n"; exprCode.push_back(line.str()); line.str(""); operand2.symbol = "%" + to_string(instruction); operand2.type = "double"; } } instruction++; // cout << "Expr: " << operand1.symbol << "\t" << sym.symbol << "\t" // << operand2.symbol << endl; if (sym.symbol == "+") { if (operand1.type == "int") { line << "%" << instruction << " = add nsw i32 " << operand1.symbol << ", " << operand2.symbol << "\n"; exprCode.push_back(line.str()); line.str(""); result.symbol = "%" + to_string(instruction); result.type = "int"; } else if (operand1.type == "double") { line << "%" << instruction << " = fadd double " << operand1.symbol <<", " << operand2.symbol << "\n"; exprCode.push_back(line.str()); line.str(""); result.symbol = "%" + to_string(instruction); result.type = "double"; } } else if (sym.symbol == "-") { if (operand1.type == "int") { line << "%" << instruction << " = sub nsw i32 " << operand1.symbol << ", " << operand2.symbol << "\n"; exprCode.push_back(line.str()); line.str(""); result.symbol = "%" + to_string(instruction); result.type = "int"; } else if (operand1.type == "double") { line << "%" << instruction << " = fsub double " << operand1.symbol << ", " << operand2.symbol <<"\n"; exprCode.push_back(line.str()); line.str(""); result.symbol = "%" + to_string(instruction); result.type = "double"; } } else if (sym.symbol == "*") { if (operand1.type == "int") { line << "%" << instruction << " = mul nsw i32 " << operand1.symbol << ", " << operand2.symbol << "\n"; exprCode.push_back(line.str()); line.str(""); result.symbol = "%" + to_string(instruction); result.type = "int"; } else if (operand1.type == "double") { line << "%" << instruction << " = fmul double " << operand1.symbol << ", " << operand2.symbol << "\n"; exprCode.push_back(line.str()); line.str(""); result.symbol = "%" + to_string(instruction); result.type = "double"; } } else if (sym.symbol == "/") { if (operand1.type == "int") { line << "%" << instruction << " = fsub double " << operand1.symbol << ", " << operand2.symbol << "\n"; exprCode.push_back(line.str()); line.str(""); result.symbol = "%" + to_string(instruction); result.type = "double"; } } else if (sym.symbol == "*") { if (operand1.type == "int") { line << "%" << instruction << " = mul nsw i32 " << operand1.symbol << ", " << operand2.symbol << "\n"; exprCode.push_back(line.str()); line.str(""); result.symbol = "%" + to_string(instruction); result.type = "int"; } else if (operand1.type == "double") { line << "%" << instruction << " = fmul double " << operand1.symbol << ", " << operand2.symbol << "\n"; exprCode.push_back(line.str()); line.str(""); result.symbol = "%" + to_string(instruction); result.type = "double"; } } else if (sym.symbol == "/") { if (operand1.type == "int") { line << "%" << instruction << " = sdiv i32 " << operand1.symbol << ", " << operand2.symbol << "\n"; exprCode.push_back(line.str()); line.str(""); result.symbol = "%" + to_string(instruction); result.type = "int"; } else if (operand1.type == "double") { line << "%" << instruction << " = fdiv double " << operand1.symbol << ", " << operand2.symbol << "\n"; exprCode.push_back(line.str()); line.str(""); result.symbol = "%" + to_string(instruction); result.type = "double"; } } else if (sym.symbol == "==") { if (operand1.type == "int") { line << "%" << instruction << " = icmp eq i32 " << operand1.symbol << ", " << operand2.symbol << "\n"; exprCode.push_back(line.str()); line.str(""); result.symbol = "%" + to_string(instruction); result.type = "int"; } else if (operand1.type == "double") { line << "%" << instruction << " = fcmp oeq double " << operand1.symbol << ", " << operand2.symbol << "\n"; exprCode.push_back(line.str()); line.str(""); result.symbol = "%" + to_string(instruction); result.type = "double"; } } else if (sym.symbol == "!=") { if (operand1.type == "int") { line << "%" << instruction << " = icmp ne i32 " << operand1.symbol << ", " << operand2.symbol << "\n"; exprCode.push_back(line.str()); line.str(""); result.symbol = "%" + to_string(instruction); result.type = "int"; } else if (operand1.type == "double") { line << "%" << instruction << " = fcmp one double " << operand1.symbol << ", " << operand2.symbol << "\n"; exprCode.push_back(line.str()); line.str(""); result.symbol = "%" + to_string(instruction); result.type = "double"; } } else if (sym.symbol == "<") { if (operand1.type == "int") { line << "%" << instruction << " = icmp slt i32 " << operand1.symbol << ", " << operand2.symbol << "\n"; exprCode.push_back(line.str()); line.str(""); result.symbol = "%" + to_string(instruction); result.type = "int"; } else if (operand1.type == "double") { line << "%" << instruction << " = fcmp olt double " << operand1.symbol << ", " << operand2.symbol << "\n"; exprCode.push_back(line.str()); line.str(""); result.symbol = "%" + to_string(instruction); result.type = "double"; } } else if (sym.symbol == "<=") { if (operand1.type == "int") { line << "%" << instruction << " = icmp sle i32 " << operand1.symbol << ", " << operand2.symbol << "\n"; exprCode.push_back(line.str()); line.str(""); result.symbol = "%" + to_string(instruction); result.type = "int"; } else if (operand1.type == "double") { line << "%" << instruction << " = fcmp ole double " << operand1.symbol << ", " << operand2.symbol << "\n"; exprCode.push_back(line.str()); line.str(""); result.symbol = "%" + to_string(instruction); result.type = "double"; } } else if (sym.symbol == ">") { if (operand1.type == "int") { line << "%" << instruction << " = icmp sgt i32 " << operand1.symbol << ", " << operand2.symbol << "\n"; exprCode.push_back(line.str()); line.str(""); result.symbol = "%" + to_string(instruction); result.type = "int"; } else if (operand1.type == "double") { line << "%" << instruction << " = fcmp ogt double " << operand1.symbol << ", " << operand2.symbol << "\n"; exprCode.push_back(line.str()); line.str(""); result.symbol = "%" + to_string(instruction); result.type = "double"; } } else if (sym.symbol == ">=") { if (operand1.type == "int") { line << "%" << instruction << " = icmp sge i32 " << operand1.symbol << ", " << operand2.symbol << "\n"; exprCode.push_back(line.str()); line.str(""); result.symbol = "%" + to_string(instruction); result.type = "int"; } else if (operand1.type == "double") { line << "%" << instruction << " = fcmp oge double " << operand1.symbol << ", " << operand2.symbol << "\n"; exprCode.push_back(line.str()); line.str(""); result.symbol = "%" + to_string(instruction); result.type = "double"; } } else if (sym.symbol == "&&") { line << "%" << instruction << " = and i32 " << operand1.symbol << ", " << operand2.symbol << "\n"; exprCode.push_back(line.str()); line.str(""); result.symbol = "%" + to_string(instruction); result.type = "int"; } else if (sym.symbol == "||") { line << "%" << instruction << " = or i32 " << operand1.symbol << ", " << operand2.symbol << "\n"; exprCode.push_back(line.str()); line.str(""); result.symbol = "%" + to_string(instruction); result.type = "int"; } else if (sym.symbol == "=") { if (operand1.type != operand2.type) { //type conversion if (operand1.type == "int") { line << "%" << instruction << " = fptosi double " << operand2.symbol << " to i32" << "\n"; exprCode.push_back(line.str()); line.str(""); operand2.symbol = "%" + to_string(instruction); } else if (operand1.type == "double") { line << "%" << instruction << " = sitofp i32 " << operand2.symbol << " to double" << "\n"; exprCode.push_back(line.str()); line.str(""); operand2.symbol = "%" + to_string(instruction); } } else instruction--; if (operand1.scope == 0) line << "store " << typeCast(operand1.type) << " " << operand2.symbol << ", " << typeCast(operand1.type) << "* @" << operand1.symbol << "\n"; else line << "store " << typeCast(operand1.type) << " " << operand2.symbol << ", " << typeCast(operand1.type) << "* %" << operand1.symbol << "\n"; exprCode.push_back(line.str()); line.str(""); } s.push(result); } } return exprCode; }