Go to the documentation of this file.00001 #ifndef NPSTAT_BOXND_HH_
00002 #define NPSTAT_BOXND_HH_
00003
00014 #include <vector>
00015
00016 #include "Alignment/Geners/interface/ClassId.hh"
00017 #include "JetMETCorrections/InterpolationTables/interface/Interval.h"
00018
00019 namespace npstat {
00023 template <typename Numeric>
00024 struct BoxND : public std::vector<Interval<Numeric> >
00025 {
00027 inline BoxND() {}
00028
00030 inline explicit BoxND(const unsigned long dim) :
00031 std::vector<Interval<Numeric> >(dim) {}
00032
00034 inline BoxND(const unsigned long dim, const Interval<Numeric>& v) :
00035 std::vector<Interval<Numeric> >(dim, v) {}
00036
00042 template <typename Num2>
00043 explicit BoxND(const std::vector<Num2>& limits);
00044
00046 template <typename Num2>
00047 explicit BoxND(const BoxND<Num2>& r);
00048
00053 template <typename Num2>
00054 BoxND& copyFrom(const BoxND<Num2>& r);
00055
00057 inline unsigned long dim() const {return this->size();}
00058
00060 Numeric volume() const;
00061
00066 void getMidpoint(Numeric* coord, unsigned long coordLen) const;
00067
00069
00074 template <typename Num2>
00075 bool isInsideLower(const Num2* coord, unsigned long coordLen) const;
00076 template <typename Num2>
00077 bool isInsideUpper(const Num2* coord, unsigned long coordLen) const;
00078 template <typename Num2>
00079 bool isInsideWithBounds(const Num2* coord, unsigned long coordLen) const;
00080 template <typename Num2>
00081 bool isInside(const Num2* coord, unsigned long coordLen) const;
00083
00085
00086 BoxND& operator*=(double r);
00087 BoxND& operator/=(double r);
00089
00091
00092 BoxND& operator*=(const std::vector<double>& scales);
00093 BoxND& operator/=(const std::vector<double>& scales);
00095
00100 BoxND& expand(double r);
00101
00103
00108 BoxND& expand(const std::vector<double>& scales);
00109 BoxND& expand(const double* scales, unsigned long lenScales);
00111
00113
00114 template <typename Num2>
00115 BoxND& operator+=(const std::vector<Num2>& shifts);
00116 template <typename Num2>
00117 BoxND& operator-=(const std::vector<Num2>& shifts);
00118 template <typename Num2>
00119 BoxND& shift(const Num2* shifts, unsigned long lenShifts);
00121
00123 BoxND& moveToOrigin();
00124
00126 Numeric overlapVolume(const BoxND& r) const;
00127
00129 double overlapFraction(const BoxND& r) const;
00130
00132 static BoxND unitBox(unsigned long ndim);
00133
00139 static BoxND sizeTwoBox(unsigned long ndim);
00140
00146 static BoxND allSpace(unsigned long ndim);
00147
00149
00150 inline gs::ClassId classId() const {return gs::ClassId(*this);}
00151 bool write(std::ostream& of) const;
00153
00154 static const char* classname();
00155 static inline unsigned version() {return 1;}
00156 static void restore(const gs::ClassId& id, std::istream& in, BoxND* box);
00157 };
00158 }
00159
00161
00162 template <typename Numeric>
00163 bool operator==(const npstat::BoxND<Numeric>& l, const npstat::BoxND<Numeric>& r);
00164
00165 template <typename Numeric>
00166 bool operator!=(const npstat::BoxND<Numeric>& l, const npstat::BoxND<Numeric>& r);
00168
00169 #include <limits>
00170 #include <cassert>
00171 #include "JetMETCorrections/InterpolationTables/interface/NpstatException.h"
00172
00173 #include "Alignment/Geners/interface/GenericIO.hh"
00174
00175 namespace npstat {
00176 template <typename Numeric>
00177 template <typename Num2>
00178 BoxND<Numeric>::BoxND(const BoxND<Num2>& r)
00179 {
00180 const unsigned long dim = r.size();
00181 if (dim)
00182 {
00183 this->reserve(dim);
00184 for (unsigned long i=0; i<dim; ++i)
00185 {
00186 const Interval<Num2>& ri(r[i]);
00187 this->push_back(Interval<Numeric>(ri.min(), ri.max()));
00188 }
00189 }
00190 }
00191
00192 template <typename Numeric>
00193 template <typename Num2>
00194 BoxND<Numeric>::BoxND(const std::vector<Num2>& limits)
00195 {
00196 const unsigned long dim = limits.size();
00197 if (dim)
00198 {
00199 this->reserve(dim);
00200 Numeric zero = Numeric();
00201 for (unsigned long i=0; i<dim; ++i)
00202 {
00203 const Numeric value(static_cast<Numeric>(limits[i]));
00204 if (value >= zero)
00205 this->push_back(Interval<Numeric>(zero, value));
00206 else
00207 this->push_back(Interval<Numeric>(value, zero));
00208 }
00209 }
00210 }
00211
00212 template <typename Numeric>
00213 template <typename Num2>
00214 BoxND<Numeric>& BoxND<Numeric>::copyFrom(const BoxND<Num2>& r)
00215 {
00216 if ((void *)this == (void *)(&r))
00217 return *this;
00218 const unsigned long n = r.size();
00219 this->clear();
00220 this->reserve(n);
00221 for (unsigned long i=0; i<n; ++i)
00222 {
00223 const Interval<Num2>& ir(r[i]);
00224 this->push_back(Interval<Numeric>(ir.min(), ir.max()));
00225 }
00226 return *this;
00227 }
00228
00229 template <typename Numeric>
00230 Numeric BoxND<Numeric>::volume() const
00231 {
00232 Numeric v(static_cast<Numeric>(1));
00233 const unsigned long mydim = this->size();
00234 for (unsigned long i=0U; i<mydim; ++i)
00235 v *= (*this)[i].length();
00236 return v;
00237 }
00238
00239 template <typename Numeric>
00240 Numeric BoxND<Numeric>::overlapVolume(const BoxND& r) const
00241 {
00242 const unsigned long mydim = this->size();
00243 if (mydim == r.size())
00244 {
00245 Numeric v(static_cast<Numeric>(1));
00246 for (unsigned long i=0U; i<mydim; ++i)
00247 v *= (*this)[i].overlapLength(r[i]);
00248 return v;
00249 }
00250 else
00251 return static_cast<Numeric>(0);
00252 }
00253
00254 template <typename Numeric>
00255 double BoxND<Numeric>::overlapFraction(const BoxND& r) const
00256 {
00257 const unsigned long mydim = this->size();
00258 if (mydim == r.size())
00259 {
00260 double f = 1.0;
00261 for (unsigned long i=0U; i<mydim; ++i)
00262 f *= (*this)[i].overlapFraction(r[i]);
00263 return f;
00264 }
00265 else
00266 return 0.0;
00267 }
00268
00269 template <typename Numeric>
00270 void BoxND<Numeric>::getMidpoint(Numeric* coord,
00271 const unsigned long coordLen) const
00272 {
00273 const unsigned long mydim = this->size();
00274 if (coordLen < mydim) throw npstat::NpstatInvalidArgument(
00275 "In npstat::BoxND::getMidpoint: insufficient output buffer length");
00276 if (mydim)
00277 {
00278 assert(coord);
00279 for (unsigned long i=0U; i<mydim; ++i)
00280 coord[i] = (*this)[i].midpoint();
00281 }
00282 }
00283
00284 template <typename Numeric>
00285 template <typename Num2>
00286 bool BoxND<Numeric>::isInsideLower(const Num2* coords,
00287 const unsigned long coordLen) const
00288 {
00289 if (coordLen != this->size()) throw npstat::NpstatInvalidArgument(
00290 "In npstat::BoxND::isInsideLower: "
00291 "incompatible point dimensionality");
00292 const Interval<Numeric>* myptr = &(*this)[0];
00293 for (unsigned long i=0; i<coordLen; ++i)
00294 if (!myptr[i].isInsideLower(coords[i]))
00295 return false;
00296 return true;
00297 }
00298
00299 template <typename Numeric>
00300 template <typename Num2>
00301 bool BoxND<Numeric>::isInsideUpper(const Num2* coords,
00302 const unsigned long coordLen) const
00303 {
00304 if (coordLen != this->size()) throw npstat::NpstatInvalidArgument(
00305 "In npstat::BoxND::isInsideUpper: "
00306 "incompatible point dimensionality");
00307 const Interval<Numeric>* myptr = &(*this)[0];
00308 for (unsigned long i=0; i<coordLen; ++i)
00309 if (!myptr[i].isInsideUpper(coords[i]))
00310 return false;
00311 return true;
00312 }
00313
00314 template <typename Numeric>
00315 template <typename Num2>
00316 bool BoxND<Numeric>::isInsideWithBounds(const Num2* coords,
00317 const unsigned long coordLen) const
00318 {
00319 if (coordLen != this->size()) throw npstat::NpstatInvalidArgument(
00320 "In npstat::BoxND::isInsideWithBounds: "
00321 "incompatible point dimensionality");
00322 const Interval<Numeric>* myptr = &(*this)[0];
00323 for (unsigned long i=0; i<coordLen; ++i)
00324 if (!myptr[i].isInsideWithBounds(coords[i]))
00325 return false;
00326 return true;
00327 }
00328
00329 template <typename Numeric>
00330 template <typename Num2>
00331 bool BoxND<Numeric>::isInside(const Num2* coords,
00332 const unsigned long coordLen) const
00333 {
00334 if (coordLen != this->size()) throw npstat::NpstatInvalidArgument(
00335 "In npstat::BoxND::isInside: incompatible point dimensionality");
00336 const Interval<Numeric>* myptr = &(*this)[0];
00337 for (unsigned long i=0; i<coordLen; ++i)
00338 if (!myptr[i].isInside(coords[i]))
00339 return false;
00340 return true;
00341 }
00342
00343 template <typename Numeric>
00344 BoxND<Numeric>& BoxND<Numeric>::operator*=(const double r)
00345 {
00346 const unsigned long mydim = this->size();
00347 for (unsigned long i=0; i<mydim; ++i)
00348 (*this)[i] *= r;
00349 return *this;
00350 }
00351
00352 template <typename Numeric>
00353 BoxND<Numeric>& BoxND<Numeric>::moveToOrigin()
00354 {
00355 const unsigned long mydim = this->size();
00356 for (unsigned long i=0; i<mydim; ++i)
00357 (*this)[i].moveMidpointTo0();
00358 return *this;
00359 }
00360
00361 template <typename Numeric>
00362 BoxND<Numeric>& BoxND<Numeric>::expand(const double r)
00363 {
00364 const unsigned long mydim = this->size();
00365 for (unsigned long i=0; i<mydim; ++i)
00366 (*this)[i].expand(r);
00367 return *this;
00368 }
00369
00370 template <typename Numeric>
00371 BoxND<Numeric>& BoxND<Numeric>::operator*=(
00372 const std::vector<double>& scales)
00373 {
00374 const unsigned long mydim = this->size();
00375 if (mydim != scales.size()) throw npstat::NpstatInvalidArgument(
00376 "In npstat::BoxND::operator*=: "
00377 "incompatible argument dimensionality");
00378 for (unsigned long i=0; i<mydim; ++i)
00379 (*this)[i] *= scales[i];
00380 return *this;
00381 }
00382
00383 template <typename Numeric>
00384 BoxND<Numeric>& BoxND<Numeric>::expand(
00385 const std::vector<double>& scales)
00386 {
00387 const unsigned long mydim = this->size();
00388 if (mydim != scales.size()) throw npstat::NpstatInvalidArgument(
00389 "In npstat::BoxND::expand: incompatible argument dimensionality");
00390 for (unsigned long i=0; i<mydim; ++i)
00391 (*this)[i].expand(scales[i]);
00392 return *this;
00393 }
00394
00395 template <typename Numeric>
00396 BoxND<Numeric>& BoxND<Numeric>::expand(
00397 const double* scales, const unsigned long lenScales)
00398 {
00399 const unsigned long mydim = this->size();
00400 if (mydim != lenScales) throw npstat::NpstatInvalidArgument(
00401 "In npstat::BoxND::expand: incompatible argument dimensionality");
00402 if (mydim)
00403 {
00404 assert(scales);
00405 for (unsigned long i=0; i<mydim; ++i)
00406 (*this)[i].expand(scales[i]);
00407 }
00408 return *this;
00409 }
00410
00411 template <typename Numeric>
00412 BoxND<Numeric>& BoxND<Numeric>::operator/=(const double r)
00413 {
00414 const unsigned long mydim = this->size();
00415 for (unsigned long i=0; i<mydim; ++i)
00416 (*this)[i] /= r;
00417 return *this;
00418 }
00419
00420 template <typename Numeric>
00421 BoxND<Numeric>& BoxND<Numeric>::operator/=(
00422 const std::vector<double>& scales)
00423 {
00424 const unsigned long mydim = this->size();
00425 if (mydim != scales.size()) throw npstat::NpstatInvalidArgument(
00426 "In npstat::BoxND::operator/=: "
00427 "incompatible argument dimensionality");
00428 for (unsigned long i=0; i<mydim; ++i)
00429 (*this)[i] /= scales[i];
00430 return *this;
00431 }
00432
00433 template <typename Numeric>
00434 template <typename Num2>
00435 BoxND<Numeric>& BoxND<Numeric>::operator+=(const std::vector<Num2>& shifts)
00436 {
00437 const unsigned long mydim = this->size();
00438 if (mydim != shifts.size()) throw npstat::NpstatInvalidArgument(
00439 "In npstat::BoxND::operator+=: "
00440 "incompatible argument dimensionality");
00441 for (unsigned long i=0; i<mydim; ++i)
00442 (*this)[i] += static_cast<Numeric>(shifts[i]);
00443 return *this;
00444 }
00445
00446 template <typename Numeric>
00447 template <typename Num2>
00448 BoxND<Numeric>& BoxND<Numeric>::shift(
00449 const Num2* shifts, const unsigned long shiftsLen)
00450 {
00451 const unsigned long mydim = this->size();
00452 if (mydim != shiftsLen) throw npstat::NpstatInvalidArgument(
00453 "In npstat::BoxND::shift: incompatible argument dimensionality");
00454 if (mydim)
00455 {
00456 assert(shifts);
00457 for (unsigned long i=0; i<mydim; ++i)
00458 (*this)[i] += static_cast<Numeric>(shifts[i]);
00459 }
00460 return *this;
00461 }
00462
00463 template <typename Numeric>
00464 template <typename Num2>
00465 BoxND<Numeric>& BoxND<Numeric>::operator-=(const std::vector<Num2>& shifts)
00466 {
00467 const unsigned long mydim = this->size();
00468 if (mydim != shifts.size()) throw npstat::NpstatInvalidArgument(
00469 "In npstat::BoxND::operator-=: "
00470 "incompatible argument dimensionality");
00471 for (unsigned long i=0; i<mydim; ++i)
00472 (*this)[i] -= static_cast<Numeric>(shifts[i]);
00473 return *this;
00474 }
00475
00476 template <typename Numeric>
00477 BoxND<Numeric> BoxND<Numeric>::unitBox(const unsigned long ndim)
00478 {
00479 Interval<Numeric> unit(static_cast<Numeric>(0),
00480 static_cast<Numeric>(1));
00481 return BoxND<Numeric>(ndim, unit);
00482 }
00483
00484 template <typename Numeric>
00485 BoxND<Numeric> BoxND<Numeric>::sizeTwoBox(const unsigned long ndim)
00486 {
00487 const Numeric one = static_cast<Numeric>(1);
00488 Interval<Numeric> i(-one, one);
00489 return BoxND<Numeric>(ndim, i);
00490 }
00491
00492 template <typename Numeric>
00493 BoxND<Numeric> BoxND<Numeric>::allSpace(const unsigned long ndim)
00494 {
00495 const Numeric maxval = std::numeric_limits<Numeric>::max();
00496 Interval<Numeric> i(-maxval, maxval);
00497 return BoxND<Numeric>(ndim, i);
00498 }
00499
00500 template<typename Numeric>
00501 const char* BoxND<Numeric>::classname()
00502 {
00503 static const std::string na(gs::template_class_name<Numeric>("npstat::BoxND"));
00504 return na.c_str();
00505 }
00506
00507 template<typename Numeric>
00508 bool BoxND<Numeric>::write(std::ostream& of) const
00509 {
00510 const unsigned long mydim = this->size();
00511 std::vector<Numeric> limits;
00512 limits.reserve(2UL*mydim);
00513 for (unsigned long i=0; i<mydim; ++i)
00514 {
00515 limits.push_back((*this)[i].min());
00516 limits.push_back((*this)[i].max());
00517 }
00518 return gs::write_item(of, limits);
00519 }
00520
00521 template<typename Numeric>
00522 void BoxND<Numeric>::restore(const gs::ClassId& id, std::istream& in, BoxND* b)
00523 {
00524 static const gs::ClassId current(gs::ClassId::makeId<BoxND<Numeric> >());
00525 current.ensureSameId(id);
00526
00527 std::vector<Numeric> limits;
00528 gs::restore_item(in, &limits);
00529 if (in.fail())
00530 throw gs::IOReadFailure("In npstat::BoxND::restore: input stream failure");
00531 const unsigned long nlimits = limits.size();
00532 if (nlimits % 2UL)
00533 throw gs::IOInvalidData("In npstat::BoxND::restore: bad limits");
00534 assert(b);
00535 b->clear();
00536 b->reserve(nlimits/2UL);
00537 for (unsigned long i=0; i<nlimits/2UL; ++i)
00538 b->push_back(npstat::Interval<Numeric>(limits[2U*i], limits[2U*i+1U]));
00539 }
00540 }
00541
00542 template <typename Numeric>
00543 bool operator==(const npstat::BoxND<Numeric>& l, const npstat::BoxND<Numeric>& r)
00544 {
00545 const unsigned long dim = l.size();
00546 if (dim != r.size())
00547 return false;
00548 for (unsigned long i=0; i<dim; ++i)
00549 if (l[i] != r[i])
00550 return false;
00551 return true;
00552 }
00553
00554 template <typename Numeric>
00555 bool operator!=(const npstat::BoxND<Numeric>& l, const npstat::BoxND<Numeric>& r)
00556 {
00557 return !(l == r);
00558 }
00559
00560
00561 #endif // NPSTAT_BOXND_HH_
00562