
# This function accepts a "dist" or matrix of scores and
# returns an ordering, based on hierarchical clustering.
# If reorder is FALSE, the order returned by hclust is used, 
# otherwise clusters are ordered by placing the nearest end points
# adjacent to each other at a merge.
 
order.hclust <- 
function(merit,reorder=TRUE,...) {
    dis <- - merit
    if (is.matrix(dis)) 
    disd <- as.dist(dis)
    else {
	disd <- dis
	dis <- as.matrix(dis)}
    n <- nrow(dis)
    if (n <= 2)
    ord <- 1:n
    else {
	hc <- hclust(disd,...)
	if (reorder)
	hc <- reorder.hclust(hc,dis)
	ord <- hc$order}
    ord }


# This function accepts hc, the results of a hierarchical clustering
# and a "dist" or distance matrix. It returns a hierarchical clustering obtained by placing 
# the nearest end points adjacent to each other at each
#  merge of the hierarchical clustering


reorder.hclust <-
function(x,dis,...) {
    if (! is.matrix(dis)) dis <- as.matrix(dis)
    merges <- x$merge
    n <- nrow(merges)
    endpoints <- matrix(0,n,2)
    dir <- matrix(1L,n,2)
    for (i in 1L:n) {
	j <- merges[i,1]
	k <- merges[i,2]
	if ((j < 0) && (k < 0)) {
	    endpoints[i,1] <- -j
	    endpoints[i,2] <- -k}
	else if (j < 0) {
	    j <- -j
	    endpoints[i,1] <- j
	    e1 <- endpoints[k,1]; e2 <- endpoints[k,2]
	    if (dis[j,e1] < dis[j,e2])        
	    endpoints[i,2] <- e2
	    else {
		endpoints[i,2] <- e1
		dir[i,2] <- -1}}
	else if (k < 0) {
	    k <- -k
	    endpoints[i,2] <- k  
	    e1 <- endpoints[j,1]; e2 <- endpoints[j,2]   
	    if (dis[k,e1] < dis[k,e2]){
		endpoints[i,1] <- e2
		dir[i,1] <- -1 }
	    else {
		endpoints[i,1] <-e1
	    }}
	else {
		ek1 <- endpoints[k,1]; ek2 <- endpoints[k,2]
        ej1 <- endpoints[j,1]; ej2 <- endpoints[j,2]

		
	    d11 <- dis[ej1,ek1]
	    d12 <- dis[ej1,ek2]
	    d21 <- dis[ej2,ek1]
	    d22 <- dis[ej2,ek2]
	    dmin <- min(d11,d12,d21,d22)
	    if (dmin == d21) {
		endpoints[i,1] <- ej1
		endpoints[i,2] <- ek2
	    }
	    
	    else if (dmin == d11) {
		endpoints[i,1] <- ej2
		endpoints[i,2] <- ek2
		dir[i,1] <- -1
	    }
	    else if (dmin == d12) {
		endpoints[i,1] <- ej2
		endpoints[i,2] <- ek1
		dir[i,1] <- -1
		dir[i,2] <- -1
	    }
	    else  {
		endpoints[i,1] <- ej1
		endpoints[i,2] <- ek1
		dir[i,2] <- -1}}
    }
    for (i in n:2L) {
	if (dir[i,1] == -1) {
	    m <- merges[i,1]
	    if (m > 0) {
		m1 <- merges[m,1]
		merges[m,1] <- merges[m,2]
		merges[m,2] <- m1
		if (dir[m,1] == dir[m,2]) 
		dir[m,] <- -dir[m,] 
	    }}
	if (dir[i,2] == -1) {
	    m <- merges[i,2]
	    if (m > 0) {
		m1 <- merges[m,1]
		merges[m,1] <- merges[m,2]
		merges[m,2] <- m1
		if (dir[m,1] == dir[m,2]) 
		dir[m,] <- -dir[m,] 
	    }}	      
	
    }    
    clusters <- as.list(1:n)
    for (i in 1:n) {
	j <- merges[[i,1]]
	k <- merges[[i,2]]
	if ((j < 0) && (k < 0)) 
	clusters[[i]] <- c(-j,-k)
	else if (j < 0)
	clusters[[i]] <- c(-j,clusters[[k]])
	else if (k < 0)
	clusters[[i]] <- c(clusters[[j]],-k)
	else clusters[[i]] <- c(clusters[[j]], clusters[[k]])}
    
    x1 <- x
    x1$merge <- merges
    x1$order <- clusters[[n]]
    x1
    
    
}



