00001 /* 00002 * Copyright 2007 Martin von Gagern 00003 * 00004 * 00005 * This file is part of mqn2mps. 00006 * 00007 * mqn2mps is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 3 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * mqn2mps is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00019 */ 00020 00021 00022 #include <string> 00023 #include <vector> 00024 #include <set> 00025 #include <algorithm> 00026 00027 #include "triplet.hh" 00028 #include "rational.hh" 00029 #include "field.hh" 00030 #include "vdiff.hh" 00031 00032 /** 00033 * @file 00034 * Implementation of class vdiff. 00035 */ 00036 00037 /** 00038 * Lexicographically compare two containers. 00039 * 00040 * As the STL implementation of lexicographical comparison has such an 00041 * awfully long name, and operates on iterator pairs instead of 00042 * container objects, the use of this wrapper function makes code 00043 * somewhat shorter. 00044 * 00045 * @param a the first container to compare. 00046 * @param b the second container to compare. 00047 * @return whether @e a is lexicographically less than @e b. 00048 */ 00049 template<class A, class B> static inline bool lexcmp(const A& a, const B& b) { 00050 return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end()); 00051 } 00052 00053 /** 00054 * Compare fields by their components. 00055 * This helper class can be passed as a template argument to 00056 * containers class or generic algorithm to define sorting on field 00057 * pointers. 00058 */ 00059 struct field_cmp { 00060 /** 00061 * Compare fields by their components. 00062 * @param a a pointer to the first field to be compared. 00063 * @param b a pointer to the second field to be compared. 00064 * @return whether the values of @e a are lexicographically less 00065 * than those of @e b. 00066 */ 00067 bool operator() (const field* a, const field* b) { 00068 return lexcmp(a->values, b->values); 00069 } 00070 }; 00071 00072 /** 00073 * Constructor that calculates difference vectors. 00074 * 00075 * Given a set of input vectors (field descriptions), this constructor 00076 * sorts them, calculates differences between the first and subsequent 00077 * vectors, and stores these difference vectors internally. 00078 * 00079 * @param[in,out] fields a collection of fields, will be sorted. 00080 */ 00081 vdiff::vdiff(std::vector<const field*>& fields) { 00082 std::sort(fields.begin(), fields.end(), field_cmp()); 00083 rows = fields[0]->values.size(); 00084 cols = fields.size() - 1; 00085 for (int col = 1; col <= cols; ++col) { 00086 for (int row = 0; row < rows; ++row) { 00087 if (fields[0]->values[row] != fields[col]->values[row]) 00088 elements.insert(make_triplet(row, col-1, fields[col]->values[row] 00089 - fields[0]->values[row])); 00090 } 00091 } 00092 } 00093 00094 /** 00095 * Retrieve a difference operator. 00096 * 00097 * The difference vector with the given index is constructed on the 00098 * fly. Assuming input consisted of vectors v[0] thrugh v[n], then for 00099 * a given argument i this method here will return the vector 00100 * v[i+1]-v[0]. Obviously the maximum index is two less than the 00101 * number of input vectors to the constructor. 00102 * 00103 * @param col the index of the difference vector to be returned. 00104 * @return the specified difference vector. 00105 */ 00106 field vdiff::operator[](int col) const { 00107 field res; 00108 res.values.resize(rows); 00109 for (std::set< triplet<rational> >::iterator 00110 i = elements.begin(), e = elements.end(); i != e; ++i) { 00111 if (i->col == col) res.values[i->row] = i->val; 00112 } 00113 return res; 00114 } 00115 00116 /** 00117 * Compare sets of vector differences. 00118 * 00119 * The comparison is implemented as a lexicographical comparison over 00120 * matrix element triplets. However, any total order should do. 00121 * 00122 * @param d the other set of difference vectors. 00123 * @return whether this set is less than the other set of difference 00124 * vectors. 00125 */ 00126 bool vdiff::operator<(const vdiff& d) const { 00127 if (cols != d.cols) return cols < d.cols; 00128 return lexcmp(elements, d.elements); 00129 }
1.6.0