blas_parser.cc

00001 /***************************************************************************
00002  *  PSIMRCC : Copyright (C) 2007 by Francesco Evangelista and Andrew Simmonett
00003  *  frank@ccc.uga.edu   andysim@ccc.uga.edu
00004  *  A multireference coupled cluster code
00005  ***************************************************************************/
00006 
00007 #include "moinfo.h"
00008 #include "blas.h"
00009 #include "debugging.h"
00010 #include "utilities.h"
00011 #include <algorithm>
00012 
00013 namespace psi{ namespace psimrcc{
00014 
00015 typedef std::vector<std::string>            strvec;
00016 typedef std::vector<std::pair<int,int> >    intpairvec;
00017 
00018 bool is_number(const std::string& str);
00019 double get_number(const std::string& str);
00020 bool is_operation(const std::string& str);
00021 
00022 // Parsing Algorithm
00023 int CCBLAS::parse(std::string& str){
00024 
00025   int noperations_added = 0;
00026   // Split the operation
00027   strvec split_str = split(str);
00028 
00029   // Define the allowed operations
00030   strvec allowed_assignments = split("= += >= +>=");
00031 
00032   // Store the A Matrix
00033   CCMatrix* A_Matrix = get_Matrix(split_str[0],str);
00034   // Check the assigment operator
00035   string assignment(split_str[1]);
00036   strvec::iterator strveciter(find(allowed_assignments.begin(),allowed_assignments.end(),assignment));
00037   if(strveciter==allowed_assignments.end())
00038     fprintf(outfile,"\n\nCCBLAS::parse() %s is not a proper assigment\n\nin the expression:\n\t%s\n\n",assignment.c_str(),str.c_str());
00039 
00040   // Eliminate the first two strings and store the rest of the terms
00041   strvec::iterator iter = split_str.begin();
00042   iter=split_str.erase(iter,iter+2);
00043   string    reindexing;
00044   string    operation;
00045   CCMatrix* B_Matrix;
00046   CCMatrix* C_Matrix;
00047 
00048   while(iter!=split_str.end()){
00049     double factor=1.0;
00050     C_Matrix = NULL;
00051     B_Matrix = NULL;
00052     // Read the reindexing
00053     if(iter->find("#")!=string::npos){
00054       reindexing = *iter;
00055       reindexing = reindexing.substr(1,reindexing.size()-2);
00056       ++iter;
00057     }
00058     // Read a product of numerical factors
00059     while((iter!=split_str.end()) && get_factor(*iter,factor))
00060       ++iter;
00061     operation="add_factor";
00062     // Read the first matrix
00063     if(iter!=split_str.end()){
00064       B_Matrix = get_Matrix(*iter,str);
00065       ++iter;
00066       // And eventually an operation and a matrix
00067       if(iter!=split_str.end()){
00068         if(is_operation(*iter)){
00069           // Check operation
00070           operation = *iter;
00071           ++iter;
00072           if(iter!=split_str.end()){
00073             C_Matrix = get_Matrix(*iter,str);
00074             ++iter;
00075           }
00076         }else{
00077           operation="plus";
00078         }
00079       }else{ // When you reach the end
00080         operation="plus";
00081       }
00082     }
00083     if(noperations_added && assignment[0]!='+')
00084       assignment= "+" + assignment;
00085     CCOperation op(factor,assignment,reindexing,operation,A_Matrix,B_Matrix,C_Matrix,work[0],buffer[0]);
00086     operations.push_back(op);
00087     noperations_added++;
00088     DEBUGGING(5,
00089       op.print();
00090     )
00091   }
00092   return(noperations_added);
00093 }
00094 
00095 bool CCBLAS::get_factor(const std::string& str,double& factor)
00096 {
00097   if(is_number(str)){
00098     factor *= get_number(str);
00099     return true;
00100   }
00101   if(str=="-"){
00102     factor *= -1.0;
00103     return true;
00104   }
00105   if(str=="+"){
00106     factor *= 1.0;
00107     return true;
00108   }
00109   if(str.substr(0,6)=="factor"){
00110     factor = get_scalar(str);
00111     return true;
00112   }
00113   return false;
00114 }
00115 
00116 bool is_number(const std::string& str){
00117   // Is the string str a number?
00118   static const string numbers = "1234567890.-+/e";
00119   bool numeric = true;
00120   for(int i=0;i<str.size();i++)
00121     if(numbers.find(str[i])==string::npos) numeric = false;
00122   // In case we have only a symbol (ex. "+")
00123   if((str.size()==1) && !isdigit(str[0])) numeric = false;
00124   return(numeric);
00125 }
00126 
00127 double get_number(const std::string& str){
00128   double value = 1.0;
00129   bool fraction = false;
00130   size_t fraction_sign;
00131   for(int i=0;i<str.size();i++)
00132     if(str[i]=='/'){
00133       fraction = true;
00134       fraction_sign = i;
00135     }
00136   if(fraction){
00137     string numerator   = str.substr(0,fraction_sign);
00138     string denominator = str.substr(fraction_sign+1,str.size()-fraction_sign-1);
00139     string unsigned_numerator = find_and_replace(numerator,"-","");
00140     if(unsigned_numerator.size() * denominator.size()!=0){
00141       value=ToDouble(numerator)/ToDouble(denominator);
00142     }else{
00143       fprintf(outfile,"\n\nSolve couldn't parse the numerical factor %s\n\n",str.c_str());
00144       fprintf(outfile,"\n\nCritical Breakdown of the Program. Blame the programmers!!!\n\n");
00145       fflush(outfile);
00146       exit(1);
00147     }
00148 
00149   }else{
00150     value=ToDouble(str);
00151   }
00152   return(value);
00153 }
00154 
00155 bool is_operation(const std::string& str){
00156   // Is the string str a number?
00157   strvec allowed_operations = split(". @ / * X");
00158   bool operation = false;
00159   for(int i=0;i<allowed_operations.size();i++)
00160     if(str.find(allowed_operations[i])!=string::npos) operation = true;
00161   return(operation);
00162 }
00163 
00164 
00165 // void split_index(const std::string& str,std::string& t2_label, int*& t2_indices,std::string& first_t1_label, int*& first_t1_indices,std::string& second_t1_label, int*& second_t1_indices)
00166 // {
00167 //   size_t opening = str.find_first_of("[");
00168 //   string index_str = str.substr(opening,8);
00169 // 
00170 //   size_t opening_ref = str.find_first_of("{");
00171 //   size_t closing_ref = str.find_first_of("}");
00172 //   string ref_str     = str.substr(opening_ref,closing_ref-opening_ref+1);
00173 // 
00174 //   intpairvec pairs;
00175 //   std::vector<char> labels;
00176 //   int index=0;
00177 //   for(int i=0;i<index_str.size();i++){
00178 //     if(index_str[i]=='o' || index_str[i]=='O' || index_str[i]=='v' || index_str[i]=='V') labels.push_back(index_str[i]);
00179 // 
00180 //     if(index_str[i]=='o') pairs.push_back(make_pair(0,index++));
00181 //     if(index_str[i]=='O') pairs.push_back(make_pair(1,index++));
00182 //     if(index_str[i]=='v') pairs.push_back(make_pair(2,index++));
00183 //     if(index_str[i]=='V') pairs.push_back(make_pair(3,index++));
00184 //   }
00185 //   sort(pairs.begin(),pairs.end());
00186 //   t2_label = "[";
00187 //   for(int i=0;i<index;i++){
00188 //     t2_indices[i]=pairs[i].second;
00189 //     t2_label += labels[t2_indices[i]];
00190 //     if(i==1)
00191 //       t2_label += "][";
00192 //   }
00193 //   t2_label += "]" + ref_str;
00194 // 
00195 //   first_t1_indices[0]=pairs[0].second;
00196 //   first_t1_indices[1]=pairs[2].second;
00197 //   second_t1_indices[0]=pairs[1].second;
00198 //   second_t1_indices[1]=pairs[3].second;
00199 //   first_t1_label = "[";
00200 //   second_t1_label = "[";
00201 //   for(int i=0;i<2;i++){
00202 //     first_t1_label += labels[first_t1_indices[i]];
00203 //     second_t1_label += labels[second_t1_indices[i]];
00204 //     if(i==0){
00205 //       first_t1_label += "][";
00206 //       second_t1_label += "][";
00207 //     }
00208 //   }
00209 //   first_t1_label += "]" + ref_str;
00210 //   second_t1_label += "]" + ref_str;
00211 // 
00212 // //   if(moinfo->get_debug()>7){
00213 // //     printf("\n\nInput string : %s",str.c_str());
00214 // //     printf("\n\nIndex string : %s + %s + %s",t2_label.c_str(),first_t1_label.c_str(),second_t1_label.c_str());
00215 // //   }
00216 // }
00217 
00218 
00219 
00220 
00221 }} /* End Namespaces */

Generated on Wed Feb 13 16:35:39 2008 for PSI by  doxygen 1.5.4