| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "courgette/adjustment_method.h" | 5 #include "courgette/adjustment_method.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <list> | 9 #include <list> |
| 10 #include <map> | 10 #include <map> |
| 11 #include <set> | 11 #include <set> |
| 12 #include <string> | 12 #include <string> |
| 13 #include <vector> | 13 #include <vector> |
| 14 | 14 |
| 15 #include <iostream> | |
| 16 | |
| 17 #include "base/basictypes.h" | 15 #include "base/basictypes.h" |
| 18 #include "base/format_macros.h" | 16 #include "base/format_macros.h" |
| 19 #include "base/logging.h" | 17 #include "base/logging.h" |
| 20 #include "base/string_util.h" | 18 #include "base/string_util.h" |
| 21 #include "base/time.h" | 19 #include "base/time.h" |
| 22 | 20 |
| 23 #include "courgette/assembly_program.h" | 21 #include "courgette/assembly_program.h" |
| 24 #include "courgette/courgette.h" | 22 #include "courgette/courgette.h" |
| 25 #include "courgette/encoded_program.h" | 23 #include "courgette/encoded_program.h" |
| 26 #include "courgette/image_info.h" | 24 #include "courgette/image_info.h" |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 146 this pattern, then there is no competing evidence and we go ahead with the | 144 this pattern, then there is no competing evidence and we go ahead with the |
| 147 assignment immediately. This produces slightly better results because these | 145 assignment immediately. This produces slightly better results because these |
| 148 cases tend to be low-scoring and susceptible to small mistakes made in | 146 cases tend to be low-scoring and susceptible to small mistakes made in |
| 149 low-scoring assignments in the approximation for large equivalence classes. | 147 low-scoring assignments in the approximation for large equivalence classes. |
| 150 | 148 |
| 151 */ | 149 */ |
| 152 | 150 |
| 153 namespace courgette { | 151 namespace courgette { |
| 154 namespace adjustment_method_2 { | 152 namespace adjustment_method_2 { |
| 155 | 153 |
| 156 // We have three discretionary information logging levels for algorithm | |
| 157 // development. For now just configure with #defines. | |
| 158 // TODO(sra): make dependent of some configurable setting. | |
| 159 struct LogToCout { | |
| 160 LogToCout() {} | |
| 161 ~LogToCout() { std::cout << std::endl; } | |
| 162 std::ostream& stream() { return std::cout; } | |
| 163 }; | |
| 164 #define LOG_TO_COUT (LogToCout().stream()) | |
| 165 #define NO_LOG DLOG_IF(INFO, false) | |
| 166 | |
| 167 #if 0 // Log to log file. | |
| 168 #define ALOG1 LOG(INFO) | |
| 169 #define ALOG2 LOG(INFO) | |
| 170 #define ALOG3 LOG(INFO) | |
| 171 #elif 0 // Log to stdout. | |
| 172 #define ALOG1 LOG_TO_COUT | |
| 173 #define ALOG2 LOG_TO_COUT | |
| 174 #define ALOG3 LOG_TO_COUT | |
| 175 #else // Log to nowhere. | |
| 176 #define ALOG1 NO_LOG | |
| 177 #define ALOG2 NO_LOG | |
| 178 #define ALOG3 NO_LOG | |
| 179 #endif | |
| 180 | |
| 181 //////////////////////////////////////////////////////////////////////////////// | 154 //////////////////////////////////////////////////////////////////////////////// |
| 182 | 155 |
| 183 class AssignmentCandidates; | 156 class AssignmentCandidates; |
| 184 class LabelInfoMaker; | 157 class LabelInfoMaker; |
| 185 class Shingle; | 158 class Shingle; |
| 186 class ShinglePattern; | 159 class ShinglePattern; |
| 187 | 160 |
| 188 // The purpose of adjustment is to assign indexes to Labels of a program 'p' to | 161 // The purpose of adjustment is to assign indexes to Labels of a program 'p' to |
| 189 // make the sequence of indexes similar to a 'model' program 'm'. Labels | 162 // make the sequence of indexes similar to a 'model' program 'm'. Labels |
| 190 // themselves don't have enough information to do this job, so we work with a | 163 // themselves don't have enough information to do this job, so we work with a |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 341 ++p) { | 314 ++p) { |
| 342 if (p->second != 0) | 315 if (p->second != 0) |
| 343 Update(p->first, p->second); | 316 Update(p->first, p->second); |
| 344 else | 317 else |
| 345 ++zeroes; | 318 ++zeroes; |
| 346 } | 319 } |
| 347 pending_updates_.clear(); | 320 pending_updates_.clear(); |
| 348 } | 321 } |
| 349 | 322 |
| 350 void Print(int max) { | 323 void Print(int max) { |
| 351 ALOG1 << "score " << TopScore() << " " << ToString(program_info_) | 324 VLOG(2) << "score " << TopScore() << " " << ToString(program_info_) |
| 352 << " := ?"; | 325 << " := ?"; |
| 353 if (!pending_updates_.empty()) | 326 if (!pending_updates_.empty()) |
| 354 ALOG1 << pending_updates_.size() << " pending"; | 327 VLOG(2) << pending_updates_.size() << " pending"; |
| 355 int count = 0; | 328 int count = 0; |
| 356 for (Queue::iterator q = queue_.begin(); q != queue_.end(); ++q) { | 329 for (Queue::iterator q = queue_.begin(); q != queue_.end(); ++q) { |
| 357 if (++count > max) break; | 330 if (++count > max) break; |
| 358 ALOG1 << " " << q->first << " " << ToString(q->second); | 331 VLOG(2) << " " << q->first << " " << ToString(q->second); |
| 359 } | 332 } |
| 360 } | 333 } |
| 361 | 334 |
| 362 private: | 335 private: |
| 363 typedef std::map<LabelInfo*, int, OrderLabelInfo> LabelToScore; | 336 typedef std::map<LabelInfo*, int, OrderLabelInfo> LabelToScore; |
| 364 typedef std::pair<int, LabelInfo*> ScoreAndLabel; | 337 typedef std::pair<int, LabelInfo*> ScoreAndLabel; |
| 365 struct OrderScoreAndLabelByScoreDecreasing { | 338 struct OrderScoreAndLabelByScoreDecreasing { |
| 366 OrderLabelInfo tie_breaker; | 339 OrderLabelInfo tie_breaker; |
| 367 bool operator()(const ScoreAndLabel& a, const ScoreAndLabel& b) const { | 340 bool operator()(const ScoreAndLabel& a, const ScoreAndLabel& b) const { |
| 368 if (a.first > b.first) return true; | 341 if (a.first > b.first) return true; |
| (...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 821 | 794 |
| 822 DISALLOW_COPY_AND_ASSIGN(VariableQueue); | 795 DISALLOW_COPY_AND_ASSIGN(VariableQueue); |
| 823 }; | 796 }; |
| 824 | 797 |
| 825 | 798 |
| 826 class AssignmentProblem { | 799 class AssignmentProblem { |
| 827 public: | 800 public: |
| 828 AssignmentProblem(const Trace& trace, size_t model_end) | 801 AssignmentProblem(const Trace& trace, size_t model_end) |
| 829 : trace_(trace), | 802 : trace_(trace), |
| 830 model_end_(model_end) { | 803 model_end_(model_end) { |
| 831 ALOG1 << "AssignmentProblem::AssignmentProblem " << model_end << ", " | 804 VLOG(2) << "AssignmentProblem::AssignmentProblem " << model_end << ", " |
| 832 << trace.size(); | 805 << trace.size(); |
| 833 } | 806 } |
| 834 | 807 |
| 835 bool Solve() { | 808 bool Solve() { |
| 836 if (model_end_ < Shingle::kWidth || | 809 if (model_end_ < Shingle::kWidth || |
| 837 trace_.size() - model_end_ < Shingle::kWidth) { | 810 trace_.size() - model_end_ < Shingle::kWidth) { |
| 838 // Nothing much we can do with such a short problem. | 811 // Nothing much we can do with such a short problem. |
| 839 return true; | 812 return true; |
| 840 } | 813 } |
| 841 instances_.resize(trace_.size() - Shingle::kWidth + 1, NULL); | 814 instances_.resize(trace_.size() - Shingle::kWidth + 1, NULL); |
| 842 AddShingles(0, model_end_); | 815 AddShingles(0, model_end_); |
| 843 AddShingles(model_end_, trace_.size()); | 816 AddShingles(model_end_, trace_.size()); |
| 844 InitialClassify(); | 817 InitialClassify(); |
| 845 AddPatternsNeedingUpdatesToQueues(); | 818 AddPatternsNeedingUpdatesToQueues(); |
| 846 | 819 |
| 847 patterns_needing_updates_.clear(); | 820 patterns_needing_updates_.clear(); |
| 848 while (FindAndAssignBestLeader()) { | 821 while (FindAndAssignBestLeader()) |
| 849 NO_LOG << "Updated " << patterns_needing_updates_.size() << " patterns"; | |
| 850 patterns_needing_updates_.clear(); | 822 patterns_needing_updates_.clear(); |
| 851 } | |
| 852 PrintActivePatterns(); | 823 PrintActivePatterns(); |
| 853 | 824 |
| 854 return true; | 825 return true; |
| 855 } | 826 } |
| 856 | 827 |
| 857 private: | 828 private: |
| 858 typedef std::set<Shingle*, Shingle::PointerLess> ShingleSet; | 829 typedef std::set<Shingle*, Shingle::PointerLess> ShingleSet; |
| 859 | 830 |
| 860 typedef std::set<const ShinglePattern*, ShinglePatternPointerLess> | 831 typedef std::set<const ShinglePattern*, ShinglePatternPointerLess> |
| 861 ShinglePatternSet; | 832 ShinglePatternSet; |
| 862 | 833 |
| 863 // Patterns are partitioned into the following sets: | 834 // Patterns are partitioned into the following sets: |
| 864 | 835 |
| 865 // * Retired patterns (not stored). No shingles exist for this pattern (they | 836 // * Retired patterns (not stored). No shingles exist for this pattern (they |
| 866 // all now match more specialized patterns). | 837 // all now match more specialized patterns). |
| 867 // * Useless patterns (not stored). There are no 'program' shingles for this | 838 // * Useless patterns (not stored). There are no 'program' shingles for this |
| 868 // pattern (they all now match more specialized patterns). | 839 // pattern (they all now match more specialized patterns). |
| 869 // * Single-use patterns - single_use_pattern_queue_. | 840 // * Single-use patterns - single_use_pattern_queue_. |
| 870 // * Other patterns - active_non_single_use_patterns_ / variable_queue_. | 841 // * Other patterns - active_non_single_use_patterns_ / variable_queue_. |
| 871 | 842 |
| 872 typedef std::set<const ShinglePattern*, | 843 typedef std::set<const ShinglePattern*, |
| 873 OrderShinglePatternByScoreDescending<&SingleUseScore> > | 844 OrderShinglePatternByScoreDescending<&SingleUseScore> > |
| 874 SingleUsePatternQueue; | 845 SingleUsePatternQueue; |
| 875 | 846 |
| 876 void PrintPatternsHeader() const { | 847 void PrintPatternsHeader() const { |
| 877 ALOG1 << shingle_instances_.size() << " instances " | 848 VLOG(2) << shingle_instances_.size() << " instances " |
| 878 << trace_.size() << " trace length " | 849 << trace_.size() << " trace length " |
| 879 << patterns_.size() << " shingle indexes " | 850 << patterns_.size() << " shingle indexes " |
| 880 << single_use_pattern_queue_.size() << " single use patterns " | 851 << single_use_pattern_queue_.size() << " single use patterns " |
| 881 << active_non_single_use_patterns_.size() << " active patterns"; | 852 << active_non_single_use_patterns_.size() << " active patterns"; |
| 882 } | 853 } |
| 883 | 854 |
| 884 void PrintActivePatterns() const { | 855 void PrintActivePatterns() const { |
| 885 for (ShinglePatternSet::const_iterator p = | 856 for (ShinglePatternSet::const_iterator p = |
| 886 active_non_single_use_patterns_.begin(); | 857 active_non_single_use_patterns_.begin(); |
| 887 p != active_non_single_use_patterns_.end(); | 858 p != active_non_single_use_patterns_.end(); |
| 888 ++p) { | 859 ++p) { |
| 889 const ShinglePattern* pattern = *p; | 860 const ShinglePattern* pattern = *p; |
| 890 ALOG1 << ToString(pattern, 10); | 861 VLOG(2) << ToString(pattern, 10); |
| 891 } | 862 } |
| 892 } | 863 } |
| 893 | 864 |
| 894 void PrintPatterns() const { | 865 void PrintPatterns() const { |
| 895 PrintAllPatterns(); | 866 PrintAllPatterns(); |
| 896 PrintActivePatterns(); | 867 PrintActivePatterns(); |
| 897 PrintAllShingles(); | 868 PrintAllShingles(); |
| 898 } | 869 } |
| 899 | 870 |
| 900 void PrintAllPatterns() const { | 871 void PrintAllPatterns() const { |
| 901 for (IndexToPattern::const_iterator p = patterns_.begin(); | 872 for (IndexToPattern::const_iterator p = patterns_.begin(); |
| 902 p != patterns_.end(); | 873 p != patterns_.end(); |
| 903 ++p) { | 874 ++p) { |
| 904 const ShinglePattern& pattern = p->second; | 875 const ShinglePattern& pattern = p->second; |
| 905 ALOG1 << ToString(&pattern, 10); | 876 VLOG(2) << ToString(&pattern, 10); |
| 906 } | 877 } |
| 907 } | 878 } |
| 908 | 879 |
| 909 void PrintAllShingles() const { | 880 void PrintAllShingles() const { |
| 910 for (Shingle::OwningSet::const_iterator p = shingle_instances_.begin(); | 881 for (Shingle::OwningSet::const_iterator p = shingle_instances_.begin(); |
| 911 p != shingle_instances_.end(); | 882 p != shingle_instances_.end(); |
| 912 ++p) { | 883 ++p) { |
| 913 const Shingle& instance = *p; | 884 const Shingle& instance = *p; |
| 914 ALOG1 << ToString(&instance) << " " << ToString(instance.pattern()); | 885 VLOG(2) << ToString(&instance) << " " << ToString(instance.pattern()); |
| 915 } | 886 } |
| 916 } | 887 } |
| 917 | 888 |
| 918 | 889 |
| 919 void AddShingles(size_t begin, size_t end) { | 890 void AddShingles(size_t begin, size_t end) { |
| 920 for (size_t i = begin; i + Shingle::kWidth - 1 < end; ++i) { | 891 for (size_t i = begin; i + Shingle::kWidth - 1 < end; ++i) { |
| 921 instances_[i] = Shingle::Find(trace_, i, &shingle_instances_); | 892 instances_[i] = Shingle::Find(trace_, i, &shingle_instances_); |
| 922 } | 893 } |
| 923 } | 894 } |
| 924 | 895 |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1086 const Shingle* program_instance = program_freq.instance(); | 1057 const Shingle* program_instance = program_freq.instance(); |
| 1087 | 1058 |
| 1088 // int score = p1; // ? weigh all equally?? | 1059 // int score = p1; // ? weigh all equally?? |
| 1089 int score = std::min(p1, m1); | 1060 int score = std::min(p1, m1); |
| 1090 | 1061 |
| 1091 for (size_t i = 0; i < Shingle::kWidth; ++i) { | 1062 for (size_t i = 0; i < Shingle::kWidth; ++i) { |
| 1092 LabelInfo* program_info = program_instance->at(i); | 1063 LabelInfo* program_info = program_instance->at(i); |
| 1093 LabelInfo* model_info = model_instance->at(i); | 1064 LabelInfo* model_info = model_instance->at(i); |
| 1094 if ((model_info->assignment_ == NULL) != | 1065 if ((model_info->assignment_ == NULL) != |
| 1095 (program_info->assignment_ == NULL)) { | 1066 (program_info->assignment_ == NULL)) { |
| 1096 ALOG1 << "ERROR " << i | 1067 VLOG(2) << "ERROR " << i |
| 1097 << "\n\t" << ToString(pattern, 10) | 1068 << "\n\t" << ToString(pattern, 10) |
| 1098 << "\n\t" << ToString(program_instance) | 1069 << "\n\t" << ToString(program_instance) |
| 1099 << "\n\t" << ToString(model_instance); | 1070 << "\n\t" << ToString(model_instance); |
| 1100 } | 1071 } |
| 1101 if (!program_info->assignment_ && !model_info->assignment_) { | 1072 if (!program_info->assignment_ && !model_info->assignment_) { |
| 1102 sums[program_info][model_info] += score; | 1073 sums[program_info][model_info] += score; |
| 1103 } | 1074 } |
| 1104 } | 1075 } |
| 1105 | 1076 |
| 1106 for (ScoreSet::iterator assignee_iterator = sums.begin(); | 1077 for (ScoreSet::iterator assignee_iterator = sums.begin(); |
| 1107 assignee_iterator != sums.end(); | 1078 assignee_iterator != sums.end(); |
| 1108 ++assignee_iterator) { | 1079 ++assignee_iterator) { |
| 1109 LabelInfo* program_info = assignee_iterator->first; | 1080 LabelInfo* program_info = assignee_iterator->first; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1132 } | 1103 } |
| 1133 } | 1104 } |
| 1134 } | 1105 } |
| 1135 | 1106 |
| 1136 void AssignOne(LabelInfo* model_info, LabelInfo* program_info) { | 1107 void AssignOne(LabelInfo* model_info, LabelInfo* program_info) { |
| 1137 LOG_ASSERT(!model_info->assignment_); | 1108 LOG_ASSERT(!model_info->assignment_); |
| 1138 LOG_ASSERT(!program_info->assignment_); | 1109 LOG_ASSERT(!program_info->assignment_); |
| 1139 LOG_ASSERT(model_info->is_model_); | 1110 LOG_ASSERT(model_info->is_model_); |
| 1140 LOG_ASSERT(!program_info->is_model_); | 1111 LOG_ASSERT(!program_info->is_model_); |
| 1141 | 1112 |
| 1142 ALOG2 << "Assign " << ToString(program_info) | 1113 VLOG(3) << "Assign " << ToString(program_info) |
| 1143 << " := " << ToString(model_info); | 1114 << " := " << ToString(model_info); |
| 1144 | 1115 |
| 1145 ShingleSet affected_shingles; | 1116 ShingleSet affected_shingles; |
| 1146 AddAffectedPositions(model_info, &affected_shingles); | 1117 AddAffectedPositions(model_info, &affected_shingles); |
| 1147 AddAffectedPositions(program_info, &affected_shingles); | 1118 AddAffectedPositions(program_info, &affected_shingles); |
| 1148 | 1119 |
| 1149 for (ShingleSet::iterator p = affected_shingles.begin(); | 1120 for (ShingleSet::iterator p = affected_shingles.begin(); |
| 1150 p != affected_shingles.end(); | 1121 p != affected_shingles.end(); |
| 1151 ++p) { | 1122 ++p) { |
| 1152 patterns_needing_updates_.insert((*p)->pattern()); | 1123 patterns_needing_updates_.insert((*p)->pattern()); |
| 1153 } | 1124 } |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1247 | 1218 |
| 1248 DISALLOW_COPY_AND_ASSIGN(AssignmentProblem); | 1219 DISALLOW_COPY_AND_ASSIGN(AssignmentProblem); |
| 1249 }; | 1220 }; |
| 1250 | 1221 |
| 1251 class Adjuster : public AdjustmentMethod { | 1222 class Adjuster : public AdjustmentMethod { |
| 1252 public: | 1223 public: |
| 1253 Adjuster() : prog_(NULL), model_(NULL) {} | 1224 Adjuster() : prog_(NULL), model_(NULL) {} |
| 1254 ~Adjuster() {} | 1225 ~Adjuster() {} |
| 1255 | 1226 |
| 1256 bool Adjust(const AssemblyProgram& model, AssemblyProgram* program) { | 1227 bool Adjust(const AssemblyProgram& model, AssemblyProgram* program) { |
| 1257 LOG(INFO) << "Adjuster::Adjust"; | 1228 VLOG(1) << "Adjuster::Adjust"; |
| 1258 prog_ = program; | 1229 prog_ = program; |
| 1259 model_ = &model; | 1230 model_ = &model; |
| 1260 return Finish(); | 1231 return Finish(); |
| 1261 } | 1232 } |
| 1262 | 1233 |
| 1263 bool Finish() { | 1234 bool Finish() { |
| 1264 prog_->UnassignIndexes(); | 1235 prog_->UnassignIndexes(); |
| 1265 Trace abs32_trace_; | 1236 Trace abs32_trace_; |
| 1266 Trace rel32_trace_; | 1237 Trace rel32_trace_; |
| 1267 CollectTraces(model_, &abs32_trace_, &rel32_trace_, true); | 1238 CollectTraces(model_, &abs32_trace_, &rel32_trace_, true); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1290 // incorporate some costing for entropy (bigger deltas) that will be | 1261 // incorporate some costing for entropy (bigger deltas) that will be |
| 1291 // introduced into the label address table by non-monotonic ordering. This | 1262 // introduced into the label address table by non-monotonic ordering. This |
| 1292 // would have some knock-on effects to parts of the algorithm that work on | 1263 // would have some knock-on effects to parts of the algorithm that work on |
| 1293 // single-occurrence labels. | 1264 // single-occurrence labels. |
| 1294 } | 1265 } |
| 1295 | 1266 |
| 1296 void Solve(const Trace& model, size_t model_end) { | 1267 void Solve(const Trace& model, size_t model_end) { |
| 1297 base::Time start_time = base::Time::Now(); | 1268 base::Time start_time = base::Time::Now(); |
| 1298 AssignmentProblem a(model, model_end); | 1269 AssignmentProblem a(model, model_end); |
| 1299 a.Solve(); | 1270 a.Solve(); |
| 1300 LOG(INFO) << " Adjuster::Solve " | 1271 VLOG(1) << " Adjuster::Solve " |
| 1301 << (base::Time::Now() - start_time).InSecondsF(); | 1272 << (base::Time::Now() - start_time).InSecondsF(); |
| 1302 } | 1273 } |
| 1303 | 1274 |
| 1304 void ReferenceLabel(Trace* trace, Label* label, bool is_model) { | 1275 void ReferenceLabel(Trace* trace, Label* label, bool is_model) { |
| 1305 trace->push_back( | 1276 trace->push_back( |
| 1306 label_info_maker_.MakeLabelInfo(label, is_model, trace->size())); | 1277 label_info_maker_.MakeLabelInfo(label, is_model, trace->size())); |
| 1307 } | 1278 } |
| 1308 | 1279 |
| 1309 AssemblyProgram* prog_; // Program to be adjusted, owned by caller. | 1280 AssemblyProgram* prog_; // Program to be adjusted, owned by caller. |
| 1310 const AssemblyProgram* model_; // Program to be mimicked, owned by caller. | 1281 const AssemblyProgram* model_; // Program to be mimicked, owned by caller. |
| 1311 | 1282 |
| 1312 LabelInfoMaker label_info_maker_; | 1283 LabelInfoMaker label_info_maker_; |
| 1313 | 1284 |
| 1314 private: | 1285 private: |
| 1315 DISALLOW_COPY_AND_ASSIGN(Adjuster); | 1286 DISALLOW_COPY_AND_ASSIGN(Adjuster); |
| 1316 }; | 1287 }; |
| 1317 | 1288 |
| 1318 //////////////////////////////////////////////////////////////////////////////// | 1289 //////////////////////////////////////////////////////////////////////////////// |
| 1319 | 1290 |
| 1320 } // namespace adjustment_method_2 | 1291 } // namespace adjustment_method_2 |
| 1321 | 1292 |
| 1322 AdjustmentMethod* AdjustmentMethod::MakeShingleAdjustmentMethod() { | 1293 AdjustmentMethod* AdjustmentMethod::MakeShingleAdjustmentMethod() { |
| 1323 return new adjustment_method_2::Adjuster(); | 1294 return new adjustment_method_2::Adjuster(); |
| 1324 } | 1295 } |
| 1325 | 1296 |
| 1326 } // namespace courgette | 1297 } // namespace courgette |
| OLD | NEW |