cut <- function(x, breaks, labels) {
	if (!is.numeric(x))
		stop("cut: x must be numeric")
	if (length(breaks) == 1) {
		if (is.na(breaks) | breaks < 2)
			stop("invalid number of breaks")
		nbreaks <- breaks
		breaks <- range(x,na.rm=TRUE)
		#breaks <- pretty(breaks + c(0, diff(breaks)/1000), nbreaks)
		breaks <- seq(breaks[1]-diff(breaks)/1000,breaks[2]+diff(breaks)/1000, len=nbreaks+1)
	}
	breaks <- sort(breaks)
	if(any(duplicated(breaks)))
		stop("cut: breaks are not unique")
	if(missing(labels)) {
		labels <- paste("Range",1:(length(breaks)-1))
	}
	else {
		if(length(labels)!=length(breaks)-1)
			stop("labels/breaks length conflict")
	}
	codes <- .C("bincode",
		as.double(x),
		length(x),
		as.double(breaks),
		length(breaks),
		integer(length(x)),
		TRUE)[[5]]
	factor(codes,1:max(codes),labels)
}