# reorder.hclust<-
# function(x,dis,...) {
    # if (! is.matrix(dis)) dis <- as.matrix(dis)
    # merges <- x$merge
    # n <- nrow(merges)
    # endpoints <- matrix(0,n,2)
    # dir <- matrix(1L,n,2)
    # for (i in 1L:n) {
	# j <- merges[i,1]
	# k <- merges[i,2]
	# if ((j < 0) && (k < 0)) {
	    # endpoints[i,1] <- -j
	    # endpoints[i,2] <- -k}
	# else if (j < 0) {
	    # j <- -j
	    # endpoints[i,1] <- j
	    # if (dis[j,endpoints[k,1]] < dis[j,endpoints[k,2]])        
	    # endpoints[i,2] <- endpoints[k,2]
	    # else {
		# endpoints[i,2] <- endpoints[k,1]
		# dir[i,2] <- -1}}
	# else if (k < 0) {
	    # k <- -k
	    # endpoints[i,2] <- k     
	    # if (dis[k,endpoints[j,1]] < dis[k,endpoints[j,2]]){
		# endpoints[i,1] <- endpoints[j,2]
		# dir[i,1] <- -1 }
	    # else {
		# endpoints[i,1] <- endpoints[j,1]
	    # }}
	# else {
	    # d11 <- dis[endpoints[j,1],endpoints[k,1]]
	    # d12 <- dis[endpoints[j,1],endpoints[k,2]]
	    # d21 <- dis[endpoints[j,2],endpoints[k,1]]
	    # d22 <- dis[endpoints[j,2],endpoints[k,2]]
	    # dmin <- min(d11,d12,d21,d22)
	    # if (dmin == d21) {
		# endpoints[i,1] <- endpoints[j,1]
		# endpoints[i,2] <- endpoints[k,2]
	    # }
	    
	    # else if (dmin == d11) {
		# endpoints[i,1] <- endpoints[j,2]
		# endpoints[i,2] <- endpoints[k,2]
		# dir[i,1] <- -1
	    # }
	    # else if (dmin == d12) {
		# endpoints[i,1] <- endpoints[j,2]
		# endpoints[i,2] <- endpoints[k,1]
		# dir[i,1] <- -1
		# dir[i,2] <- -1
	    # }
	    # else  {
		# endpoints[i,1] <- endpoints[j,1]
		# endpoints[i,2] <- endpoints[k,1]
		# dir[i,2] <- -1}}
    # }
    # for (i in n:2) {
	# if (dir[i,1] == -1) {
	    # m <- merges[i,1]
	    # if (m > 0) {
		# m1 <- merges[m,1]
		# merges[m,1] <- merges[m,2]
		# merges[m,2] <- m1
		# if (dir[m,1] == dir[m,2]) 
		# dir[m,] <- -dir[m,] 
	    # }}
	# if (dir[i,2] == -1) {
	    # m <- merges[i,2]
	    # if (m > 0) {
		# m1 <- merges[m,1]
		# merges[m,1] <- merges[m,2]
		# merges[m,2] <- m1
		# if (dir[m,1] == dir[m,2]) 
		# dir[m,] <- -dir[m,] 
	    # }}	      
	
    # }
    
    # clusters <- as.list(1:n)
    # for (i in 1:n) {
	# j <- merges[i,1]
	# k <- merges[i,2]
	# if ((j < 0) && (k < 0)) 
	# clusters[[i]] <- c(-j,-k)
	# else if (j < 0)
	# clusters[[i]] <- c(-j,clusters[[k]])
	# else if (k < 0)
	# clusters[[i]] <- c(clusters[[j]],-k)
	# else clusters[[i]] <- c(clusters[[j]], clusters[[k]])}
    
    # x1 <- x
    # x1$merge <- merges
    # x1$order <- clusters[[n]]
    # x1
    
    
# }

reorder.hclust <- compiler::cmpfun(reorder.hclust)