00001 /*
00002 File: SparseVec.cc
00003
00004 Function: Implements SparseVec.h
00005
00006 Author(s): Andrew Willmott
00007
00008 Copyright: (c) 1995-2000, Andrew Willmott
00009
00010 Notes:
00011
00012 */
00013
00014
00015 #include "vl/SparseVec.h"
00016 #include <stdarg.h>
00017 #include <iomanip.h>
00018 #include "vl/SparseVec.h"
00019 #include "vl/SubSVec.h"
00020
00021
00022 TSparseVec::TSparseVec() : TSVList(), elts(0)
00023 {
00024 End();
00025 }
00026
00027 TSparseVec::TSparseVec(Int n) : TSVList(), elts(n)
00028 {
00029 Assert(n > 0,"(SparseVec) illegal vector size");
00030 }
00031
00032 TSparseVec::TSparseVec(const TSparseVec &v) : TSVList(v), elts(v.elts)
00033 {
00034 }
00035
00036 TSparseVec::TSparseVec(const TSubSVec &v) : TSVList()
00037 {
00038 SELF = v;
00039 }
00040
00041 TSparseVec::TSparseVec(const TVec &v) : TSVList()
00042 {
00043 SELF = v;
00044 }
00045
00046 TSparseVec::TSparseVec(Int n, Int indices[], TVReal elts[]) : TSVList(), elts(n)
00047 {
00048 Assert(n > 0,"(SparseVec) illegal vector size");
00049 Int i = 0;
00050
00051 while (1)
00052 {
00053 if (indices[i] < 0)
00054 break;
00055 AddElt(indices[i], elts[i]);
00056 i++;
00057 }
00058
00059 End();
00060 }
00061
00062 TSparseVec::TSparseVec(Int n, Int idx0, double elt0, ...) : TSVList(), elts(n)
00063 {
00064 Assert(n > 0,"(SparseVec) illegal vector size");
00065 va_list ap;
00066 Int idx;
00067 TVReal elt;
00068
00069 va_start(ap, elt0);
00070 Assert(idx0 >= 0 && idx0 < elts, "(SparseVec) illegal first index");
00071 SetReal(elt, elt0);
00072 AddElt(idx0, elt);
00073
00074 while (1)
00075 {
00076 idx = va_arg(ap, Int);
00077 if (idx < 0)
00078 break;
00079 Assert(idx < elts, "(SparseVec) illegal index");
00080 SetReal(elt, va_arg(ap, double));
00081 AddElt(idx, elt);
00082 }
00083
00084 End();
00085 va_end(ap);
00086 }
00087
00088 TSparseVec::TSparseVec(Int n, ZeroOrOne k) : elts(n)
00089 {
00090 Assert(n > 0,"(SparseVec) illegal vector size");
00091 MakeBlock(k);
00092 }
00093
00094 TSparseVec::TSparseVec(Int n, Axis a) : elts(n)
00095 {
00096 Assert(n > 0,"(SparseVec) illegal vector size");
00097 MakeUnit(a);
00098 }
00099
00100
00101 TSparseVec::~TSparseVec()
00102 {
00103 }
00104
00105 TSparseVec &TSparseVec::operator = (const TSparseVec &v)
00106 {
00107 Int i;
00108
00109 SetNumElts(v.Elts());
00110 Begin();
00111
00112 for (i = 0; i < v.NumItems() - 1; i++)
00113 Append(v[i]);
00114
00115 End();
00116
00117 return(SELF);
00118 }
00119
00120 TSparseVec &TSparseVec::operator = (const TVec &v)
00121 {
00122 Int i;
00123
00124 SetNumElts(v.Elts());
00125 Begin();
00126
00127 for (i = 0; i < v.Elts(); i++)
00128 AddElt(i, v[i]);
00129
00130 End();
00131
00132 return(SELF);
00133 }
00134
00135 TSparseVec &TSparseVec::operator = (const TSubSVec &v)
00136 {
00137 v.Store(SELF);
00138 return(SELF);
00139 }
00140
00141 Void TSparseVec::SetSize(Int n)
00142 {
00143 SetNumElts(n);
00144 Begin();
00145 End();
00146 }
00147
00148 Void TSparseVec::MakeZero()
00149 {
00150 Begin();
00151 End();
00152 }
00153
00154 Void TSparseVec::MakeUnit(Int i, TVReal k)
00155 {
00156 Begin();
00157 AddElt(i, k);
00158 End();
00159 }
00160
00161 Void TSparseVec::MakeBlock(TVReal k)
00162 {
00163 if (len(k) == 0.0)
00164 MakeZero();
00165 else
00166 _Error("(SparseVec::MakeBlock) Calling this method is a really dumb idea.");
00167 // What's the point of setting every member of a sparse vector to
00168 // something non-zero?
00169 }
00170
00171
00172 Bool TSparseVec::compactPrint = false;
00173 TVReal TSparseVec::fuzz = 1e-10;
00174
00175 Void TSparseVec::SetCompactPrint(Bool on)
00176 { compactPrint = on; }
00177
00178 Void TSparseVec::SetFuzz(TVReal theFuzz)
00179 { fuzz = theFuzz; }
00180
00181
00182 // --- Vector operations ------------------------------------------------------
00183
00184
00185 #include <ctype.h>
00186
00187 /* [Note]
00188
00189 When operating on sparse vectors in place, it is faster to create a
00190 new vector on the fly, and swap it in at the end, than to perform
00191 inserts/deletes on the original. (O(n) vs O(n^2).)
00192
00193 Supporting Analysis:
00194
00195 There will be O(n) new/deleted elts.
00196 Copying will involve O(n) copies in creating the new array, plus
00197 a temporary memory overhead the size of the old vector. Operating
00198 in place will require O(n) insert/deletes, each of which require
00199 O(n) copies, and thus requires O(n^2) copies overall.
00200 */
00201
00202 TSparseVec &operator += (TSparseVec &a, const TSparseVec &b)
00203 {
00204 TSparseVec t = a + b;
00205 a.Replace(t);
00206 return(a);
00207 }
00208
00209 TSparseVec &operator -= (TSparseVec &a, const TSparseVec &b)
00210 {
00211 TSparseVec t = a - b;
00212 a.Replace(t);
00213 return(a);
00214 }
00215
00216 TSparseVec &operator *= (TSparseVec &a, const TSparseVec &b)
00217 {
00218 TSparseVec t = a * b;
00219 a.Replace(t);
00220 return(a);
00221 }
00222
00223 TSparseVec &operator *= (TSparseVec &v, TVReal s)
00224 {
00225 TSparseVec t = v * s;
00226 v.Replace(t);
00227 return(v);
00228 }
00229
00230 TSparseVec &operator /= (TSparseVec &a, const TSparseVec &b)
00231 {
00232 TSparseVec t = a / b;
00233 a.Replace(t);
00234 return(a);
00235 }
00236
00237 TSparseVec &operator /= (TSparseVec &v, TVReal s)
00238 {
00239 TSparseVec t = v / s;
00240 v.Replace(t);
00241 return(v);
00242 }
00243
00244
00245 // --- Vec Comparison Operators -----------------------------------------------
00246
00247
00248 Bool operator == (const TSparseVec &a, const TSparseVec &b)
00249 {
00250 Assert(a.Elts() == b.Elts(), "(SparseVec::==) Vec sizes don't match");
00251
00252 if (a.NumItems() != b.NumItems())
00253 return(false);
00254 else
00255 {
00256 Int i;
00257
00258 for (i = 0; i < a.NumItems(); i++)
00259 if (a[i] != b[i])
00260 return(false);
00261
00262 return(true);
00263 }
00264 }
00265
00266 Bool operator != (const TSparseVec &a, const TSparseVec &b)
00267 {
00268 return(!(a == b));
00269 }
00270
00271
00272 // --- SparseVec Methods ------------------------------------------------------
00273
00274
00275 TSparseVec TSparseVec::Overlay(const TSparseVec &b) const
00276 {
00277 TSparseVec result(Elts());
00278 Int i, j;
00279
00280 for (i = 0, j = 0; ; )
00281 if (item[i].index == b[j].index)
00282 {
00283 if (item[i].index == VL_SV_MAX_INDEX)
00284 break;
00285
00286 result.AddNZElt(b[j]);
00287 i++;
00288 j++;
00289 }
00290 else if (item[i].index < b[j].index)
00291 { result.AddNZElt(item[i]); i++; }
00292 else
00293 { result.AddNZElt(b[j]); j++; }
00294
00295 result.End();
00296 return(result);
00297 }
00298
00299 Void TSparseVec::SetElts(Int idx0, double elt0, ...)
00300 {
00301 va_list ap;
00302 Int idx;
00303 TVReal elt;
00304
00305 va_start(ap, elt0);
00306 Begin();
00307 Assert(idx0 >= 0 && idx0 < elts, "(SparseVec::SetElts) illegal first index");
00308 SetReal(elt, elt0);
00309 AddElt(idx0, elt);
00310
00311 while (1)
00312 {
00313 idx = va_arg(ap, Int);
00314 if (idx < 0)
00315 break;
00316 Assert(idx < elts, "(SparseVec::SetElts) illegal index");
00317 SetReal(elt, va_arg(ap, double));
00318 AddElt(idx, elt);
00319 }
00320
00321 End();
00322 va_end(ap);
00323 }
00324
00325 Void TSparseVec::Set(Int index, TVReal elt)
00326 {
00327 TSVIter j(SELF);
00328
00329 if (len(elt) <= fuzz)
00330 return;
00331
00332 if (!j.IncTo(index))
00333 {
00334 Insert(j.PairIdx());
00335 Item(j.PairIdx()).index = index;
00336 }
00337
00338 Item(j.PairIdx()).elt = elt;
00339 }
00340
00341 TVReal TSparseVec::Get(Int index) const
00342 {
00343 TSVIter j(SELF);
00344
00345 if (j.IncTo(index))
00346 return(j.Data());
00347 else
00348 return(vl_zero);
00349 }
00350
00351 // --- Vec Arithmetic Operators -----------------------------------------------
00352
00353 TSparseVec operator + (const TSparseVec &a, const TSparseVec &b)
00354 {
00355 Assert(a.Elts() == b.Elts(), "(SparseVec::+) Vec sizes don't match");
00356
00357 TSparseVec result(a.Elts());
00358 Int i, j;
00359
00360 // Step through a and b in parallel
00361
00362 for (i = 0, j = 0; ; )
00363 if (a[i].index == b[j].index)
00364 {
00365 // We have two elements at the same index.
00366 // Are we at the end of both arrays?
00367 if (a[i].index == VL_SV_MAX_INDEX)
00368 break;
00369
00370 // If not, add the result
00371
00372 result.AddElt(a[i].index, a[i].elt + b[j].elt); // +
00373 i++;
00374 j++;
00375 }
00376 else if (a[i].index < b[j].index)
00377 // result[x] = a[i] + 0
00378 { result.AddNZElt(a[i]); i++; }
00379 else
00380 // result[x] = b[j] + 0
00381 { result.AddNZElt(b[j]); j++; }
00382
00383 result.End();
00384 return(result);
00385 }
00386
00387 TSparseVec operator - (const TSparseVec &a, const TSparseVec &b)
00388 {
00389 Assert(a.Elts() == b.Elts(), "(SparseVec::-) Vec sizes don't match");
00390
00391 TSparseVec result(a.Elts());
00392 Int i, j;
00393
00394 for (i = 0, j = 0; ; )
00395 if (a[i].index == b[j].index)
00396 {
00397 if (a[i].index == VL_SV_MAX_INDEX)
00398 break;
00399
00400 result.AddElt(a[i].index, a[i].elt - b[j].elt); // -
00401 i++;
00402 j++;
00403 }
00404 else if (a[i].index < b[j].index)
00405 { result.AddNZElt(a[i]); i++; }
00406 else
00407 { result.AddNZElt(b[j].index, -b[j].elt); j++; }
00408
00409 result.End();
00410 return(result);
00411 }
00412
00413 TSparseVec operator - (const TSparseVec &v)
00414 {
00415 TSparseVec result(v.Elts());
00416 Int i;
00417
00418 for (i = 0; i < v.NumItems() - 1; i++)
00419 result.AddNZElt(v[i].index, -v[i].elt);
00420
00421 result.End();
00422 return(result);
00423 }
00424
00425 TSparseVec operator * (const TSparseVec &a, const TSparseVec &b)
00426 {
00427 Assert(a.Elts() == b.Elts(), "(SparseVec::*) Vec sizes don't match");
00428
00429 TSparseVec result(a.Elts());
00430 TSVIter j(a);
00431 Int i;
00432
00433 for (i = 0; i < b.NumItems() - 1; i++)
00434 if (j.IncTo(b[i].index))
00435 result.AddElt(b[i].index, j.Data() * b[i].elt);
00436
00437 result.End();
00438 return(result);
00439 }
00440
00441 TSparseVec operator * (const TSparseVec &v, TVReal s)
00442 {
00443 TSparseVec result(v.Elts());
00444 Int i;
00445
00446 for (i = 0; i < v.NumItems() - 1; i++)
00447 result.AddElt(v[i].index, s * v[i].elt);
00448
00449 result.End();
00450 return(result);
00451 }
00452
00453 TSparseVec operator / (const TSparseVec &a, const TSparseVec &b)
00454 {
00455 Assert(a.Elts() == b.Elts(), "(SparseVec::/) Vec sizes don't match");
00456
00457 TSparseVec result(a.Elts());
00458 TSVIter j(a);
00459 Int i;
00460
00461 for (i = 0; i < b.NumItems() - 1; i++)
00462 if (j.IncTo(b[i].index))
00463 result.AddElt(b[i].index, j.Data() / b[i].elt);
00464
00465 result.End();
00466 return(result);
00467 }
00468
00469 TSparseVec operator / (const TSparseVec &v, TVReal s)
00470 {
00471 TSparseVec result(v.Elts());
00472 Int i;
00473 TVReal t = vl_1 / s;
00474
00475 for (i = 0; i < v.NumItems() - 1; i++)
00476 result.AddElt(v[i].index, v[i].elt * t);
00477
00478 result.End();
00479 return(result);
00480 }
00481
00482 TVReal dot(const TSparseVec &a, const TSparseVec &b)
00483 {
00484 Assert(a.Elts() == b.Elts(), "(SparseVec::dot) Vec sizes don't match");
00485
00486 TMReal sum = vl_zero;
00487 TSVIter j(a);
00488 Int i;
00489
00490 for (i = 0; i < b.NumItems() - 1; i++)
00491 if (j.IncTo(b[i].index))
00492 sum += j.Data() * b[i].elt;
00493
00494 return(sum);
00495 }
00496
00497 TVReal dot(const TSparseVec &a, const TVec &b)
00498 {
00499 Assert(a.Elts() == b.Elts(), "(SparseVec::dot) Vec sizes don't match");
00500
00501 TMReal sum = vl_zero;
00502 Int i;
00503
00504 for (i = 0; i < a.NumItems() - 1; i++)
00505 sum += a[i].elt * b[a[i].index];
00506
00507 return(sum);
00508 }
00509
00510 TSparseVec operator * (TVReal s, const TSparseVec &v)
00511 {
00512 return(v * s);
00513 }
00514
00515 TVReal sqrlen(const TSparseVec &v)
00516 {
00517 TVReal sum = vl_zero;
00518 Int i;
00519
00520 for (i = 0; i < v.NumItems() - 1; i++)
00521 sum += sqrlen(v[i].elt);
00522
00523 return(sum);
00524 }
00525
00526 TVReal len(const TSparseVec &v)
00527 {
00528 return(sqrt(sqrlen(v)));
00529 }
00530
00531 TSparseVec norm(const TSparseVec &v)
00532 {
00533 return(v / len(v));
00534 }
00535
00536
00537 // --- Vec Input & Output -----------------------------------------------------
00538
00539
00540 ostream &operator << (ostream &s, const TSparsePair &sp)
00541 {
00542 s << sp.index << ':' << sp.elt;
00543
00544 return(s);
00545 }
00546
00547 ostream &operator << (ostream &s, const TSparseVec &v)
00548 {
00549 if (TSparseVec::IsCompact())
00550 {
00551 Int i;
00552
00553 s << '[';
00554
00555 for (i = 0; i < v.NumItems() - 2; i++)
00556 s << v[i] << ' ';
00557
00558 s << v[i] << ']';
00559 }
00560 else
00561 {
00562 Int i, j;
00563
00564 s << '[';
00565
00566 for (i = 0, j = 0; i < v.Elts() - 1; i++)
00567 if (i < v[j].index)
00568 s << "0 ";
00569 else
00570 s << v[j++].elt << ' ';
00571
00572 if (i < v[j].index)
00573 s << "0]";
00574 else
00575 s << v[j].elt << ']';
00576 }
00577
00578 return(s);
00579 }
00580
00581 istream &operator >> (istream &s, TSparseVec &v)
00582 {
00583 Char c;
00584 Int i = 0;
00585 TVReal elt;
00586
00587 // Expected format: [a b c d ...]
00588
00589 while (isspace(s.peek())) // chomp white space
00590 s.get(c);
00591
00592 if (s.peek() == '[')
00593 {
00594 v.Begin();
00595
00596 s.get(c);
00597
00598 while (isspace(s.peek())) // chomp white space
00599 s.get(c);
00600
00601 while (s.peek() != ']')
00602 {
00603 s >> elt;
00604
00605 if (!s)
00606 {
00607 _Warning("Couldn't read array component");
00608 return(s);
00609 }
00610 else
00611 {
00612 v.AddElt(i, elt);
00613 i++;
00614 }
00615
00616 while (isspace(s.peek())) // chomp white space
00617 s.get(c);
00618 }
00619 s.get(c);
00620 }
00621 else
00622 {
00623 s.clear(ios::failbit);
00624 _Warning("Error: Expected '[' while reading array");
00625 return(s);
00626 }
00627
00628 v.End();
00629 v.SetNumElts(i);
00630
00631 return(s);
00632 }
00633
00634
00635 // --- SparseVec iterator -----------------------------------------------------
00636
00637
00638 Void TSVIter::OrdFindLinear(Int i)
00639 {
00640 // Linear search for the right pair
00641
00642 while (!AtEnd() && (i > Index()))
00643 pairIdx++;
00644 }
00645
00646 #define SV_MIXED_SEARCH
00647
00648 #ifndef __SV_CONST__
00649 #define __SV_CONST__
00650 static const Int kLinearSearchRange = 10; // Linear search over intervals smaller than this...
00651 static const Int kSparsenessEst = 5; // estimated elts per non-zero elt.
00652 static const Int kLSRSparse = kSparsenessEst * kLinearSearchRange;
00653 #endif
00654
00655 Void TSVIter::OrdFindBinary(Int i)
00656 // Move index to point to the pair that corresponds to i, or if no such pair exists,
00657 // the pair with the next index after i that does exist.
00658 {
00659 #ifdef SV_MIXED_SEARCH
00660 // Mixture of linear & binary, parameterised by kLinearSearchRange.
00661 // If the item we're looking for is farther away from the current
00662 // pair than kLSRSparse, we binary search.
00663
00664 if ((i - Index()) > kLSRSparse)
00665 {
00666 #endif
00667
00668 // --- Binary search on the pairs list-------------------------------------
00669
00670 // A really nice thing to do here would be to back out
00671 // hierarchically from the current index instead of just
00672 // giving up on it. Similar to storing the current octree
00673 // node in RT, and doing the same.
00674
00675 Int j = 0, k = list->NumItems() - 1, m;
00676
00677 // Test for trivial cases: i lies before or after the pairs list
00678
00679 if (k < 0 || i <= list->Item(j).index)
00680 { pairIdx = 0; return; }
00681 if (list->Item(k).index < i)
00682 { pairIdx = k + 1; return; }
00683 if (list->Item(k).index == i)
00684 { pairIdx = k; return; }
00685
00686 while(k > j + 1 + kLinearSearchRange)
00687 {
00688 // precondition: j.index < i < k.index
00689 Assert(list->Item(j).index < i && i < list->Item(k).index, "Precondition failed.");
00690
00691 // Naive midpoint picking
00692 m = (j + k) / 2; // m ~ [j+1..k-1]
00693
00694 // Linear midpoint picking
00695 // m = j + 1 + ((k - j - 1) * (i - list->Item(j))) / list->Item(k) - list->Item(j));
00696
00697 if (i > list->Item(m).index)
00698 j = m;
00699 else
00700 {
00701 k = m;
00702
00703 if (i >= list->Item(k).index)
00704 {
00705 pairIdx = k;
00706 return;
00707 }
00708 }
00709 }
00710
00711 pairIdx = j + 1;
00712
00713 #ifdef SV_MIXED_SEARCH
00714 }
00715
00716 while (i > Index()) // Linear search, assuming sentinel
00717 pairIdx++;
00718 #endif
00719 }
00720