OverviewFilesCommitsIssuesDocsReleasesPeers

opencog-atomspace commits / 8e06d2a

Provide tail-recursive AtomSpace::depth()
8e06d2af611d95c73423463bed73c0007b1ac788
by Linas Vepštas <linasvepstas@gmail.com> · 2026-01-22T03:16:08.000Z

Changed files (1) +28 -16

opencog/atomspace/AtomSpace.cc +28 -16
……@@ -418,24 +418,42 @@ Handle AtomSpace::getOutgoingAtom(Arity n) const
418418}
419419
420420// ====================================================================
421// XXX FIXME -- The recursive design of the depth() routine below makes
422// it into a bottleneck, when the stack of AtomSpaces exceeds a few
423// hundred. In particular, the recursion is on the C stack, and I don't
424// believe the compiler has optimized them to be tail-recursive. (If
425// they are tail-recursive, I guess that's OK, eh?)
426// At this time, the only user of this code appears to be UniqueLink.cc
427// It is NOT used by Rocks.
428
421/// Search for the given AtomSpace in our stack. Return a count to
422/// the shallowest copy found. Return -1 if the AtomSpace is not found
423/// in the stack.
424// Tail-recursive implementation, should be fast.
429425int AtomSpace::depth(const AtomSpace* as) const
430426{
431427 if (nullptr == as) return -1;
432428 if (as == this) return 0;
433429
430 // As long as _environ is exactly one in size, just loop.
431 int lvl = 1;
432 const std::vector<AtomSpacePtr>* env = &_environ;
433 while (true)
434 {
435 size_t evs = env->size();
436 if (0 == evs) return -1;
437 if (1 < evs) break;
438 if (as == (*env)[0].get()) return lvl;
439 lvl++;
440 env = &((*env)[0]->_environ);
441 }
442
443 // Hunt for shallowest.
444 int shallowest = -1;
434445 for (const AtomSpacePtr& base : _environ)
435446 {
436447 int d = base->depth(as);
437 if (0 <= d) return d+1;
448 if (0 <= d and
449 ((-1 == shallowest) or (d < shallowest)))
450 {
451 shallowest = d;
452 }
438453 }
454 if (0 <= shallowest)
455 return lvl + shallowest;
456
439457 return -1;
440458}
441459
……@@ -444,13 +462,7 @@ int AtomSpace::depth(const Handle& atom) const
444462 if (nullptr == atom) return -1;
445463 AtomSpace* as = atom->getAtomSpace();
446464 if (as == this) return 0;
447
448 for (const AtomSpacePtr& base : _environ)
449 {
450 int d = base->depth(as);
451 if (0 <= d) return d+1;
452 }
453 return -1;
465 return depth(as);
454466}
455467
456468bool AtomSpace::in_environ(const AtomSpace* as) const