Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

build open-axiom

54510 views
import Type
import FiniteLinearAggregate
)abbrev category A1AGG OneDimensionalArrayAggregate
++ Author: Michael Monagan; revised by Manuel Bronstein and Richard Jenks
++ Date Created: August 87 through August 88
++ Date Last Updated: April 1991
++ Basic Operations:
++ Related Constructors:
++ Also See:
++ AMS Classifications:
++ Keywords:
++ References:
++ Description:
++ One-dimensional-array aggregates serves as models for one-dimensional arrays.
++ Categorically, these aggregates are finite linear aggregates
++ with the shallowly mutable property, that is, any component of
++ the array may be changed without affecting the
++ identity of the overall array.
++ Array data structures are typically represented by a fixed area in storage and
++ therefore cannot efficiently grow or shrink on demand as can list structures
++ (see however \spadtype{FlexibleArray} for a data structure which
++ is a cross between a list and an array).
++ Iteration over, and access to, elements of arrays is extremely fast
++ (and often can be optimized to open-code).
++ Insertion and deletion however is generally slow since an entirely new
++ data structure must be created for the result.
OneDimensionalArrayAggregate(S:Type): Category ==
    Join(FiniteLinearAggregate S,ShallowlyMutableAggregate S)
  add
    members x	    == [qelt(x, i) for i in minIndex x .. maxIndex x]
    sort!(f, a) == quickSort(f, a)$FiniteLinearAggregateSort(S, %)

    any?(f, a) ==
      for i in minIndex a .. maxIndex a repeat
	f qelt(a, i) => return true
      false

    every?(f, a) ==
      for i in minIndex a .. maxIndex a repeat
	not(f qelt(a, i)) => return false
      true

    position(f:S -> Boolean, a:%) ==
      for i in minIndex a .. maxIndex a repeat
	f qelt(a, i) => return i
      minIndex(a) - 1

    find(f, a) ==
      for i in minIndex a .. maxIndex a repeat
	f qelt(a, i) => return qelt(a, i)
      "failed"

    count(f:S->Boolean, a:%) ==
      n:NonNegativeInteger := 0
      for i in minIndex a .. maxIndex a repeat
	if f(qelt(a, i)) then n := n+1
      n

    map!(f, a) ==
      for i in minIndex a .. maxIndex a repeat
	qsetelt!(a, i, f qelt(a, i))
      a

    setelt(a:%, s:UniversalSegment(Integer), x:S) ==
      l := lo s; h := if hasHi s then hi s else maxIndex a
      l < minIndex a or h > maxIndex a => error "index out of range"
      for k in l..h repeat qsetelt!(a, k, x)
      x

    reduce(f, a) ==
      empty? a => error "cannot reduce an empty aggregate"
      r := qelt(a, m := minIndex a)
      for k in m+1 .. maxIndex a repeat r := f(r, qelt(a, k))
      r

    reduce(f, a, identity) ==
      for k in minIndex a .. maxIndex a repeat
	identity := f(identity, qelt(a, k))
      identity

    if S has BasicType then
       reduce(f, a, identity,absorber) ==
	 for k in minIndex a .. maxIndex a while identity ~= absorber
		repeat identity := f(identity, qelt(a, k))
	 identity

-- this is necessary since new has disappeared.
    stupidnew: (NonNegativeInteger, %, %) -> %
    stupidget: List % -> S
-- a and b are not both empty if n > 0
    stupidnew(n, a, b) ==
      zero? n => empty()
      new(n, (empty? a => qelt(b, minIndex b); qelt(a, minIndex a)))
-- at least one element of l must be non-empty
    stupidget l ==
      for a in l repeat
	not empty? a => return first a
      error "Should not happen"

    map(f, a, b) ==
      m := max(minIndex a, minIndex b)
      n := min(maxIndex a, maxIndex b)
      l := max(0, n - m + 1)::NonNegativeInteger
      c := stupidnew(l, a, b)
      for i in minIndex(c).. for j in m..n repeat
	qsetelt!(c, i, f(qelt(a, j), qelt(b, j)))
      c

