private boolean applyBeforeUpdateUndirected(Update u) {
    if (u instanceof NodeAddition) {
      Node n = (Node) ((NodeAddition) u).getNode();
      this.localCC.setValue(n.getIndex(), 0);
      this.nodePotentialCount =
          ArrayUtils.set(this.nodePotentialCount, n.getIndex(), 0, Long.MIN_VALUE);
      this.nodeTriangleCount =
          ArrayUtils.set(this.nodeTriangleCount, n.getIndex(), 0, Long.MIN_VALUE);
      this.averageCC = ArrayUtils.avgIgnoreNaN(this.localCC.getValues());
    } else if (u instanceof NodeRemoval) {
      UndirectedNode n = (UndirectedNode) ((NodeRemoval) u).getNode();

      UndirectedNode[] neighbors = new UndirectedNode[n.getDegree()];
      int index = 0;
      for (IElement eUncasted : n.getEdges()) {
        UndirectedEdge e = (UndirectedEdge) eUncasted;
        neighbors[index++] = e.getDifferingNode(n);
      }

      for (int i = 0; i < neighbors.length; i++) {
        for (int j = i + 1; j < neighbors.length; j++) {
          if (neighbors[i].hasEdge(new UndirectedEdge(neighbors[i], neighbors[j]))) {
            this.removeTriangle(n);
            this.removeTriangle(neighbors[i]);
            this.removeTriangle(neighbors[j]);
          }
        }
        this.removePotentials(neighbors[i], neighbors[i].getDegree() - 1);
      }

      this.removePotentials(n, n.getDegree() * (n.getDegree() - 1) / 2);

      this.localCC.setValue(n.getIndex(), NodeValueList.emptyValue);
      this.nodePotentialCount[n.getIndex()] = Long.MIN_VALUE;
      this.nodeTriangleCount[n.getIndex()] = Long.MIN_VALUE;
      this.localCC.truncate();
      this.nodePotentialCount = ArrayUtils.truncate(this.nodePotentialCount, Long.MIN_VALUE);
      this.nodeTriangleCount = ArrayUtils.truncate(this.nodeTriangleCount, Long.MIN_VALUE);
    } else if (u instanceof EdgeAddition) {
      UndirectedEdge e = (UndirectedEdge) ((EdgeAddition) u).getEdge();
      UndirectedNode a = e.getNode1();
      UndirectedNode b = e.getNode2();
      // new triangles
      for (IElement c_Uncasted : a.getEdges()) {
        UndirectedEdge c_ = (UndirectedEdge) c_Uncasted;
        UndirectedNode c = c_.getDifferingNode(a);
        if (c.hasEdge(new UndirectedEdge(c, b))) {
          this.addTriangle(a);
          this.addTriangle(b);
          this.addTriangle(c);
        }
      }
      // new potentials
      this.addPotentials(a, a.getDegree());
      this.addPotentials(b, b.getDegree());
    }
    return true;
  }
  private boolean applyBeforeUpdateDirected(Update u) {
    if (u instanceof NodeAddition) {
      Node n = (Node) ((NodeAddition) u).getNode();
      this.localCC.setValue(n.getIndex(), 0);
      this.nodePotentialCount =
          ArrayUtils.set(this.nodePotentialCount, n.getIndex(), 0, Long.MIN_VALUE);
      this.nodeTriangleCount =
          ArrayUtils.set(this.nodeTriangleCount, n.getIndex(), 0, Long.MIN_VALUE);
      this.averageCC = ArrayUtils.avgIgnoreNaN(this.localCC.getValues());
    } else if (u instanceof NodeRemoval) {

      DirectedNode n = (DirectedNode) ((NodeRemoval) u).getNode();

      DirectedNode[] neighbors = new DirectedNode[n.getNeighborCount()];
      int index = 0;
      for (IElement neighbor : n.getNeighbors()) {
        neighbors[index++] = (DirectedNode) neighbor;
      }

      for (int i = 0; i < neighbors.length; i++) {
        for (int j = i + 1; j < neighbors.length; j++) {
          if (neighbors[i].hasEdge(new DirectedEdge(neighbors[i], neighbors[j]))
              && neighbors[i].hasEdge(new DirectedEdge(neighbors[j], neighbors[i]))) {
            this.removeTriangle(n);
            this.removeTriangle(neighbors[i]);
            this.removeTriangle(neighbors[j]);
          }
        }
        this.removePotentials(neighbors[i], neighbors[i].getNeighborCount() - 1);
      }

      this.removePotentials(n, n.getNeighborCount() * (n.getNeighborCount() - 1) / 2);

      this.localCC.setValue(n.getIndex(), NodeValueList.emptyValue);
      this.nodePotentialCount[n.getIndex()] = Long.MIN_VALUE;
      this.nodeTriangleCount[n.getIndex()] = Long.MIN_VALUE;
      this.localCC.truncate();
      this.nodePotentialCount = ArrayUtils.truncate(this.nodePotentialCount, Long.MIN_VALUE);
      this.nodeTriangleCount = ArrayUtils.truncate(this.nodeTriangleCount, Long.MIN_VALUE);

      this.averageCC = ArrayUtils.avgIgnoreNaN(this.localCC.getValues());

    } else if (u instanceof EdgeAddition) {
      DirectedEdge e = (DirectedEdge) ((EdgeAddition) u).getEdge();
      DirectedNode a = e.getSrc();
      DirectedNode b = e.getDst();
      if (a.hasEdge(new DirectedEdge(b, a))) {
        // new triangles
        for (IElement cUncasted : a.getNeighbors()) {
          DirectedNode c = (DirectedNode) cUncasted;
          if (b.hasNeighbor(c)) {
            this.addTriangle(a);
            this.addTriangle(b);
            this.addTriangle(c);
          }
        }
        // new potentials
        this.addPotentials(a, a.getNeighborCount());
        this.addPotentials(b, b.getNeighborCount());
      }
    }
    return true;
  }