00001
00002
00003 #ifndef __ug_mm_2d_table_h
00004 #define __ug_mm_2d_table_h
00005 #include <boost/iostreams/device/mapped_file.hpp>
00006 #include <boost/shared_ptr.hpp>
00007 #include <vector>
00008 #include <map>
00009 #include "tpt_typedefs.h"
00010 #include "tpt_pickler.h"
00011 #include "ug_typedefs.h"
00012 #include "util/exception.hh"
00013 namespace bio=boost::iostreams;
00014 namespace sapt
00015 {
00016 template<typename OFFSET, typename ID, typename VAL, typename INIT>
00017 class
00018 mm2dTable
00019 {
00020 public:
00021 struct Cell
00022 {
00023 ID id;
00024 VAL val;
00025
00026 bool
00027 operator<(ID const otherId) const
00028 {
00029 return id < otherId;
00030 }
00031
00032 bool
00033 operator<(Cell const& other) const
00034 {
00035 return id < other.id;
00036 }
00037
00038 struct SortDescendingByValue
00039 {
00040 bool operator()(Cell const& a, Cell const& b) const
00041 {
00042 return a.val > b.val;
00043 }
00044 };
00045 };
00046
00047 struct Row
00048 {
00049 Cell const* start;
00050 Cell const* stop;
00051 VAL operator[](ID key) const;
00052 };
00053
00054 Cell const* data;
00055 VAL const* M1;
00056 VAL const* M2;
00057 OFFSET const* index;
00058 ID numRows;
00059 ID numCols;
00060 boost::shared_ptr<bio::mapped_file_source> file;
00061
00062 VAL m1(ID key) const
00063 {
00064 return (key < numRows) ? M1[key] : INIT(0);
00065 }
00066
00067 VAL m2(ID key) const
00068 {
00069 return (key < numCols) ? M2[key] : INIT(0);
00070 }
00071
00072
00073 void open(std::string fname);
00074 void close();
00075
00076 Row operator[](ID key) const;
00077
00078 mm2dTable(std::string const fname="") { if (!fname.empty()) open(fname); };
00079 ~mm2dTable() { file.reset(); };
00080 };
00081
00082 template<typename OFFSET, typename ID, typename VAL, typename INIT>
00083 typename mm2dTable<OFFSET,ID,VAL,INIT>::Row
00084 mm2dTable<OFFSET,ID,VAL,INIT>::
00085 operator[](ID key) const
00086 {
00087 Row ret;
00088 if (key < numRows)
00089 {
00090 ret.start = data+index[key];
00091 ret.stop = data+index[key+1];
00092 }
00093 else
00094 ret.start = ret.stop = data+index[key+1];
00095 return ret;
00096 }
00097
00098 template<typename OFFSET, typename ID, typename VAL, typename INIT>
00099 VAL
00100 mm2dTable<OFFSET,ID,VAL,INIT>::
00101 Row::
00102 operator[](ID key) const
00103 {
00104 if (start==stop) return INIT(0);
00105 Cell const* c = std::lower_bound(start,stop,key);
00106 return (c != stop && c->id == key ? c->val : INIT(0));
00107 }
00108
00109 template<typename OFFSET, typename ID, typename VAL, typename INIT>
00110 void
00111 mm2dTable<OFFSET,ID,VAL,INIT>::
00112 open(std::string fname)
00113 {
00114
00115 if (access(fname.c_str(),R_OK))
00116 {
00117 std::ostringstream msg;
00118 msg << "[" << __FILE__ << ":" << __LINE__ <<"] FATAL ERROR: "
00119 << "file '" << fname << " is not accessible." << std::endl;
00120 std::string foo = msg.str();
00121 UTIL_THROW(util::Exception,foo.c_str());
00122 }
00123 file.reset(new bio::mapped_file_source());
00124 file->open(fname);
00125 if (!file->is_open())
00126 {
00127 std::ostringstream msg;
00128 msg << "[" << __FILE__ << ":" << __LINE__ <<"] FATAL ERROR: "
00129 << "Opening file '" << fname << "' failed." << std::endl;
00130 std::string foo = msg.str();
00131 UTIL_THROW(util::Exception,foo.c_str());
00132 }
00133 char const* p = file->data();
00134 filepos_type offset = *reinterpret_cast<filepos_type const*>(p);
00135 index = reinterpret_cast<OFFSET const*>(p+offset); p += sizeof(offset);
00136 numRows = *reinterpret_cast<ID const*>(p); p += sizeof(id_type);
00137 numCols = *reinterpret_cast<ID const*>(p); p += sizeof(id_type);
00138 data = reinterpret_cast<Cell const*>(p);
00139
00140 M1 = reinterpret_cast<VAL const*>(index+numRows+1);
00141 M2 = M1+numRows;
00142
00143
00144
00145
00146
00147
00148 }
00149
00150 template<
00151 typename OFFSET,
00152 typename ID,
00153 typename VAL,
00154 typename INIT,
00155 typename ICONT
00156 >
00157 void
00158 write_mm_2d_table(std::ostream& out, std::vector<ICONT> const& T,
00159 std::vector<VAL> const* m1 = NULL,
00160 std::vector<VAL> const* m2 = NULL)
00161 {
00162 assert(T.size());
00163 typedef typename ICONT::const_iterator iter;
00164
00165
00166 std::vector<VAL> m1x,m2x;
00167 if (!m1)
00168 {
00169 m1x.resize(T.size(),INIT(0));
00170 for (size_t r = 0; r < T.size(); ++r)
00171 for (iter c = T.at(r).begin(); c != T.at(r).end(); ++c)
00172 m1x[r] = m1x[r] + c->second;
00173 m1 = &m1x;
00174 }
00175 if (!m2)
00176 {
00177 for (size_t r = 0; r < T.size(); ++r)
00178 for (iter c = T.at(r).begin(); c != T.at(r).end(); ++c)
00179 {
00180 while (c->first >= m2x.size())
00181 m2x.push_back(INIT(0));
00182 m2x[c->first] = m2x[c->first] + c->second;
00183 }
00184 m2 = &m2x;
00185 }
00186
00187 filepos_type idxOffset=0;
00188 tpt::numwrite(out,idxOffset);
00189 tpt::numwrite(out,id_type(m1->size()));
00190 tpt::numwrite(out,id_type(m2->size()));
00191
00192
00193 std::vector<OFFSET> index;
00194 size_t ctr =0;
00195 index.reserve(m1->size()+1);
00196 for (ID r = 0; r < ID(T.size()); ++r)
00197 {
00198
00199 index.push_back(ctr);
00200 ID lastId = 0;
00201 if (T.at(r).size())
00202 lastId = T.at(r).begin()->first;
00203 for (typename ICONT::const_iterator c = T.at(r).begin();
00204 c != T.at(r).end(); ++c)
00205 {
00206 ctr++;
00207 assert(c->first >= lastId);
00208 lastId = c->first;
00209 typename mm2dTable<OFFSET,ID,VAL,INIT>::Cell item;
00210 item.id = c->first;
00211 item.val = c->second;
00212 out.write(reinterpret_cast<char const*>(&item),sizeof(item));
00213 }
00214 }
00215
00216 index.push_back(ctr);
00217 idxOffset=out.tellp();
00218
00219
00220 for (size_t i = 0; i < index.size(); ++i)
00221 {
00222 OFFSET o = index[i];
00223 out.write(reinterpret_cast<char*>(&o),sizeof(OFFSET));
00224 }
00225
00226
00227 out.write(reinterpret_cast<char const*>(&(*m1)[0]),m1->size()*sizeof(VAL));
00228 out.write(reinterpret_cast<char const*>(&(*m2)[0]),m2->size()*sizeof(VAL));
00229
00230 out.seekp(0);
00231 tpt::numwrite(out,idxOffset);
00232 }
00233 }
00234 #endif