--  map(f, a, b, x) ==
--    m := min(minIndex a, minIndex b)
--    n := max(maxIndex a, maxIndex b)
--    l := (n - m + 1)::NonNegativeInteger
--    c := new l
--    for i in minIndex(c).. for j in m..n repeat
--	qsetelt!(c, i, f(a(j, x), b(j, x)))
--    c

    merge(f, a, b) ==
      r := stupidnew(#a + #b, a, b)
      i := minIndex a
      m := maxIndex a
      j := minIndex b
      n := maxIndex b
      k := minIndex(r)
      while i <= m and j <= n repeat
	if f(qelt(a, i), qelt(b, j)) then
	  qsetelt!(r, k, qelt(a, i))
	  i := i+1
	else
	  qsetelt!(r, k, qelt(b, j))
	  j := j+1
        k := k + 1
      while i <= m repeat
        qsetelt!(r, k, elt(a, i))
        k := k + 1
        i := i + 1
      while j <= n repeat
        qsetelt!(r, k, elt(b, j))
        k := k + 1
        j := j + 1
      r

    elt(a:%, s:UniversalSegment(Integer)) ==
      l := lo s
      h := if hasHi s then hi s else maxIndex a
      l < minIndex a or h > maxIndex a => error "index out of range"
      r := stupidnew(max(0, h - l + 1)::NonNegativeInteger, a, a)
      for k in minIndex r.. for i in l..h repeat
	qsetelt!(r, k, qelt(a, i))
      r

    insert(a:%, b:%, i:Integer) ==
      m := minIndex b
      n := maxIndex b
      i < m or i > n => error "index out of range"
      y := stupidnew(#a + #b, a, b)
      k := minIndex y
      for j in m..i-1 repeat
	qsetelt!(y, k, qelt(b, j))
        k := k + 1
      for j in minIndex a .. maxIndex a repeat
	qsetelt!(y, k, qelt(a, j))
        k := k + 1
      for j in i..n repeat
        qsetelt!(y, k, qelt(b, j))
        k := k + 1
      y

    copy x ==
      y := stupidnew(#x, x, x)
      for i in minIndex x .. maxIndex x for j in minIndex y .. repeat
	qsetelt!(y, j, qelt(x, i))
      y

    copyInto!(y, x, s) ==
      s < minIndex y or s + #x > maxIndex y + 1 =>
					      error "index out of range"
      for i in minIndex x .. maxIndex x for j in s.. repeat
	qsetelt!(y, j, qelt(x, i))
      y

    construct l ==
--    a := new(#l)
      empty? l => empty()
      a := new(#l, first l)
      for i in minIndex(a).. for x in l repeat qsetelt!(a, i, x)
      a

    delete(a:%, s:UniversalSegment(Integer)) ==
      l := lo s; h := if hasHi s then hi s else maxIndex a
      l < minIndex a or h > maxIndex a => error "index out of range"
      h < l => copy a
      r := stupidnew((#a - h + l - 1)::NonNegativeInteger, a, a)
      k := minIndex(r)
      for i in minIndex a..l-1 repeat
	qsetelt!(r, k, qelt(a, i))
        k := k + 1
      for i in h+1 .. maxIndex a repeat
	qsetelt!(r, k, qelt(a, i))
        k := k + 1
      r

    delete(x:%, i:Integer) ==
      i < minIndex x or i > maxIndex x => error "index out of range"
      y := stupidnew((#x - 1)::NonNegativeInteger, x, x)
      k := minIndex y
      for j in minIndex x..i-1 repeat
	qsetelt!(y, k, qelt(x, j))
        k := k + 1
      for j in i+1 .. maxIndex x repeat
	qsetelt!(y, k, qelt(x, j))
        k := k + 1
      y

    reverse! x ==
      m := minIndex x
      n := maxIndex x
      for i in 0..((n-m) quo 2) repeat swap!(x, m+i, n-i)
      x

    concat l ==
      empty? l => empty()
      n := +/[#a for a in l]
      i := minIndex(r := new(n, stupidget l))
      for a in l repeat
	copyInto!(r, a, i)
	i := i + #a
      r

    sorted?(f, a) ==
      for i in minIndex(a)..maxIndex(a)-1 repeat
	not f(qelt(a, i), qelt(a, i + 1)) => return false
      true

    concat(x:%, y:%) ==
      z := stupidnew(#x + #y, x, y)
      copyInto!(z, x, i := minIndex z)
      copyInto!(z, y, i + #x)
      z

    if S has CoercibleTo(OutputForm) then
      coerce(r:%):OutputForm ==
	bracket commaSeparate
	      [qelt(r, k)::OutputForm for k in minIndex r .. maxIndex r]

    if S has BasicType then
      x = y ==
	#x ~= #y => false
	for i in minIndex x .. maxIndex x repeat
	  not(qelt(x, i) = qelt(y, i)) => return false
	true

      position(x:S, t:%, s:Integer) ==
	n := maxIndex t
	s < minIndex t or s > n => error "index out of range"
	for k in s..n repeat
	  qelt(t, k) = x => return k
	minIndex(t) - 1

    if S has OrderedSet then
      a < b ==
	for i in minIndex a .. maxIndex a
	  for j in minIndex b .. maxIndex b repeat
	    qelt(a, i) ~= qelt(b, j) => return a.i < b.j
	#a < #b