(***********************************************************************)
(* *)
(* Applied Type System *)
(* *)
(* Hongwei Xi *)
(* *)
(***********************************************************************)
(*
** ATS - Unleashing the Potential of Types!
**
** Copyright (C) 2002-2009 Hongwei Xi, Boston University
**
** All rights reserved
**
** ATS is free software; you can redistribute it and/or modify it under
** the terms of the GNU LESSER GENERAL PUBLIC LICENSE as published by the
** Free Software Foundation; either version 2.1, or (at your option) any
** later version.
**
** ATS is distributed in the hope that it will be useful, but WITHOUT ANY
** WARRANTY; without even the implied warranty of MERCHANTABILITY or
** FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
** for more details.
**
** You should have received a copy of the GNU General Public License
** along with ATS; see the file COPYING. If not, please write to the
** Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
** 02110-1301, USA.
*)
(* ****** ****** *)
//
// Author: Hongwei Xi (hwxi AT cs DOT bu DOT edu)
// Time: Summer, 2009
//
(* ****** ****** *)
//
// SML Basis Library: Array2 (http://www.standardml.org/Basis/array2.html)
//
(* ****** ****** *)
staload "libats/smlbas/SATS/general.sats"
(* ****** ****** *)
staload "libats/smlbas/SATS/array2.sats"
(* ****** ****** *)
(*
** note that RowMajor representation is assumed
*)
assume array2_t0ype_type (a: t@ype) = [m,n:nat] [l:addr] '{
data= ptr l, view= vbox (matrix_v (a, m, n, l)), row= size_t m, col= size_t n
} // end of [array2_t0ype_type]
(* ****** ****** *)
extern fun vbox_make_view_ptr_matrix {a:viewt@ype} {m,n:int} {l:addr}
(pf: matrix_v (a, m, n, l) | p: ptr l):<> (vbox (matrix_v (a, m, n, l)) | void)
= "atspre_vbox_make_view_ptr"
(* ****** ****** *)
implement{a} array (row, col, ini) = let
val [m:int] m = size1_of_size row
and [n:int] n = size1_of_size col
val (pf_mul | mn) = mul2_size1_size1 (m, n)
prval () = mul_nat_nat_nat pf_mul
val [l:addr] (pf_gc, pf_arr | p_arr) =
array_ptr_alloc_tsz {a} (mn, sizeof)
// end of [val]
prval () = free_gc_elim {a} (pf_gc) // return the certificate
val () = array_ptr_initialize_elt (!p_arr, mn, ini)
prval pf_mat = matrix_v_of_array_v (pf_mul, pf_arr)
val (pf_mat_box | ()) = vbox_make_view_ptr_matrix (pf_mat | p_arr)
in
#[m,n | #[l | '{ data= p_arr, view= pf_mat_box, row= m, col= n} ] ]
end // end of [array]
(* ****** ****** *)
extern fun{a:t@ype} array_ptr_initialize_lstlst {m,n:nat} {mn:int} (
pf_mul: MUL (m, n, mn) | base: &(@[a?][mn]) >> @[a][mn], m: size_t m, xss: list (list (a, m), n)
) :<> void
// end of [array_ptr_initialize_lstlst]
implement{a} array_ptr_initialize_lstlst
{m,n}{mn} (pf_mul | base, m, xss) = let
val (pf_ofs | ofs) = mul2_size1_size1 (m, sizeof)
fun loop {n:nat} {mn:int} {l:addr} .. (
pf_mul: MUL (n, m, mn), pf_arr: !array_v (a?, mn, l) >> array_v (a, mn, l)
| p_arr: ptr l, xss: list (list (a, m), n)
) : void =
case+ xss of
| list_nil () => () where {
prval MULbas () = pf_mul
prval () = array_v_unnil (pf_arr); prval () = pf_arr := array_v_nil {a} ()
} // end of [list_nil]
| list_cons (xs, xss) => let
prval pf1_mul = mul_add_const {~1} {n,m} (pf_mul)
prval () = mul_nat_nat_nat (pf1_mul)
prval (pf1_arr, pf2_arr) = array_v_split {a?} {mn,m} (pf_ofs, pf_arr)
val () = array_ptr_initialize_lst (!p_arr, xs)
val () = loop (pf1_mul, pf2_arr | p_arr + ofs, xss)
prval () = pf_arr := array_v_unsplit {a} (pf_ofs, pf1_arr, pf2_arr)
in
// nothing
end (* end of [list_cons] *)
// end of [loop]
in
loop (mul_commute (pf_mul), view@ base | &base, xss)
end // end of [array_ptr_initialize_lstlst]
(* ****** ****** *)
implement{a} fromList (xss) = let
val n = list0_length (xss)
val [n:int] n = int1_of_int (n)
val () = (if (n > 0) then () else $raise Size ()): [n > 0] void
val- list0_cons (xs, xss1) = xss
val [m:int] xs = list1_of_list0 xs
val m = list_length (xs)
val () = auxcheck (m, xss1) where {
fun auxcheck (m: int, xss: list0 (list0 a)): void =
case+ xss of
| list0_cons (xs, xss) => begin
if list0_length (xs) = m then auxcheck (m, xss) else $raise Size ()
end // end of [list0_cons]
| list0_nil () => ()
// end of [auxcheck]
} // end of [val]
//
// There should be a better way of doing this
//
val xss = __cast (xss) where {
extern castfn __cast (xss: list0 (list0 a)):<> list (list (a, m), n)
} (* end of [val] *)
//
val m = size1_of_int1 (m) and n = size1_of_int1 (n)
val (pf_mul | mn) = mul2_size1_size1 (m, n)
prval () = mul_nat_nat_nat pf_mul
val [l:addr] (pf_gc, pf_arr | p_arr) =
array_ptr_alloc_tsz {a} (mn, sizeof)
// end of [val]
prval () = free_gc_elim {a} (pf_gc) // return the certificate
val () = array_ptr_initialize_lstlst (pf_mul | !p_arr, m, xss)
prval pf_mat = matrix_v_of_array_v (pf_mul, pf_arr)
val (pf_mat_box | ()) = vbox_make_view_ptr_matrix (pf_mat | p_arr)
in
#[m,n | #[l | '{ data= p_arr, view= pf_mat_box, row= m, col= n} ] ]
end // end of [fromList]
(* ****** ****** *)
implement{a} tabulate (trv, m, n, f) = let
val [m:int] m = size1_of_size (m) and [n:int] n = size1_of_size (n)
val () = (if m > 0 then () else $raise Size ()): [m > 0] void
val () = (if n > 0 then () else $raise Size ()): [n > 0] void
val [mn:int] (pf_mul_mn | mn) = mul2_size1_size1 (m, n)
prval () = mul_nat_nat_nat (pf_mul_mn)
val [l:addr] (pf_gc, pf_arr | p_arr) =
array_ptr_alloc_tsz {a} (mn, sizeof)
// end of [val]
prval () = free_gc_elim {a} (pf_gc) // return the certificate
prval pf_arr = __cast pf_arr where {
extern prfun __cast (pf_arr: array_v (a?, mn, l)):<> array_v (a, mn, l)
} (* end of [prval] *)
val _0 = size1_of_int1 0 and _1 = size1_of_int1 1
val () = case+ :(pf_arr: array_v (a, mn, l)) => trv of
| RowMajor () => let
var i: size_t? and j: size_t? ; var k: size_t = _0
in
for* (i: sizeLte m) => (i := _0; i < m; i := i + _1)
for* (i: sizeLt m, j: sizeLte n) => (j := _0; j < n; j := j + _1) let
val k1 = __cast k where {
extern castfn __cast (k: size_t):<> sizeLt (mn)
} // end of [val]
in
p_arr->[k1] := f (i, j); k := k + _1
end // end of [for] // end of [for]
end // end of [RowMajor]
| ColMajor () => let
var i: size_t? and j: size_t? ; var k: size_t = _0
in
for* (j: sizeLte n) => (j := _0; j < n; j := j + _1) let
val () = k := j
in
for* (i: sizeLte m, j: sizeLt n) => (i := _0; i < m; i := i + _1) let
val k1 = __cast k where {
extern castfn __cast (k: size_t):<> sizeLt (mn)
} // end of [val]
in
p_arr->[k1] := f (i, j); k := k + n
end // end of [for]
end // end of [for]
end (* end of [ColMajor] *)
// end of [val]
prval pf_mat = matrix_v_of_array_v {a} (pf_mul_mn, pf_arr)
val (pf_mat_box | ()) = vbox_make_view_ptr_matrix (pf_mat | p_arr)
in
#[m,n | #[l | '{ data= p_arr, view= pf_mat_box, row= m, col= n} ] ]
end // end of [tabulate]
(* ****** ****** *)
prfun lemma_for_matrix_subscripting
{m,n:nat} {i:nat | i < m} {mn,p:int} ..
(pf1: MUL (m, n, mn), pf2: MUL (i, n, p)): [p+n <= mn] void = let
prval MULind pf11 = pf1
in
sif i < m-1 then begin
lemma_for_matrix_subscripting (pf11, pf2)
end else let // i = m-1
prval () = mul_isfun (pf11, pf2)
in
// empty
end // end of [sif]
end // end of [lemma_for_matrix_subscripting]
implement{a} sub (M, i, j) = let
val m = M.row and n = M.col
val i = size1_of_size (i) and j = size1_of_size (j)
in
if i < m then
if j < n then let
prval vbox pf_mat = M.view
prval (pf_mul_mn, pf_arr) = array_v_of_matrix_v (pf_mat)
val (pf_mul_i_n | i_n) = mul2_size1_size1 (i, n)
prval () = mul_nat_nat_nat pf_mul_i_n
prval () = lemma_for_matrix_subscripting (pf_mul_mn, pf_mul_i_n)
val M_data = M.data
val x = !M_data.[i_n+j]
prval () = pf_mat := matrix_v_of_array_v (pf_mul_mn, pf_arr)
in
x // return value
end else begin
$raise Subscript ()
end // end of [if]
else begin
$raise Subscript ()
end // end of [if]
end (* end of [sub] *)
implement{a} update (M, i, j, x) = let
val m = M.row and n = M.col
val i = size1_of_size (i) and j = size1_of_size (j)
in
if i < m then
if j < n then let
prval vbox pf_mat = M.view
prval (pf_mul_mn, pf_arr) = array_v_of_matrix_v (pf_mat)
val (pf_mul_i_n | i_n) = mul2_size1_size1 (i, n)
prval () = mul_nat_nat_nat pf_mul_i_n
prval () = lemma_for_matrix_subscripting (pf_mul_mn, pf_mul_i_n)
val M_data = M.data
val () = !M_data.[i_n+j] := x
prval () = pf_mat := matrix_v_of_array_v (pf_mul_mn, pf_arr)
in
// no return value
end else begin
$raise Subscript ()
end // end of [if]
else begin
$raise Subscript ()
end // end of [if]
end (* end of [sub] *)
(* ****** ****** *)
implement dimensions (M) = @(M.row, M.col)
implement nRows (M) = M.row
implement nCols (M) = M.col
(* ****** ****** *)
implement{a} app (trv, f, [m,n:int] [l:addr] M) = let
val p_arr = M.data; prval vbox pf_mat = M.view
val m = M.row and n = M.col
prval [mn:int] (pf_mul_mn, pf_arr) = array_v_of_matrix_v (pf_mat)
val _0 = size1_of_int1 0 and _1 = size1_of_int1 1
val () = case+ trv of
| RowMajor () => let
var i: size_t? and j: size_t? ; var k: size_t = _0
in
for* (i: sizeLte m) => (i := _0; i < m; i := i + _1)
for* (i: sizeLt m, j: sizeLte n) => (j := _0; j < n; j := j + _1) let
val k1 = __cast k where {
extern castfn __cast (k: size_t):<> sizeLt (mn)
} // end of [val]
in
$effmask_ref (f (p_arr->[k1])); k := k + _1
end // end of [for] // end of [for]
end // end of [RowMajor]
| ColMajor () => let
var i: size_t? and j: size_t? ; var k: size_t = _0
in
for* (j: sizeLte n) => (j := _0; j < n; j := j + _1) let
val () = k := j
in
for* (i: sizeLte m, j: sizeLt n) => (i := _0; i < m; i := i + _1) let
val k1 = __cast k where {
extern castfn __cast (k: size_t):<> sizeLt (mn)
} // end of [val]
in
$effmask_ref (f (p_arr->[k1])); k := k + n
end // end of [for]
end // end of [for]
end (* end of [ColMajor] *)
// end of [val]
in
pf_mat := matrix_v_of_array_v (pf_mul_mn, pf_arr)
end // end of [app]
(* ****** ****** *)
implement{a,b} fold (trv, f, ini, [m,n:int] [l:addr] M) = let
val p_arr = M.data; prval vbox pf_mat = M.view
val m = M.row and n = M.col
prval [mn:int] (pf_mul_mn, pf_arr) = array_v_of_matrix_v (pf_mat)
val _0 = size1_of_int1 0 and _1 = size1_of_int1 1
var res: b = ini
val () = case+ trv of
| RowMajor () => let
var i: size_t? and j: size_t? ; var k: size_t = _0
in
for* (i: sizeLte m) => (i := _0; i < m; i := i + _1)
for* (i: sizeLt m, j: sizeLte n) => (j := _0; j < n; j := j + _1) let
val k1 = __cast k where {
extern castfn __cast (k: size_t):<> sizeLt (mn)
} // end of [val]
in
res := $effmask_ref (f (p_arr->[k1], res)); k := k + _1
end // end of [for] // end of [for]
end // end of [RowMajor]
| ColMajor () => let
var i: size_t? and j: size_t? ; var k: size_t = _0
in
for* (j: sizeLte n) => (j := _0; j < n; j := j + _1) let
val () = k := j
in
for* (i: sizeLte m, j: sizeLt n) => (i := _0; i < m; i := i + _1) let
val k1 = __cast k where {
extern castfn __cast (k: size_t):<> sizeLt (mn)
} // end of [val]
in
res := $effmask_ref (f (p_arr->[k1], res)); k := k + n
end // end of [for]
end // end of [for]
end (* end of [ColMajor] *)
// end of [val]
in
pf_mat := matrix_v_of_array_v (pf_mul_mn, pf_arr)
end // end of [fold]
(* ****** ****** *)
implement{a} modify (trv, f, [m,n:int] [l:addr] M) = let
val p_arr = M.data; prval vbox pf_mat = M.view
val m = M.row and n = M.col
prval [mn:int] (pf_mul_mn, pf_arr) = array_v_of_matrix_v (pf_mat)
val _0 = size1_of_int1 0 and _1 = size1_of_int1 1
val () = case+ trv of
| RowMajor () => let
var i: size_t? and j: size_t? ; var k: size_t = _0
in
for* (i: sizeLte m) => (i := _0; i < m; i := i + _1)
for* (i: sizeLt m, j: sizeLte n) => (j := _0; j < n; j := j + _1) let
val k1 = __cast k where {
extern castfn __cast (k: size_t):<> sizeLt (mn)
} // end of [val]
in
p_arr->[k1] := $effmask_ref (f (p_arr->[k1])); k := k + _1
end // end of [for] // end of [for]
end // end of [RowMajor]
| ColMajor () => let
var i: size_t? and j: size_t? ; var k: size_t = _0
in
for* (j: sizeLte n) => (j := _0; j < n; j := j + _1) let
val () = k := j
in
for* (i: sizeLte m, j: sizeLt n) => (i := _0; i < m; i := i + _1) let
val k1 = __cast k where {
extern castfn __cast (k: size_t):<> sizeLt (mn)
} // end of [val]
in
p_arr->[k1] := $effmask_ref (f (p_arr->[k1])); k := k + n
end // end of [for]
end // end of [for]
end (* end of [ColMajor] *)
// end of [val]
in
pf_mat := matrix_v_of_array_v (pf_mul_mn, pf_arr)
end // end of [modify]
(* ****** ****** *)
(* end of [array2.dats] *)