Array2.copy

Stephen Weeks sweeks@wasabi.epr.com
Mon, 18 Oct 1999 16:49:59 -0700 (PDT)


I finally got around to building an implementation of Array2.copy.
Let me know if you notice any bugs.

--------------------------------------------------------------------------------

fun checkSliceMax(start: int, num: int option, max: int): int =
   case num of
      NONE => if start < 0 orelse start > max
		 then raise Subscript
	      else max
    | SOME num =>
	 if start < 0 orelse num < 0 orelse start > max - num
	    then raise Subscript
	 else start + num

fun checkRegion{base, row, col, nrows, ncols} =
   let val (rows, cols) = dimensions base
   in {stopRow = checkSliceMax(row, nrows, rows),
       stopCol = checkSliceMax(col, ncols, cols)}
   end

fun copy{src = src as {base, row, col, nrows, ncols},
	 dst, dst_row, dst_col} =
   let val {stopRow, stopCol} = checkRegion src
      val nrows = stopRow - row
      val ncols = stopCol - col
      val _ = checkRegion{base = dst, row = dst_row, col = dst_col,
			  nrows = SOME nrows, ncols = SOME ncols}
      fun for(start, stop, f) =
	 let fun loop i = if i = stop then () else (f i; loop(i + 1))
	 in loop start
	 end
      fun forDown(start, stop, f) =
	 let fun loop i = if i < start then () else (f i; loop(i - 1))
	 in loop(stop - 1)
	 end
      val forRows = if row <= dst_row then forDown else for
      val forCols = if col <= dst_col then for else forDown
   in forRows(0, nrows, fn r =>
	      forCols(0, ncols, fn c =>
		      update(dst, dst_row + r, dst_col + c,
			     sub(base, row + r, col + c))))
   end