\documentclass{article}
\usepackage{axiom}
\begin{document}
\title{src/algebra aggcat2.spad}
\author{Robert S. Sutor}
\maketitle

\begin{abstract}
\end{abstract}
\tableofcontents
\eject

\section{package FLAGG2 FiniteLinearAggregateFunctions2}

<<package FLAGG2 FiniteLinearAggregateFunctions2>>=
import Type
import FiniteLinearAggregate
)abbrev package FLAGG2 FiniteLinearAggregateFunctions2
--% FiniteLinearAggregateFunctions2

++ Author: ???
++ Date Created: ???
++ Date Last Updated: ???
++ Description:
++ FiniteLinearAggregateFunctions2 provides functions involving two
++ FiniteLinearAggregates where the underlying domains might be
++ different. An example of this might be creating a list of rational
++ numbers by mapping a function across a list of integers where the
++ function divides each integer by 1000.

FiniteLinearAggregateFunctions2(S, A, R, B):
 Exports == Implementation where
  S, R: Type
  A   : FiniteLinearAggregate S
  B   : FiniteLinearAggregate R

  Exports ==> with
    map    : (S -> R, A) -> B          ++ map(f,a) applies function f to each member of aggregate
                                       ++ \spad{a} resulting in a new aggregate over a
                                       ++ possibly different underlying domain.

    reduce : ((S, R) -> R, A, R) -> R  ++ reduce(f,a,r) applies function f to each
                                       ++ successive element of the
                                       ++ aggregate \spad{a} and an accumulant initialized to r.
                                       ++ For example,
                                       ++ \spad{reduce(_+$Integer,[1,2,3],0)}
                                       ++ does \spad{3+(2+(1+0))}. Note: third argument r
                                       ++ may be regarded as the
                                       ++ identity element for the function f.

    scan   : ((S, R) -> R, A, R) -> B  ++ scan(f,a,r) successively applies
                                       ++ \spad{reduce(f,x,r)} to more and more leading sub-aggregates
                                       ++ x of aggregrate \spad{a}.
                                       ++ More precisely, if \spad{a} is \spad{[a1,a2,...]}, then
                                       ++ \spad{scan(f,a,r)} returns
                                       ++ \spad{[reduce(f,[a1],r),reduce(f,[a1,a2],r),...]}.

  Implementation ==> add
    getRSample(): R ==
      R has sample: R => sample$R
      R has random: () -> R => random()$R
      NIL$Lisp         -- R got to be non-trivial.

    if A has ListAggregate(S) then         -- A is a list-oid
      reduce(fn, l, ident) ==
        empty? l => ident
        reduce(fn, rest l, fn(first l, ident))

      if B has ListAggregate(R) or not(B has shallowlyMutable) then
        -- A is a list-oid, and B is either list-oids or not mutable
        map(f, l) == construct [f s for s in entries l]

        scan(fn, l, ident) ==
          empty? l => empty()
          val := fn(first l, ident)
          concat(val, scan(fn, rest l, val))

      else                      -- A is a list-oid, B a mutable array-oid
        map(f, l) ==
          i := minIndex(w := new(#l,getRSample())$B)
          for a in entries l repeat (qsetelt!(w, i, f a); i := inc i)
          w

        scan(fn, l, ident) ==
          i := minIndex(w := new(#l,getRSample())$B)
          vl := ident
          for a in entries l repeat
            vl := qsetelt!(w, i, fn(a, vl))
            i := inc i
          w

    else                              -- A is an array-oid
      reduce(fn, v, ident) ==
        val := ident
        for i in minIndex v .. maxIndex v repeat
          val := fn(qelt(v, i), val)
        val

      if B has ListAggregate(R) then   -- A is an array-oid, B a list-oid
        map(f, v) ==
          construct [f qelt(v, i) for i in minIndex v .. maxIndex v]

        scan(fn, v, ident) ==
          w := empty()$B
          for i in minIndex v .. maxIndex v repeat
            ident := fn(qelt(v, i), ident)
            w := concat(ident, w)
          reverse! w

      else                             -- A and B are array-oid's
        if B has shallowlyMutable then -- B is also mutable
          map(f, v) ==
            w := new(#v,getRSample())$B
            for i in minIndex w .. maxIndex w repeat
              qsetelt!(w, i, f qelt(v, i))
            w

          scan(fn, v, ident) ==
            w   := new(#v,getRSample())$B
            vl := ident
            for i in minIndex v .. maxIndex v repeat
              vl := qsetelt!(w, i, fn(qelt(v, i), vl))
            w

        else                                   -- B non mutable array-oid
          map(f, v) ==
            construct [f qelt(v, i) for i in minIndex v .. maxIndex v]

          scan(fn, v, ident) ==
            w := empty()$B
            for i in minIndex v .. maxIndex v repeat
              ident := fn(qelt(v, i), ident)
              w := concat(w, ident)
            w

@

\section{package FSAGG2 FiniteSetAggregateFunctions2}

<<package FSAGG2 FiniteSetAggregateFunctions2>>=
import SetCategory
import FiniteSetAggregate
)abbrev package FSAGG2 FiniteSetAggregateFunctions2

--% FiniteSetAggregateFunctions2

++ Author: Robert S. Sutor
++ Date Created: 15 May 1990
++ Date Last Updated: 14 Oct 1993
++ Description:
++ FiniteSetAggregateFunctions2 provides functions involving two
++ finite set aggregates where the underlying domains might be
++ different. An example of this is to create a set of rational
++ numbers by mapping a function across a set of integers, where the
++ function divides each integer by 1000.

FiniteSetAggregateFunctions2(S, A, R, B): Exports == Implementation where
   S, R: SetCategory
   A   : FiniteSetAggregate S
   B   : FiniteSetAggregate R

   Exports ==> with
     map    : (S -> R, A) -> B          ++ map(f,a) applies function f to each member of
                                        ++ aggregate \spad{a}, creating a new aggregate with
                                        ++ a possibly different underlying domain.

     reduce : ((S, R) -> R, A, R) -> R  ++ reduce(f,a,r) applies function f to each
                                        ++ successive element of the aggregate \spad{a} and an
                                        ++ accumulant initialised to r.
                                        ++ For example,
                                        ++ \spad{reduce(_+$Integer,[1,2,3],0)}
                                        ++ does a \spad{3+(2+(1+0))}.
                                        ++ Note: third argument r may be regarded
                                        ++ as an identity element for the function.

     scan   : ((S, R) -> R, A, R) -> B  ++ scan(f,a,r) successively applies \spad{reduce(f,x,r)}
                                        ++ to more and more leading sub-aggregates x of
                                        ++ aggregate \spad{a}.
                                        ++ More precisely, if \spad{a} is \spad{[a1,a2,...]}, then
                                        ++ \spad{scan(f,a,r)} returns
                                        ++ \spad {[reduce(f,[a1],r),reduce(f,[a1,a2],r),...]}.

   Implementation ==> add
     map(fn, a) ==
       set(map(fn, parts a)$ListFunctions2(S, R))$B
     reduce(fn, a, ident) ==
       reduce(fn, parts a, ident)$ListFunctions2(S, R)
     scan(fn, a, ident) ==
       set(scan(fn, parts a, ident)$ListFunctions2(S, R))$B

@
\section{License}
<<license>>=
--Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
--All rights reserved.
--Copyright (C) 2007-2009, Gabriel Dos Reis.
--All rights reserved.
--
--Redistribution and use in source and binary forms, with or without
--modification, are permitted provided that the following conditions are
--met:
--
--    - Redistributions of source code must retain the above copyright
--      notice, this list of conditions and the following disclaimer.
--
--    - Redistributions in binary form must reproduce the above copyright
--      notice, this list of conditions and the following disclaimer in
--      the documentation and/or other materials provided with the
--      distribution.
--
--    - Neither the name of The Numerical ALgorithms Group Ltd. nor the
--      names of its contributors may be used to endorse or promote products
--      derived from this software without specific prior written permission.
--
--THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
--IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
--TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
--PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
--OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
--EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
--PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
--PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
--LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
--NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
--SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@
<<*>>=
<<license>>

<<package FLAGG2 FiniteLinearAggregateFunctions2>>
<<package FSAGG2 FiniteSetAggregateFunctions2>>

@
\eject
\begin{thebibliography}{99}
\bibitem{1} nothing
\end{thebibliography}
\end{document}