[0b990d] | 1 | //
|
---|
| 2 | // moindexspace.cc
|
---|
| 3 | //
|
---|
| 4 | // Copyright (C) 2003 Edward Valeev
|
---|
| 5 | //
|
---|
| 6 | // Author: Edward Valeev <edward.valeev@chemistry.gatech.edu>
|
---|
| 7 | // Maintainer: EV
|
---|
| 8 | //
|
---|
| 9 | // This file is part of the SC Toolkit.
|
---|
| 10 | //
|
---|
| 11 | // The SC Toolkit is free software; you can redistribute it and/or modify
|
---|
| 12 | // it under the terms of the GNU Library General Public License as published by
|
---|
| 13 | // the Free Software Foundation; either version 2, or (at your option)
|
---|
| 14 | // any later version.
|
---|
| 15 | //
|
---|
| 16 | // The SC Toolkit is distributed in the hope that it will be useful,
|
---|
| 17 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 18 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
| 19 | // GNU Library General Public License for more details.
|
---|
| 20 | //
|
---|
| 21 | // You should have received a copy of the GNU Library General Public License
|
---|
| 22 | // along with the SC Toolkit; see the file COPYING.LIB. If not, write to
|
---|
| 23 | // the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
---|
| 24 | //
|
---|
| 25 | // The U.S. Government is granted a limited license as per AL 91-7.
|
---|
| 26 | //
|
---|
| 27 |
|
---|
| 28 | #ifdef __GNUG__
|
---|
| 29 | #pragma implementation
|
---|
| 30 | #endif
|
---|
| 31 |
|
---|
| 32 | #include <stdexcept>
|
---|
| 33 | #include <algorithm>
|
---|
| 34 | #include <stdlib.h>
|
---|
| 35 | #include <util/misc/formio.h>
|
---|
| 36 | #include <chemistry/qc/basis/petite.h>
|
---|
| 37 | #include <chemistry/qc/mbptr12/moindexspace.h>
|
---|
| 38 |
|
---|
| 39 | using namespace std;
|
---|
| 40 | using namespace sc;
|
---|
| 41 |
|
---|
| 42 | inline int max(int a,int b) { return (a > b) ? a : b;}
|
---|
| 43 |
|
---|
| 44 | /*---------------
|
---|
| 45 | MOIndexSpace
|
---|
| 46 | ---------------*/
|
---|
| 47 | static ClassDesc MOIndexSpace_cd(
|
---|
| 48 | typeid(MOIndexSpace),"MOIndexSpace",1,"virtual public SavableState",
|
---|
| 49 | 0, 0, create<MOIndexSpace>);
|
---|
| 50 |
|
---|
| 51 | MOIndexSpace::MOIndexSpace(std::string name, const RefSCMatrix& full_coefs,
|
---|
| 52 | const Ref<GaussianBasisSet> basis, const Ref<Integral>& integral,
|
---|
| 53 | const vector<int>& offsets, const vector<int>& nmopi, IndexOrder moorder,
|
---|
| 54 | const RefDiagSCMatrix& evals) :
|
---|
| 55 | name_(name), basis_(basis), integral_(integral), offsets_(offsets), nmo_(nmopi), full_rank_(full_coefs.coldim().n()),
|
---|
| 56 | moorder_(moorder)
|
---|
| 57 | {
|
---|
| 58 | full_coefs_to_coefs(full_coefs, evals);
|
---|
| 59 |
|
---|
| 60 | init();
|
---|
| 61 | }
|
---|
| 62 |
|
---|
| 63 | MOIndexSpace::MOIndexSpace(std::string name, const RefSCMatrix& full_coefs,
|
---|
| 64 | const Ref<GaussianBasisSet> basis, const Ref<Integral>& integral,
|
---|
| 65 | const RefDiagSCMatrix& evals, int nfzc, int nfzv, IndexOrder moorder) :
|
---|
| 66 | name_(name), basis_(basis), integral_(integral), full_rank_(full_coefs.coldim().n()), moorder_(moorder)
|
---|
| 67 | {
|
---|
| 68 | if (evals.null())
|
---|
| 69 | throw std::runtime_error("MOIndexSpace::MOIndexSpace() -- null eigenvalues matrix");
|
---|
| 70 | if (nfzc < 0 || nfzc >= full_coefs.coldim().n())
|
---|
| 71 | throw std::runtime_error("MOIndexSpace::MOIndexSpace() -- invalid nfzc");
|
---|
| 72 | if (nfzc + nfzv >= full_coefs.coldim().n())
|
---|
| 73 | throw std::runtime_error("MOIndexSpace::MOIndexSpace() -- invalid nfzc+nfzv");
|
---|
| 74 | frozen_to_blockinfo(nfzc,nfzv,evals);
|
---|
| 75 | full_coefs_to_coefs(full_coefs, evals);
|
---|
| 76 |
|
---|
| 77 | init();
|
---|
| 78 | }
|
---|
| 79 |
|
---|
| 80 | MOIndexSpace::MOIndexSpace(std::string name, const RefSCMatrix& full_coefs,
|
---|
| 81 | const Ref<GaussianBasisSet> basis, const Ref<Integral>& integral) :
|
---|
| 82 | name_(name), basis_(basis), integral_(integral),
|
---|
| 83 | full_rank_(full_coefs.coldim().n()), moorder_(symmetry)
|
---|
| 84 | {
|
---|
| 85 | Ref<SCBlockInfo> modim_blocks = full_coefs.coldim()->blocks();
|
---|
| 86 | int nb = modim_blocks->nblock();
|
---|
| 87 | offsets_.resize(nb);
|
---|
| 88 | nmo_.resize(nb);
|
---|
| 89 | for(int i=0; i<nb; i++) {
|
---|
| 90 | offsets_[i] = 0;
|
---|
| 91 | nmo_[i] = modim_blocks->size(i);
|
---|
| 92 | }
|
---|
| 93 |
|
---|
| 94 | full_coefs_to_coefs(full_coefs, 0);
|
---|
| 95 |
|
---|
| 96 | init();
|
---|
| 97 | }
|
---|
| 98 |
|
---|
| 99 | MOIndexSpace::MOIndexSpace(std::string name, const Ref<MOIndexSpace>& orig_space, const RefSCMatrix& new_coefs,
|
---|
| 100 | const Ref<GaussianBasisSet>& new_basis) :
|
---|
| 101 | name_(name), integral_(orig_space->integral()), mosym_(orig_space->mosym_), evals_(orig_space->evals_),
|
---|
| 102 | rank_(orig_space->rank_), full_rank_(orig_space->full_rank_), nblocks_(orig_space->nblocks_),
|
---|
| 103 | offsets_(orig_space->offsets_), nmo_(orig_space->nmo_), map_to_full_space_(orig_space->map_to_full_space_),
|
---|
| 104 | moorder_(orig_space->moorder_)
|
---|
| 105 | {
|
---|
| 106 | if (rank_ != new_coefs.coldim()->n())
|
---|
| 107 | throw std::runtime_error("MOIndexSpace::MOIndexSpace() -- new_coefs have different number of orbitals");
|
---|
| 108 | coefs_ = new_coefs;
|
---|
| 109 | basis_ = new_basis;
|
---|
| 110 | init();
|
---|
| 111 | }
|
---|
| 112 |
|
---|
| 113 | MOIndexSpace::MOIndexSpace(StateIn& si) : SavableState(si)
|
---|
| 114 | {
|
---|
| 115 | si.get(name_);
|
---|
| 116 |
|
---|
| 117 | coefs_.restore(si);
|
---|
| 118 | evals_.restore(si);
|
---|
| 119 | basis_ << SavableState::restore_state(si);
|
---|
| 120 | integral_ << SavableState::restore_state(si);
|
---|
| 121 | si.get(mosym_);
|
---|
| 122 |
|
---|
| 123 | si.get(rank_);
|
---|
| 124 | si.get(full_rank_);
|
---|
| 125 | si.get(nblocks_);
|
---|
| 126 | si.get(offsets_);
|
---|
| 127 | si.get(nmo_);
|
---|
| 128 | si.get(map_to_full_space_);
|
---|
| 129 |
|
---|
| 130 | int moorder; si.get(moorder); moorder = (int) moorder_;
|
---|
| 131 |
|
---|
| 132 | init();
|
---|
| 133 | }
|
---|
| 134 |
|
---|
| 135 | MOIndexSpace::~MOIndexSpace()
|
---|
| 136 | {
|
---|
| 137 | }
|
---|
| 138 |
|
---|
| 139 | void
|
---|
| 140 | MOIndexSpace::save_data_state(StateOut& so)
|
---|
| 141 | {
|
---|
| 142 | so.put(name_);
|
---|
| 143 |
|
---|
| 144 | coefs_.save(so);
|
---|
| 145 | evals_.save(so);
|
---|
| 146 | modim_ = evals_.dim();
|
---|
| 147 | SavableState::save_state(basis_.pointer(),so);
|
---|
| 148 | SavableState::save_state(integral_.pointer(),so);
|
---|
| 149 | so.put(mosym_);
|
---|
| 150 |
|
---|
| 151 | so.put(rank_);
|
---|
| 152 | so.put(full_rank_);
|
---|
| 153 | so.put(nblocks_);
|
---|
| 154 | so.put(offsets_);
|
---|
| 155 | so.put(nmo_);
|
---|
| 156 | so.put(map_to_full_space_);
|
---|
| 157 |
|
---|
| 158 | so.put((int)moorder_);
|
---|
| 159 | }
|
---|
| 160 |
|
---|
| 161 | const std::string
|
---|
| 162 | MOIndexSpace::name() const { return name_; }
|
---|
| 163 |
|
---|
| 164 | const Ref<GaussianBasisSet>
|
---|
| 165 | MOIndexSpace::basis() const { return basis_; }
|
---|
| 166 |
|
---|
| 167 | Ref<Integral>
|
---|
| 168 | MOIndexSpace::integral() const { return integral_; }
|
---|
| 169 |
|
---|
| 170 | const RefSCMatrix
|
---|
| 171 | MOIndexSpace::coefs() const { return coefs_; }
|
---|
| 172 |
|
---|
| 173 | const RefDiagSCMatrix
|
---|
| 174 | MOIndexSpace::evals() const { return evals_; }
|
---|
| 175 |
|
---|
| 176 | vector<int>
|
---|
| 177 | MOIndexSpace::mosym() const { return mosym_; }
|
---|
| 178 |
|
---|
| 179 | MOIndexSpace::IndexOrder
|
---|
| 180 | MOIndexSpace::moorder() const { return moorder_; }
|
---|
| 181 |
|
---|
| 182 | int
|
---|
| 183 | MOIndexSpace::rank() const { return rank_; }
|
---|
| 184 |
|
---|
| 185 | int
|
---|
| 186 | MOIndexSpace::full_rank() const { return full_rank_; }
|
---|
| 187 |
|
---|
| 188 | int
|
---|
| 189 | MOIndexSpace::nblocks() const { return nblocks_; }
|
---|
| 190 |
|
---|
| 191 | vector<int>
|
---|
| 192 | MOIndexSpace::nmo() const { return nmo_; }
|
---|
| 193 |
|
---|
| 194 | vector<int>
|
---|
| 195 | MOIndexSpace::offsets() const { return offsets_; }
|
---|
| 196 |
|
---|
| 197 | int
|
---|
| 198 | MOIndexSpace::to_full_space(const int i) const { return map_to_full_space_.at(i); }
|
---|
| 199 |
|
---|
| 200 | void
|
---|
| 201 | MOIndexSpace::check_mosym() const
|
---|
| 202 | {
|
---|
| 203 | int ng = basis_->molecule()->point_group()->char_table().order();
|
---|
| 204 |
|
---|
| 205 | for(vector<int>::const_iterator p=mosym_.begin(); p != mosym_.end(); ++p) {
|
---|
| 206 | if (*p < 0 || *p >= ng)
|
---|
| 207 | throw std::runtime_error("MOIndexSpace::check_mosym() -- invalid value in the list of orbital irreps");
|
---|
| 208 | }
|
---|
| 209 | }
|
---|
| 210 |
|
---|
| 211 |
|
---|
| 212 | void
|
---|
| 213 | MOIndexSpace::frozen_to_blockinfo(const int nfzc, const int nfzv, const RefDiagSCMatrix& evals)
|
---|
| 214 | {
|
---|
| 215 | int rank = evals.dim().n();
|
---|
| 216 |
|
---|
| 217 | int nb = evals.dim()->blocks()->nblock();
|
---|
| 218 | nmo_.resize(nb);
|
---|
| 219 | offsets_.resize(nb);
|
---|
| 220 | for(int b=0; b<nb; b++) {
|
---|
| 221 | nmo_[b] = evals.dim()->blocks()->size(b);
|
---|
| 222 | offsets_[b] = 0;
|
---|
| 223 | }
|
---|
| 224 |
|
---|
| 225 | // Get the energies of the orbitals in this space
|
---|
| 226 | double* energy = new double[rank];
|
---|
| 227 | int* index_map = new int[rank];
|
---|
| 228 | vector<int> blocked_index_to_irrep(rank);
|
---|
| 229 | int ii = 0; // blocked index to this space
|
---|
| 230 | int offset = 0;
|
---|
| 231 | for(int b=0; b<nb; b++) {
|
---|
| 232 | for(int i=0; i<nmo_[b]; i++, ii++) {
|
---|
| 233 | energy[ii] = evals.get_element(i+offset);
|
---|
| 234 | blocked_index_to_irrep[ii] = b;
|
---|
| 235 | }
|
---|
| 236 | offset += nmo_[b];
|
---|
| 237 | }
|
---|
| 238 |
|
---|
| 239 | // Do the sort
|
---|
| 240 | dquicksort(energy,index_map,rank);
|
---|
| 241 | delete[] energy;
|
---|
| 242 |
|
---|
| 243 | // Get rid of nfzc lowest orbitals
|
---|
| 244 | for(int i=0; i<nfzc; i++) {
|
---|
| 245 | int b = blocked_index_to_irrep[index_map[i]];
|
---|
| 246 | ++offsets_[b];
|
---|
| 247 | --nmo_[b];
|
---|
| 248 | }
|
---|
| 249 |
|
---|
| 250 | // Get rid of nfzv highest orbitals
|
---|
| 251 | for(int i=rank-nfzv; i<rank; i++) {
|
---|
| 252 | int b = blocked_index_to_irrep[index_map[i]];
|
---|
| 253 | --nmo_[b];
|
---|
| 254 | }
|
---|
| 255 |
|
---|
| 256 | delete[] index_map;
|
---|
| 257 | }
|
---|
| 258 |
|
---|
| 259 | void
|
---|
| 260 | MOIndexSpace::full_coefs_to_coefs(const RefSCMatrix& full_coefs, const RefDiagSCMatrix& evals)
|
---|
| 261 | {
|
---|
| 262 | // compute the rank of this
|
---|
| 263 | rank_ = 0;
|
---|
| 264 | for(vector<int>::const_iterator p=nmo_.begin(); p != nmo_.end(); ++p) {
|
---|
| 265 | rank_ += *p;
|
---|
| 266 | }
|
---|
| 267 |
|
---|
| 268 | mosym_.resize(rank_);
|
---|
| 269 | RefSCDimension modim = full_coefs.coldim(); // the dimension of the full space
|
---|
| 270 |
|
---|
| 271 | // In general vectors are ordered differently from the original
|
---|
| 272 | int* index_map = new int[rank_]; // maps index in this (sorted) space to this (blocked) space
|
---|
| 273 | vector<int> blocked_subindex_to_full_index(rank_); // maps index from this space(in blocked form) into the full space
|
---|
| 274 | vector<int> blocked_subindex_to_irrep(rank_); // maps index from this space(in blocked form) to the irrep
|
---|
| 275 | if (moorder_ == symmetry) {
|
---|
| 276 | // coefs_ has the same number of blocks as full_coefs_
|
---|
| 277 | int nb = modim->blocks()->nblock();
|
---|
| 278 | int* nfunc_per_block = new int[nb];
|
---|
| 279 | for(int i=0; i<nb; i++)
|
---|
| 280 | nfunc_per_block[i] = nmo_[i];
|
---|
| 281 | modim_ = new SCDimension(rank_, nb, nfunc_per_block, ("MO(" + name_ + ")").c_str());
|
---|
| 282 | for(int i=0; i<nb; i++)
|
---|
| 283 | modim_->blocks()->set_subdim(i, new SCDimension(nfunc_per_block[i]));
|
---|
| 284 | delete[] nfunc_per_block;
|
---|
| 285 |
|
---|
| 286 | // The sorted->blocked reordering array is trivial when no resorting is done
|
---|
| 287 | for(int i=0; i<rank_; i++) {
|
---|
| 288 | index_map[i] = i;
|
---|
| 289 | }
|
---|
| 290 |
|
---|
| 291 | int ii = 0; // blocked index to this space
|
---|
| 292 | int offset = 0;
|
---|
| 293 | for(int b=0; b<nb; b++) {
|
---|
| 294 | for(int i=0; i<nmo_[b]; i++, ii++) {
|
---|
| 295 | blocked_subindex_to_full_index[ii] = i+offsets_[b]+offset;
|
---|
| 296 | blocked_subindex_to_irrep[ii] = b;
|
---|
| 297 | }
|
---|
| 298 | offset += modim->blocks()->size(b);
|
---|
| 299 | }
|
---|
| 300 | }
|
---|
| 301 | else if (moorder_ == energy) {
|
---|
| 302 | //
|
---|
| 303 | // Sort vectors by their energy
|
---|
| 304 | //
|
---|
| 305 |
|
---|
| 306 | // Get the energies of the orbitals in this space
|
---|
| 307 | double* energy = new double[rank_];
|
---|
| 308 | int nb = nmo_.size();
|
---|
| 309 | int ii = 0; // blocked index to this space
|
---|
| 310 | int offset = 0;
|
---|
| 311 | for(int b=0; b<nb; b++) {
|
---|
| 312 | for(int i=0; i<nmo_[b]; i++, ii++) {
|
---|
| 313 | energy[ii] = evals.get_element(i+offsets_[b]+offset);
|
---|
| 314 | blocked_subindex_to_full_index[ii] = i+offsets_[b]+offset;
|
---|
| 315 | blocked_subindex_to_irrep[ii] = b;
|
---|
| 316 | }
|
---|
| 317 | offset += modim->blocks()->size(b);
|
---|
| 318 | }
|
---|
| 319 |
|
---|
| 320 | // Do the sort
|
---|
| 321 | dquicksort(energy,index_map,rank_);
|
---|
| 322 |
|
---|
| 323 | // coefs_ has 1 block
|
---|
| 324 | int* nfunc_per_block = new int[1];
|
---|
| 325 | nfunc_per_block[0] = rank_;
|
---|
| 326 | modim_ = new SCDimension(rank_, 1, nfunc_per_block, ("MO(" + name_ + ")").c_str());
|
---|
| 327 | modim_->blocks()->set_subdim(0, new SCDimension(nfunc_per_block[0]));
|
---|
| 328 |
|
---|
| 329 | // Recompute offsets_ and nmo_ to conform the energy ordering
|
---|
| 330 | offset = 0;
|
---|
| 331 | for(vector<int>::const_iterator p=offsets_.begin(); p != offsets_.end(); ++p) {
|
---|
| 332 | offset += *p;
|
---|
| 333 | }
|
---|
| 334 | offsets_.resize(1);
|
---|
| 335 | offsets_[0] = offset;
|
---|
| 336 | nmo_.resize(1);
|
---|
| 337 | nmo_[0] = rank_;
|
---|
| 338 |
|
---|
| 339 | delete[] energy;
|
---|
| 340 | delete[] nfunc_per_block;
|
---|
| 341 | }
|
---|
| 342 | else
|
---|
| 343 | throw std::runtime_error("MOIndexSpace::full_coefs_to_coefs() -- moorder should be either energy or symmetry");
|
---|
| 344 |
|
---|
| 345 | // Copy required columns of full_coefs_ into coefs_
|
---|
| 346 | RefSCDimension aodim = full_coefs.rowdim();
|
---|
| 347 | Ref<SCMatrixKit> so_matrixkit = basis_->so_matrixkit();
|
---|
| 348 | coefs_ = so_matrixkit->matrix(aodim, modim_);
|
---|
| 349 | evals_ = so_matrixkit->diagmatrix(modim_);
|
---|
| 350 | for (int i=0; i<rank_; i++) {
|
---|
| 351 | int ii = blocked_subindex_to_full_index[index_map[i]];
|
---|
| 352 | mosym_[i] = blocked_subindex_to_irrep[index_map[i]];
|
---|
| 353 | for (int j=0; j<aodim.n(); j++) {
|
---|
| 354 | coefs_(j,i) = full_coefs(j,ii);
|
---|
| 355 | }
|
---|
| 356 | }
|
---|
| 357 | if (evals.nonnull())
|
---|
| 358 | for (int i=0; i<rank_; i++) {
|
---|
| 359 | int ii = blocked_subindex_to_full_index[index_map[i]];
|
---|
| 360 | evals_(i) = evals(ii);
|
---|
| 361 | }
|
---|
| 362 | else
|
---|
| 363 | evals_.assign(0.0);
|
---|
| 364 |
|
---|
| 365 | nblocks_ = modim_->blocks()->nblock();
|
---|
| 366 |
|
---|
| 367 | // Compute the map to the full space
|
---|
| 368 | map_to_full_space_.resize(rank_);
|
---|
| 369 | for (int i=0; i<rank_; i++) {
|
---|
| 370 | map_to_full_space_[i] = blocked_subindex_to_full_index[index_map[i]];
|
---|
| 371 | }
|
---|
| 372 |
|
---|
| 373 | delete[] index_map;
|
---|
| 374 | }
|
---|
| 375 |
|
---|
| 376 | void
|
---|
| 377 | MOIndexSpace::init()
|
---|
| 378 | {
|
---|
| 379 | }
|
---|
| 380 |
|
---|
| 381 |
|
---|
| 382 | size_t
|
---|
| 383 | MOIndexSpace::memory_in_use() const
|
---|
| 384 | {
|
---|
| 385 | size_t memory = (size_t)basis_->nbasis() * rank_ * sizeof(double);
|
---|
| 386 | return memory;
|
---|
| 387 | }
|
---|
| 388 |
|
---|
| 389 | void
|
---|
| 390 | MOIndexSpace::print(ostream&o) const
|
---|
| 391 | {
|
---|
| 392 | o << indent << "MOIndexSpace \"" << name_ << "\":" << endl;
|
---|
| 393 | o << incindent;
|
---|
| 394 | o << indent << "Basis Set:" << endl;
|
---|
| 395 | o << incindent; basis_->print(o); o << decindent << endl;
|
---|
| 396 | o << decindent;
|
---|
| 397 | }
|
---|
| 398 |
|
---|
| 399 | void
|
---|
| 400 | MOIndexSpace::print_summary(ostream& o) const
|
---|
| 401 | {
|
---|
| 402 | o << indent << "MOIndexSpace \"" << name_ << "\":" << endl;
|
---|
| 403 | o << incindent;
|
---|
| 404 | o << indent << "GaussianBasisSet \"" << basis_->name() << "\""<< endl;
|
---|
| 405 | o << indent << " rank nbasis nshell nfuncmax" << endl;
|
---|
| 406 | o << indent << scprintf(" %-6i %-6i %-6i %-6i",
|
---|
| 407 | rank_,
|
---|
| 408 | basis_->nbasis(),
|
---|
| 409 | basis_->nshell(),
|
---|
| 410 | basis_->max_nfunction_in_shell()) << endl;
|
---|
| 411 | o << decindent;
|
---|
| 412 |
|
---|
| 413 | }
|
---|
| 414 |
|
---|
| 415 | /////////////////////////////////////////////////////////////////
|
---|
| 416 | // Function dquicksort performs a quick sort (smaller -> larger)
|
---|
| 417 | // of the double data in item by the integer indices in index;
|
---|
| 418 | // data in item remain unchanged
|
---|
| 419 | //
|
---|
| 420 | // Both functions borrowed from lib/chemistry/qc/mbpt/mbpt.cc
|
---|
| 421 | //
|
---|
| 422 | /////////////////////////////////////////////////////////////////
|
---|
| 423 | void
|
---|
| 424 | MOIndexSpace::dqs(double *item,int *index,int left,int right)
|
---|
| 425 | {
|
---|
| 426 | int i,j;
|
---|
| 427 | double x;
|
---|
| 428 | int y;
|
---|
| 429 | const double small_diff = 1.0e-12;
|
---|
| 430 |
|
---|
| 431 | i=left; j=right;
|
---|
| 432 | x=item[index[(left+right)/2]];
|
---|
| 433 |
|
---|
| 434 | do {
|
---|
| 435 | while(item[index[i]]<x && fabs(x-item[index[i]]) > small_diff && i<right) i++;
|
---|
| 436 | while(x<item[index[j]] && fabs(x-item[index[j]]) > small_diff && j>left) j--;
|
---|
| 437 |
|
---|
| 438 | if (i<=j) {
|
---|
| 439 | if (fabs(item[index[i]] - item[index[j]]) > small_diff) {
|
---|
| 440 | y=index[i];
|
---|
| 441 | index[i]=index[j];
|
---|
| 442 | index[j]=y;
|
---|
| 443 | }
|
---|
| 444 | i++; j--;
|
---|
| 445 | }
|
---|
| 446 | } while(i<=j);
|
---|
| 447 |
|
---|
| 448 | if (left<j) dqs(item,index,left,j);
|
---|
| 449 | if (i<right) dqs(item,index,i,right);
|
---|
| 450 | }
|
---|
| 451 |
|
---|
| 452 | namespace {
|
---|
| 453 | // use this to compute permutation corresponding to a sort
|
---|
| 454 | class IndexedValue {
|
---|
| 455 | int index_;
|
---|
| 456 | double value_;
|
---|
| 457 | public:
|
---|
| 458 | IndexedValue(int index, double value) : index_(index), value_(value) {}
|
---|
| 459 | int index() const { return index_; }
|
---|
| 460 | double value() const { return value_; }
|
---|
| 461 |
|
---|
| 462 | bool operator<(const IndexedValue& a) const {
|
---|
| 463 | const double small_diff = 1.0e-12;
|
---|
| 464 | if (fabs(value_-a.value_) < small_diff)
|
---|
| 465 | return false;
|
---|
| 466 | else
|
---|
| 467 | return value_ < a.value_;
|
---|
| 468 | }
|
---|
| 469 | };
|
---|
| 470 |
|
---|
| 471 | };
|
---|
| 472 |
|
---|
| 473 |
|
---|
| 474 | void
|
---|
| 475 | MOIndexSpace::dquicksort(double *item,int *index,int n)
|
---|
| 476 | {
|
---|
| 477 | if (n<=0) return;
|
---|
| 478 | typedef vector<IndexedValue> vectype;
|
---|
| 479 | typedef vector<IndexedValue>::iterator iter;
|
---|
| 480 | vector<IndexedValue> vals;
|
---|
| 481 | for (int i=0; i<n; i++) {
|
---|
| 482 | IndexedValue val(i,item[i]);
|
---|
| 483 | vals.push_back(val);
|
---|
| 484 | }
|
---|
| 485 | stable_sort(vals.begin(),vals.end());
|
---|
| 486 | for (int i=0; i<n; i++) {
|
---|
| 487 | index[i] = vals.at(i).index();
|
---|
| 488 | }
|
---|
| 489 | }
|
---|
| 490 |
|
---|
| 491 |
|
---|
| 492 | /////////////////////////////////////////////////////////////////////////////
|
---|
| 493 |
|
---|
| 494 | // Local Variables:
|
---|
| 495 | // mode: c++
|
---|
| 496 | // c-file-style: "CLJ-CONDENSED"
|
---|
| 497 | // End:
|
---|