1/* Copyright (c) 2012 Massachusetts Institute of Technology 2 * 3 * Permission is hereby granted, free of charge, to any person obtaining a copy 4 * of this software and associated documentation files (the "Software"), to deal 5 * in the Software without restriction, including without limitation the rights 6 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 * copies of the Software, and to permit persons to whom the Software is 8 * furnished to do so, subject to the following conditions: 9 * 10 * The above copyright notice and this permission notice shall be included in 11 * all copies or substantial portions of the Software. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 * THE SOFTWARE. 20 */ 21 22#include "util/Result.h" 23 24#include <iostream> 25 26#include "libutil/Log.h" 27#include "libutil/Assert.h" 28 29namespace DSENT 30{ 31 using std::ostream; 32 using std::endl; 33 34 Result::SubResult::SubResult(const Result* sub_result_, const String& producer_, double num_results_) 35 : m_result_(sub_result_), m_producer_(producer_), m_num_results_(num_results_) 36 { 37 // Check if the result is not a null pointer 38 ASSERT((sub_result_ != NULL), "Internal error: sub_result_ is null"); 39 40 // Check if the number of results greater than 0 41 ASSERT((num_results_ >= 0), "Internal error: num_results_ (" + String(num_results_) + ") is less than 0"); 42 } 43 44 Result::SubResult::~SubResult() 45 {} 46 47 const Result* Result::SubResult::getResult() const 48 { 49 return m_result_; 50 } 51 52 const String& Result::SubResult::getProducer() const 53 { 54 return m_producer_; 55 } 56 57 double Result::SubResult::getNumResults() const 58 { 59 return m_num_results_; 60 } 61 62 Result::SubResult* Result::SubResult::clone() const 63 { 64 return new SubResult(*this); 65 } 66 67 Result::SubResult::SubResult(const SubResult& sub_result_) 68 : m_result_(sub_result_.m_result_), m_producer_(sub_result_.m_producer_), m_num_results_(sub_result_.m_num_results_) 69 {} 70 71 Result::Result() 72 {} 73 74 Result::Result(const String& result_name_) 75 : m_result_name_(result_name_) 76 {} 77 78 Result::~Result() 79 { 80 // Clear all sub results 81 for(vector<SubResult*>::iterator it = m_sub_results_.begin(); 82 it != m_sub_results_.end(); ++it) 83 { 84 SubResult* sub_result = (*it); 85 delete sub_result; 86 } 87 } 88 89 const String& Result::getName() const 90 { 91 return m_result_name_; 92 } 93 94 void Result::setValue(double /* value_ */) 95 { 96 throw LibUtil::Exception("[Error] " + getName() + " -> Cannot set the value of a non-atomic result!"); 97 return; 98 } 99 100 void Result::addValue(double /* value_ */) 101 { 102 throw LibUtil::Exception("[Error] " + getName() + 103 " -> Cannot add the value of a non-atomic result"); 104 return; 105 } 106 107 double Result::getValue() const 108 { 109 throw LibUtil::Exception("[Error] " + getName() + " -> Cannot get the value of a non-atomic result!"); 110 return 0.0; 111 } 112 113 void Result::addSubResult(const Result* sub_result_, const String& result_producer_, double num_results_) 114 { 115 SubResult* new_sub_result = new SubResult(sub_result_, result_producer_, num_results_); 116 m_sub_results_.push_back(new_sub_result); 117 return; 118 } 119 120 void Result::removeAllSubResults() 121 { 122 // Clear all sub results 123 for(vector<SubResult*>::iterator it = m_sub_results_.begin(); 124 it != m_sub_results_.end(); ++it) 125 { 126 SubResult* sub_result = (*it); 127 delete sub_result; 128 } 129 m_sub_results_.clear(); 130 return; 131 } 132 133 double Result::calculateSum() const 134 { 135 double sum = 0.0; 136 137 // Loop through all sub results and calculate the sum 138 for(vector<SubResult*>::const_iterator it = m_sub_results_.begin(); 139 it != m_sub_results_.end(); ++it) 140 { 141 const SubResult* temp_sub_result = (*it); 142 const Result* temp_result = temp_sub_result->getResult(); 143 double num_results = temp_sub_result->getNumResults(); 144 sum += temp_result->calculateSum()*num_results; 145 } 146 return sum; 147 } 148 149 void Result::print(const String& prepend_str_, int detail_level_, ostream& ost_) const 150 { 151 print(prepend_str_, 1.0, detail_level_, ost_); 152 return; 153 } 154 155 Result* Result::clone() const 156 { 157 return new Result(*this); 158 } 159 160 Result::Result(const Result& result_) 161 { 162 // Copy the result name 163 m_result_name_ = result_.m_result_name_; 164 165 // Clone all sub results 166 for(vector<SubResult*>::const_iterator it = m_sub_results_.begin(); 167 it != m_sub_results_.end(); ++it) 168 { 169 const SubResult* temp_sub_result = (*it); 170 SubResult* new_sub_result = temp_sub_result->clone(); 171 m_sub_results_.push_back(new_sub_result); 172 } 173 } 174 175 void Result::print(const String& prepend_str_, double num_results_, int detail_level_, ostream& ost_) const 176 { 177 // Go down to lower level if detail_level_ > 0, else print the sthe sthe sthe sum 178 if(detail_level_ > 0) 179 { 180 for(vector<SubResult*>::const_iterator it = m_sub_results_.begin(); 181 it != m_sub_results_.end(); ++it) 182 { 183 const SubResult* temp_sub_result = (*it); 184 const Result* temp_result = temp_sub_result->getResult(); 185 const String& temp_producer = temp_sub_result->getProducer(); 186 const String& temp_result_name = temp_result->getName(); 187 double temp_num_results = temp_sub_result->getNumResults(); 188 String temp_prepend_str = prepend_str_ + "->" + temp_producer; 189 190 if(!temp_result_name.empty()) 191 { 192 temp_prepend_str += ":" + temp_result_name; 193 } 194 temp_result->print(temp_prepend_str, num_results_*temp_num_results, detail_level_ - 1, ost_); 195 } 196 } 197 else 198 { 199 ost_ << prepend_str_ << " = " << calculateSum()*num_results_; 200 ost_ << " (" << calculateSum() << " * " << num_results_ << ")" << endl; 201 } 202 return; 203 } 204 205 void Result::printHierarchy(const String& prepend_str_, int detail_level_, ostream& ost_) const 206 { 207 if(detail_level_ > 0) 208 { 209 for(vector<SubResult*>::const_iterator it = m_sub_results_.begin(); it != m_sub_results_.end(); ++it) 210 { 211 const SubResult* temp_sub_result = (*it); 212 const Result* temp_result = temp_sub_result->getResult(); 213 const String& temp_producer = temp_sub_result->getProducer(); 214 const String& temp_result_name = temp_result->getName(); 215 String temp_prepend_str = prepend_str_ + " "; 216 217 ost_ << prepend_str_ << " |--" << temp_producer << "->" << temp_result_name << endl; 218 219 temp_result->printHierarchy(temp_prepend_str, detail_level_ - 1, ost_); 220 } 221 } 222 return; 223 } 224 225 AtomicResult::AtomicResult(const String& result_name_, double value_) 226 : Result(result_name_), m_value_(value_) 227 {} 228 229 AtomicResult::~AtomicResult() 230 {} 231 232 void AtomicResult::setValue(double value_) 233 { 234 m_value_ = value_; 235 return; 236 } 237 238 void AtomicResult::addValue(double value_) 239 { 240 m_value_ += value_; 241 return; 242 } 243 244 double AtomicResult::getValue() const 245 { 246 return m_value_; 247 } 248 249 double AtomicResult::calculateSum() const 250 { 251 return m_value_; 252 } 253 254 AtomicResult* AtomicResult::clone() const 255 { 256 return new AtomicResult(*this); 257 } 258 259 AtomicResult::AtomicResult(const AtomicResult& atomic_result_) 260 : Result(atomic_result_), m_value_(atomic_result_.m_value_) 261 {} 262 263 void AtomicResult::print(const String& prepend_str_, double num_results_, int /* detail_level_ */, ostream& ost_) const 264 { 265 ost_ << prepend_str_ << " = " << m_value_*num_results_; 266 ost_ << " (" << m_value_ << " * " << num_results_ << ")" << endl; 267 return; 268 } 269} // namespace DSENT 270 271