anchor.diff:  % Helpers
   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   
  --spec cluster(centroids:centroids(), centroids:centroids()) -> centroids:centroids().
  -cluster([], RemoteCentroids) -> RemoteCentroids;
  -cluster(Centroids, RemoteCentroids) ->
  -    % TODO extract Radius into state
  -    Radius = case config:read(dc_clustering_radius) of
  -        failed -> exit(dc_clustering_radius_not_set);
  -        R when R > 0 -> R;
  -        _Else -> exit(dc_clustering_radius_invalid)
  -    end,
  -
  -    %% TODO avoid ++
  +-spec cluster(centroids:centroids(), centroids:centroids(), float()) -> centroids:centroids().
  +cluster([], RemoteCentroids, _Radius) -> RemoteCentroids;
  +cluster(Centroids, RemoteCentroids, Radius) ->
       NewCentroids = mathlib:aggloClustering(Centroids ++ RemoteCentroids, Radius),
       NormalizedCentroids = lists:map(fun (Centroid) ->
                   dc_centroids:set_relative_size(Centroid,
                       0.5 * dc_centroids:get_relative_size(Centroid))
                   end, NewCentroids),
  -    % XXX fails: 1 = lists:foldr(fun(S, Acc) -> Acc + S end, 0, NormalizedSizes),
       NormalizedCentroids.
   
   %% @doc Gets the clustering reset interval set in scalaris.cfg.
  
positive.code:     ;
  
  % return my clusters
  on_active({query_clustering, Pid}, {Centroids, _Epoch, _ResetTriggerState, _ClusterTriggerState} = State) ->
      comm:send(Pid, {query_clustering_response, Centroids}),
      State
      ;
  
  on_active({query_epoch, Pid},
      {_Centroids, Epoch,_ResetTriggerState, _ClusterTriggerState} = State) ->
      comm:send(Pid, {query_epoch_response, Epoch}),
      State
      .
  
  
negative.code: on_active({activate_clustering}, State) ->
      State;
      
  on_active({start_clustering_shuffle}, #state_active{cluster_trigger_state = C} = State) ->
      % start new clustering shuffle -> gossip communication
      NewClusterTriggerState = trigger:next(C),
      cyclon:get_subset_rand(1),
      State#state_active{cluster_trigger_state=NewClusterTriggerState}
      ;
  
  % ask vivaldi for network coordinate
  on_active({reset_clustering}
            , #state_active{reset_trigger_state = ResetTriggerState} = State) ->
      NewResetTriggerState = trigger:next(ResetTriggerState),
      vivaldi:get_coordinate(),
      State#state_active{reset_trigger_state=NewResetTriggerState}
      ;
  
  % reset the local state and start a new epoche
  on_active({vivaldi_get_coordinate_response, Coordinate, _Confidence}
             , #state_active{local_epoch=Epoch} = State) ->
      State#state_active{
          local_epoch=Epoch + 1
          , centroids=[dc_centroids:new(Coordinate, 1.0)]
      }
      ;
  
  on_active({cy_cache, []}, State)  ->
      % ignore empty cache from cyclon
      State;
  
  % got random node from cyclon
  on_active({cy_cache, [Node] = _Cache}
            , #state_active{centroids=C, local_epoch=E} = State) ->
      %io:format("~p~n",[_Cache]),
      comm:send(node:pidX(Node), {clustering_shuffle, comm:this(), C, E},
                [{group_member, dc_clustering}]),
      State;
  
  