whole_func_string: function _equals(x, y, rc) {
      if (rc.count > rc.maxStackDepth)
          throw new Error("Stack depth exceeded: " + rc.maxStackDepth + "!");
      // check for reference and primitive equality
      if (x === y)
          return true;
      // check for type equality
      let xType = getType(x);
      let yType = getType(y);
      if (xType !== yType)
          return false;
      // check for circular references
      let xIndex = rc.xStack.lastIndexOf(x);
      let yIndex = rc.yStack.lastIndexOf(y);
      if (xIndex !== -1) {
          if (yIndex === xIndex)
              return true;
      }
      // check for inequalities
      switch(xType) {
          case types.number:
              if (x !== y) {
                  if (isNaN(x) && isNaN(y))
                      return true;
                  return false;
              }
              break;
          case types.date:
              if (x.getTime() !== y.getTime())
                  return false;
              // check for extra properties stored on the Date object
              if (!_compareObject(x, y, rc))
                  return false;
              break;
          case types.array:
              if (x.length !== y.length)
                  return false;
              rc.push(x, y);
              for (let i = 0; i < x.length; i++) {
                  if (!_equals(x[i], y[i], rc))
                      return false;
              }
              rc.pop();
              break;
          case types.map:
              if (x.size !== y.size)
                  return false;
              let xMapArr = [...x]; // these need to be sorted by key before comparison
              let yMapArr = [...y]; // order shouldn't matter, as long as they are the same
              xMapArr.sort((a, b) => {
                  return a[0] > b[0] ? 1 : a[0] < b[0] ? -1 : 0;
              });
              yMapArr.sort((a, b) => {
                  return a[0] > b[0] ? 1 : a[0] < b[0] ? -1 : 0;
              });
              if (!_equals(xMapArr, yMapArr, rc))
                  return false;
              break;
          case types.set:
              if (x.size !== y.size)
                  return false;
              let xArr = [...x]; // consider doing a comparison without converting to array?
              let yArr = [...y]; // converting to array may still be the fastest option.
              if (!_equals(xArr, yArr, rc))
                  return false;
              break;
          case types.function:
              if (!_compareObject(x, y, rc)) // check for properties on function
                  return false;
              if (x !== y)
                  return false; // other than that, just use reference equality for now
              break;
          case types.object:
              if (Buffer.isBuffer(x)) {
                  if (!Buffer.isBuffer(y))
                      return false;
                  if (x.length !== y.length)
                      return false;
                  if (!x.equals(y))
                      return false;
              }
              else {
                  if (!_compareObject(x, y, rc))
                      return false;
              }
              break;
          case types.regexp:
              if (!_equals(x.toString(), y.toString(), rc))
                  return false;
              if (!_compareObject(x, y, rc))
                  return false;
              break;
          case types.boolean:
          case types.string:
          case types.symbol:
              if (x !== y)
                  return false;
              break;
          default:
              if (!_compareObject(x, y, rc))
                  return false;
              break;
      }
      return true;
  }
func_code_string: function _equals(x, y, rc) {
      if (rc.count > rc.maxStackDepth)
          throw new Error("Stack depth exceeded: " + rc.maxStackDepth + "!");
      // check for reference and primitive equality
      if (x === y)
          return true;
      // check for type equality
      let xType = getType(x);
      let yType = getType(y);
      if (xType !== yType)
          return false;
      // check for circular references
      let xIndex = rc.xStack.lastIndexOf(x);
      let yIndex = rc.yStack.lastIndexOf(y);
      if (xIndex !== -1) {
          if (yIndex === xIndex)
              return true;
      }
      // check for inequalities
      switch(xType) {
          case types.number:
              if (x !== y) {
                  if (isNaN(x) && isNaN(y))
                      return true;
                  return false;
              }
              break;
          case types.date:
              if (x.getTime() !== y.getTime())
                  return false;
              // check for extra properties stored on the Date object
              if (!_compareObject(x, y, rc))
                  return false;
              break;
          case types.array:
              if (x.length !== y.length)
                  return false;
              rc.push(x, y);
              for (let i = 0; i < x.length; i++) {
                  if (!_equals(x[i], y[i], rc))
                      return false;
              }
              rc.pop();
              break;
          case types.map:
              if (x.size !== y.size)
                  return false;
              let xMapArr = [...x]; // these need to be sorted by key before comparison
              let yMapArr = [...y]; // order shouldn't matter, as long as they are the same
              xMapArr.sort((a, b) => {
                  return a[0] > b[0] ? 1 : a[0] < b[0] ? -1 : 0;
              });
              yMapArr.sort((a, b) => {
                  return a[0] > b[0] ? 1 : a[0] < b[0] ? -1 : 0;
              });
              if (!_equals(xMapArr, yMapArr, rc))
                  return false;
              break;
          case types.set:
              if (x.size !== y.size)
                  return false;
              let xArr = [...x]; // consider doing a comparison without converting to array?
              let yArr = [...y]; // converting to array may still be the fastest option.
              if (!_equals(xArr, yArr, rc))
                  return false;
              break;
          case types.function:
              if (!_compareObject(x, y, rc)) // check for properties on function
                  return false;
              if (x !== y)
                  return false; // other than that, just use reference equality for now
              break;
          case types.object:
              if (Buffer.isBuffer(x)) {
                  if (!Buffer.isBuffer(y))
                      return false;
                  if (x.length !== y.length)
                      return false;
                  if (!x.equals(y))
                      return false;
              }
              else {
                  if (!_compareObject(x, y, rc))
                      return false;
              }
              break;
          case types.regexp:
              if (!_equals(x.toString(), y.toString(), rc))
                  return false;
              if (!_compareObject(x, y, rc))
                  return false;
              break;
          case types.boolean:
          case types.string:
          case types.symbol:
              if (x !== y)
                  return false;
              break;
          default:
              if (!_compareObject(x, y, rc))
                  return false;
              break;
      }
      return true;
  }
func_documentation_string: Internal method for comparing the equivalence of items.
  
  @param x The first item to compare.
  @param y The second item to compare.
  @param rc The running counter for comparing circular references.
  @returns {boolean} An indication as to whether or not x and y were equal.