[comp.sources.unix] v10i034: Interpreted Functional Programming lanuage, Part 01/07

rs@uunet.UU.NET (Rich Salz) (07/07/87)

Mod.sources: Volume 10, Number 34
Submitted by: robison@b.cs.uiuc.edu (Arch Robison)
Archive-name: ifp/Part01

IFP[1] is a variant of Backus' FP [2].  The IFP interpreter is written
in C and is an order of magnitude faster than the BSD 4.2 FP [3].
The interpreter should run on any UNIX box.

Arch D. Robison
University of Illinois at Urbana-Champaign
	
CSNET: robison@UIUC.CSNET
UUCP: {ihnp4,pur-ee,convex}!uiucdcs!robison
ARPA: robison@B.CS.UIUC.EDU (robison@UIUC.ARPA)

General References
------------------

[1]  Arch D. Robison, "Illinois  Functional  Programming:  A
     Tutorial," BYTE Vol. 12,2 pp. 115-125 McGraw-Hill Inc.,
     (February 1987).

[2]  John Backus, "Can Programming Be Liberated from the von
     Neumann  Style?   A Functional Style and Its Algebra of
     Programs," CACM  Vol.  21,8 pp.  613-641  ACM,  (August
     1978).

[3]  Scott Baden, "Berkeley FP  User's  Manual,  Rev.  4.1,"
     UNIX Programmers Manual, (July 27,1983).


#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh.
# The following files will be created:
#	README
#	ifp.1
#	RunIFP
#	fproot
export PATH; PATH=/bin:$PATH
if test -f 'README'
then
	echo shar: over-writing existing file "'README'"
fi
cat << \SHAR_EOF > 'README'
This directory contains the following subdirectories and files:

	README - this file

	RunIFP - shell script which runs IFP interpreter

	fproot - IFP demonstration root directory
	fproot/demo - demonstration functions

	interp - source code and Makefile for IFP interpreter

	manual - troff files and Makefile for IFP manual
SHAR_EOF
chmod +x 'README'
if test -f 'ifp.1'
then
	echo shar: over-writing existing file "'ifp.1'"
fi
cat << \SHAR_EOF > 'ifp.1'
.TH IFP 1 "Jan 28, 1987"
.UC 4
.SH NAME
ifp \- Illinois FP interpreter 
.SH SYNOPSIS
.B ifp
[ option ] 
.SH DESCRIPTION
.I Ifp
starts the Illinois FP interpreter.
.PP
.I Ifp
understands several options.  Normally, no options are required.
Most of the options are for experimental work.  
Not all (or even any) of the options may
exist for a particular version of the interpreter.
.TP
.B \-l
Print all functions with full pathname.  
Useful for debugging scope problems.
.TP
.B \-e[012]
Turn on expression cache.  The cache may be turned on for any subset of:
.nf
	0	Primitive functions
	1	User-defined functions
	2	PFOs
.fi
To see the cache statistics, give the command "cache" to the interpreter.
.TP
.B \-pn
(Multimax only) This option specifies that the interpreter should be run
as n parallel processes.
.TP
.B \-f
(Multimax only) Print expression queue statistics.
.TP 
.B  \-sn
(Multimax only) Use stack of max. depth n for expression scheduling.
.TP
.B \-qn
(Multimax only) Use queue of max. length n for expression scheduling.
.TP
.B \-d[pafricxhusle]
Turn on spy points corresponding to selected letters.
.nf
	p	parser
	a	memory allocation
	f	file io
	r	reference counts
	i	initialization
	c	expression cache
	x	extended definitions
	h	hypercube
	u	Multimax
	s	Semaphores
	l	Free list
	e	Expression sckeduling
.fi
For example, -dar turns on spy points for memory allocation and 
reference counts.
.SH FILES
.ta \w'/usr/local/lib/lib*.a\ \ 'u
ifp	interpreter 
.br
.SH "SEE ALSO"
Illinois FP User's Manual
.sp 2
A Functional Programming Interpreter (THESIS, Univerisity of Illinois) 
.sp 2
.ul
Illinois Functional Programming: A Tutorial 
(BYTE, Feb. 1987)
.br
fp(1)
.SH BUGS
Programming in IFP still requires thinking.  Some the options are incompatible.
.SH AUTHOR
Arch D. Robison
SHAR_EOF
if test -f 'RunIFP'
then
	echo shar: over-writing existing file "'RunIFP'"
fi
cat << \SHAR_EOF > 'RunIFP'
# Shell script for invoking IFP interpreter.

# This script is for demonstration and documentation purposes only.
# Running the script will set the appropriate environment variables
# and start up the IFP interpreter in the demonstration directory.

# All its actions should be put in the user's .login, and .cshrc files.
# The IFP interpreter must be compiled before running this script.
# See the Makefile in subdirectory "interp" for instructions on how
# to compile the interpreter.

#-----------------------------------------------------------------------

# These two lines should go in each user's .login file and be customized
# for the user's particular IFP root directory and editor. 

	setenv IFProot $cwd/fproot
	setenv EDITOR "/usr/ucb/vi"

# This alias is for convenience.  Presumably the interpreter will normally
# reside on the user's search path.

	alias ifp $cwd/interp/ifp

# Normally the user would type in the following two lines:

	cd fproot/demo
	ifp

# The interpreter will respond with the prompt "ifp>" when ready for 
# user input.

SHAR_EOF
chmod +x 'RunIFP'
if test ! -d 'fproot'
then
	mkdir 'fproot'
fi
cd 'fproot'
if test ! -d 'demo'
then
	mkdir 'demo'
fi
cd 'demo'
if test -f '%IMPORT'
then
	echo shar: over-writing existing file "'%IMPORT'"
fi
cat << \SHAR_EOF > '%IMPORT'
FROM /sys IMPORT
   apndl,apndr,apply,assoc,cat,distl,distr,dropl,dropr,explode,id,implode,
   iota,length,patom,pick,repeat,reverse,takel,taker,tl,tlr,trans;

FROM /math/arith IMPORT
   +,-,*,%,add1,arccos,arcsin,arctan,cos,div,exp,ln,
   max,min,mod,minus,power,prod,sin,sqrt,sub1,sum,tan;

FROM /math/logic IMPORT
   <,<=,=,~=,>=,>,~,and,all,any,atom,boolean,false,longer,member,null,
   numeric,odd,or,pair,shorter,xor; 

SHAR_EOF
if test -f 'A'
then
	echo shar: over-writing existing file "'A'"
fi
cat << \SHAR_EOF > 'A'
DEF A AS
  #<<1 2 3>
    <4 5 6>
    <7 8 9>>;
SHAR_EOF
if test -f 'Abs'
then
	echo shar: over-writing existing file "'Abs'"
fi
cat << \SHAR_EOF > 'Abs'
(* Absolute value function *)

DEF Abs AS
   IF [id,#0] | < THEN minus
   ELSE id
   END;
SHAR_EOF
if test -f 'B'
then
	echo shar: over-writing existing file "'B'"
fi
cat << \SHAR_EOF > 'B'
(*
 * A data matrix.
 *)
DEF B AS
   #<5 3 88  6 21  0  0 -7 
     5 2  1  4  8 10  1  4
     2 4  3  7  9  5  2  5
     1 3  3  5  7  2  3  6
     4 7  5  3  1  8  4  7
     8 9  7  1  6 12  5  8
    10 5  2  8 12  1  6  9
     1 2  3  4  5  6  1  2
     4 5  6  7  8  9  2  1>;

SHAR_EOF
if test -f 'Cart'
then
	echo shar: over-writing existing file "'Cart'"
fi
cat << \SHAR_EOF > 'Cart'
(* 
 * Cartesian product of two sequences
 *)
DEF Cart AS 
   distr | EACH distl END;

SHAR_EOF
if test -f 'CosSin'
then
	echo shar: over-writing existing file "'CosSin'"
fi
cat << \SHAR_EOF > 'CosSin'
(*
 * CosSin
 *
 * Compute the sine and cosine of an angle via half-angle formulae.
 * The function is accurate to 12 decimals.
 *)
DEF CosSin AS
   IF [id|Abs,#1e-6]|< THEN [[#1,[Square,#2]|%]|-,id]
   ELSE
      [id,#2]|% | CosSin | 
      [[+,-]|*, [*,*]|+] 
   END;

SHAR_EOF
if test -f 'Data'
then
	echo shar: over-writing existing file "'Data'"
fi
cat << \SHAR_EOF > 'Data'
(*
 * Currently I/O is almost non-existent in IFP.  One way to skirt this problem
 * when you have a large amount of data to input is to define a constant 
 * function with the appropriate values.
 *
 * The function Data returns a sequence of data values.  We could, for 
 * instance, sort them by composing Data with QuickSort
 *
 * Examples:
 *      0 : Data -> <5 3 88 6 21 0 -7>
 *      0 : Data | QuickSort -> <-7 0 3 5 6 21 88>
 *)

DEF Data AS
   #<5 3 88 6 21 0 -7>;
 
SHAR_EOF
if test -f 'Debug'
then
	echo shar: over-writing existing file "'Debug'"
fi
cat << \SHAR_EOF > 'Debug'
(*
 * Version of Fib with debugging output
 *
 * n : Debug -> sequence of first n Fibonacci numbers
 *
 * The two functions created with the "@" form print their inputs
 * so we can see what is going on inside the Debug function.
 *)

DEF Debug AS

   IF [id,#2] | <= THEN

      @"trivial case" | [#<1 1>,id] | takel

   ELSE

      @"recurse" | sub1 | Debug | [id, [1r,2r]|+] | apndr

   END;

SHAR_EOF
if test -f 'Double'
then
	echo shar: over-writing existing file "'Double'"
fi
cat << \SHAR_EOF > 'Double'
(* Double a number - e.g. 3:Double -> 6 *)

DEF Double AS [id,id]|+;

SHAR_EOF
if test -f 'Fib'
then
	echo shar: over-writing existing file "'Fib'"
fi
cat << \SHAR_EOF > 'Fib'
(*
 * Compute nth fibonacci number
 *
 * Examples:
 *
 *	6 : Fib -> 8
 *	7 : Fib -> 13
 *	8 : Fib -> 21
 *)

DEF Fib AS 
   IF [id,#2] | < THEN id
   ELSE
      sub1 | [Fib,sub1|Fib] | +
   END;
SHAR_EOF
if test -f 'FibSeq'
then
	echo shar: over-writing existing file "'FibSeq'"
fi
cat << \SHAR_EOF > 'FibSeq'
(*
 * Fibonacci numbers
 * 
 * n : FibSeq -> sequence of first n Fibonacci numbers
 *
 * Example
 *      6 : FibSeq -> <1 1 2 3 5 8>
 *)

DEF FibSeq AS
   IF [id,#2] | <= THEN
      [#<1 1>,id] | takel       (* trivial case *)
   ELSE
      sub1 | FibSeq |           (* generate n-1 Fibonacci numbers        *)
      [id, [1r,2r]|+] | apndr   (* append sum of last two to end of list *)
   END;

SHAR_EOF
if test -f 'Format'
then
	echo shar: over-writing existing file "'Format'"
fi
cat << \SHAR_EOF > 'Format'
DEF Format AS
   [id,#" "] | distr | cat | implode;

SHAR_EOF
if test -f 'Hanoi'
then
	echo shar: over-writing existing file "'Hanoi'"
fi
cat << \SHAR_EOF > 'Hanoi'
(*
 * Hanio - towers of Hanoi solver
 *
 * <N Names> : Hanoi -> <<src dst> ...<src dst>>
 *
 * where N is number of rings and names is a triple of post names
 * <source temporary dest>.
 *
 * Example:
 *	<2 <a b c>> : Hanoi -> <<a,b>,<a,c>,<b,c>>
 *)

DEF Hanoi AS
   {[n,[a,b,c]] := id}
   IF [n,#0]|= THEN []
   ELSE [
      [n|sub1, [a,c,b]] | Hanoi,
      [[a,c]],
      [n|sub1, [b,a,c]] | Hanoi 
   ] | cat
   END;

SHAR_EOF
if test -f 'Inner'
then
	echo shar: over-writing existing file "'Inner'"
fi
cat << \SHAR_EOF > 'Inner'
(*
 * Compute the inner product of two vectors.
 *)
DEF Inner AS 
   trans | EACH * END | INSERT + END;
SHAR_EOF
if test -f 'InsertSort'
then
	echo shar: over-writing existing file "'InsertSort'"
fi
cat << \SHAR_EOF > 'InsertSort'
(*
 * InsertSort
 *
 * This function sorts a sequence of numbers or strings into ascending order
 * using insertion sort.
 *
 * Examples:
 *
 *      <3 1 4 1 5 9 2> : InsertSort == <1 1 2 3 4 5 9>
 *
 *      <all work and no play> : InsertSort == <all and no play work>
 *
 * The sequence may not mix strings and numbers.
 *)
DEF InsertSort AS
   IF null THEN id			(* Check for trivial case *)
   ELSE
      [tl,[1]] | apndr | 
      INSERT
	 {[Element,Seq] := id}
         {[Left,Right] := [Seq, distl | FILTER > END | length] | [takel,dropl]}
	 [Left,[Element],Right] | cat
      END
   END;

SHAR_EOF
if test -f 'Inter'
then
	echo shar: over-writing existing file "'Inter'"
fi
cat << \SHAR_EOF > 'Inter'
(*
 * Set intersection: [A,B] : Inter -> elements of B which are in A 
 * 
 * Example:
 *      <<2 3 4> <5 3 2 1>> : Inter -> <3 2>
 *)

DEF Inter AS
   distl | FILTER member END | EACH 2 END;
SHAR_EOF
if test -f 'MatMul'
then
	echo shar: over-writing existing file "'MatMul'"
fi
cat << \SHAR_EOF > 'MatMul'
(*
 * MatMul
 *
 * [matrixA,matrixB] -> matrixAB
 *)
DEF MatMul AS
   {[A,B] := id}
   [A,B|trans] | distr |
   EACH distl |
      EACH Inner END
   END;  
SHAR_EOF
if test -f 'Member'
then
	echo shar: over-writing existing file "'Member'"
fi
cat << \SHAR_EOF > 'Member'
(*
 * <S e> : Member -> #t if e is in sequence S, #f otherwise
 *
 * Examples:
 *      <<a b c d> c> -> t
 *      <<2 4 6 8> 3> -> f
 *)
DEF Member AS
   distr | EACH = END | any;

SHAR_EOF
if test -f 'Merge'
then
	echo shar: over-writing existing file "'Merge'"
fi
cat << \SHAR_EOF > 'Merge'
(*
 * Merge
 *
 * Merge two ascending sequences.
 *
 * The sequences should not mix strings and numbers.
 *
 * Example:
 *
 *	<<a b x z> <c d z>> : Merge -> <a b c d x y z>
 *)
DEF Merge AS
   IF EACH null END | or THEN cat
   ELSE
      IF EACH 1 END | > THEN reverse ELSE id END |
      [1|1,[1|tl,2]|Merge] | apndl
   END;

SHAR_EOF
if test -f 'MergeSort'
then
	echo shar: over-writing existing file "'MergeSort'"
fi
cat << \SHAR_EOF > 'MergeSort'
(*
 * MergeSort
 *
 * This function sorts a sequence of numbers or strings into ascending order
 * using merge sort.
 *
 * Examples:
 *
 *      <3 1 4 1 5 9 2> : MergeSort == <1 1 2 3 4 5 9>
 *
 *      <all work and no play> : MergeSort == <all and no play work>
 *
 * The sequence may not mix strings and numbers.
 *)
DEF MergeSort AS
   IF [length,#2] | < THEN id
   ELSE
       [id, [length,#2] | div] |
       [takel,dropl] | EACH MergeSort END | Merge
   END;

SHAR_EOF
if test -f 'Outer'
then
	echo shar: over-writing existing file "'Outer'"
fi
cat << \SHAR_EOF > 'Outer'
(* 
 * Outer product of two vectors 
 *)
DEF Outer AS 
   Cart | EACH EACH * END END;

SHAR_EOF
if test -f 'PasTri'
then
	echo shar: over-writing existing file "'PasTri'"
fi
cat << \SHAR_EOF > 'PasTri'
(*
 * Pascal's triangle generator
 *
 * n : PasTri -> first n rows of Pascal's triangle
 *
 * Example
 *              5 : PasTri -> <
 *                               <1>
 *                               <1 1>
 *                               <1 2 1>
 *                               <1 3 3 1>
 *                               <1 4 6 4 1>
 *                            >
 *)

DEF PasTri AS          
   IF [id,#0] | <= THEN #<<1>>
   ELSE
      sub1 | PasTri |                (* Create triangle with n-1 rows *)
      [
         id,  

         1r |                        (* Take last row of smaller triangle *)
         [
            [#0,id] | apndl,         (* Append 0 to left edge of row  *)
            [id,#0] | apndr          (* Append 0 to right edge of row *)
         ] | trans | EACH + END      (* Add corresponding elements *)

      ] | apndr                      (* Append new row to smaller triangle *)
   END;




SHAR_EOF
if test -f 'Permute'
then
	echo shar: over-writing existing file "'Permute'"
fi
cat << \SHAR_EOF > 'Permute'
DEF Permute AS
   IF null THEN #<<>>
   ELSE
      [id,length|iota] | distl |
      EACH
	 [pick,[takel|tlr,dropl]|cat|Permute] | distl | EACH apndl END
      END | cat
   END; 
SHAR_EOF
if test -f 'PigLatin'
then
	echo shar: over-writing existing file "'PigLatin'"
fi
cat << \SHAR_EOF > 'PigLatin'
(*
 * Convert sequence of words to pig-latin
 *
 * E.g.
 *      <Have a nice day> : PigLatin -> <aveHay a icenay ayday>
 *
 * The text processing is done via explode and implode.
 * `explode' converts a string into a sequence of characters (1 letter strings),
 * `implode' catenates a sequence of strings into a single string.
 *
 * Coded by Kevin Kenny and Arch Robison
 *)

DEF PigLatin AS

   EACH
      explode |

      IF EACH Vowel END | any | ~ THEN id    (* Not a word, don't mangle it *)
      ELSE

         IF 1|Vowel|~ THEN

            (* Word begins with a consonant - rotate first vowel to front. *)

            WHILE 1|Vowel|~ DO
               [tl,1]|apndr
            END

         ELSIF [1r|Vowel, [#<y Y>,1r]|member] | or THEN

            (* Word ends in vowel or 'y' - append a 'w' *)

            [id,#w] | apndr

         ELSE id
         END |

         [id,#<a y>] | cat

      END |

      implode
   END;

SHAR_EOF
if test -f 'PowerSet'
then
	echo shar: over-writing existing file "'PowerSet'"
fi
cat << \SHAR_EOF > 'PowerSet'
(*
 * PowerSet
 *
 * This function generates all subsets of a given set.  Sets are 
 * represented as sequences of distinct elements.
 *
 * Examples:
 *
 *      <> : PowerSet -> <<>>
 *
 *      <a b c> : PowerSet -> <<a,b,c>,<a,b>,<a,c>,<a>,<b,c>,<b>,<c>,<>>
 *)

DEF PowerSet AS
   IF null THEN [id] 
   ELSE 
      [1, tl | PowerSet] |
      [
         distl | EACH apndl END,
	 2 
      ] 
      | cat 
   END;

SHAR_EOF
if test -f 'QuickSort'
then
	echo shar: over-writing existing file "'QuickSort'"
fi
cat << \SHAR_EOF > 'QuickSort'
(*
 * QuickSort
 *
 * This function sorts a sequence of numbers or strings into ascending order
 * using the Quicksort algorithm.
 *
 * Examples:
 *
 *      <3 1 4 1 5 9 2> : QuickSort == <1 1 2 3 4 5 9>
 *
 *      <all work and no play> : QuickSort == <all and no play work>
 *
 * The sequence may not mix strings and numbers.
 *)

DEF QuickSort AS
   IF [length,#2] | < THEN id
   ELSE
      [id,1] | distr |
      [      
         FILTER < END | EACH 1 END | QuickSort,
         FILTER = END | EACH 1 END,
         FILTER > END | EACH 1 END | QuickSort
      ] | cat
   END;

SHAR_EOF
if test -f 'SelSort'
then
	echo shar: over-writing existing file "'SelSort'"
fi
cat << \SHAR_EOF > 'SelSort'
(*
 * Selection sort
 *
 * Example:
 *
 *      <3 1 4 1 5 9 2> : SelSort == <1 1 2 3 4 5 9>
 *
 * The sequence must be numeric.
 *)
DEF SelSort AS
   IF [length,#2] | < THEN id
   ELSE 
      [INSERT min END,id] | distl |
      [
         FILTER  = END | EACH 2 END,
         FILTER ~= END | EACH 2 END | SelSort
      ] | cat
   END;

SHAR_EOF
if test -f 'SlowSort'
then
	echo shar: over-writing existing file "'SlowSort'"
fi
cat << \SHAR_EOF > 'SlowSort'
(*
 * SlowSort
 *
 * Sort a sequence the hard way, i.e. take all permutations
 * and pick one for which all elements are in order.
 *)
DEF SlowSort AS
   Permute | 
   FILTER 
      [tl,tlr]|trans | EACH >= END | all 
   END | 1;

SHAR_EOF
if test -f 'Square'
then
	echo shar: over-writing existing file "'Square'"
fi
cat << \SHAR_EOF > 'Square'
(* Square a number - e.g. 3:Square -> 9 *)

DEF Square AS [id,id]|*;

SHAR_EOF
if test -f 'Tangent'
then
	echo shar: over-writing existing file "'Tangent'"
fi
cat << \SHAR_EOF > 'Tangent'
(* Trigonometric tangent function *)

DEF Tangent AS [sin,cos]|%;
SHAR_EOF
if test -f 'Text'
then
	echo shar: over-writing existing file "'Text'"
fi
cat << \SHAR_EOF > 'Text'
(*
 * Text
 * 
 * Example piece of text for use with PigLatin function.
 *
 * Example:
 *
 *	0 : Text | PigLatin -> ...
 *)

DEF Text AS
   #<All work and no play makes Jack a dull boy>;
SHAR_EOF
if test -f 'Vowel'
then
	echo shar: over-writing existing file "'Vowel'"
fi
cat << \SHAR_EOF > 'Vowel'
(*
 * Determine if a letter is a vowel.
 *
 * E.g.
 *      A : Vowel -> t
 *      u : Vowel -> t
 *      R : Vowel -> f
 *
 * This function is used by function PigLatin.
 *)

DEF Vowel AS 
   [#<a e i o u A E I O U>, id] | member;
SHAR_EOF
if test -f 'cotan'
then
	echo shar: over-writing existing file "'cotan'"
fi
cat << \SHAR_EOF > 'cotan'
(*
 * Trigonmetric cotangent function
 *)

DEF cotan AS [cos,sin] | %;

SHAR_EOF
if test -f 'Euler'
then
	echo shar: over-writing existing file "'Euler'"
fi
cat << \SHAR_EOF > 'Euler'
(*
 * Compute Euler's phi-function, i.e. number of number rel. prime to n.
 *
 * E.g. 8:Euler -> 4 since 1,3,5,7 are relatively prime to 8
 *)
DEF Euler AS
   [id,iota] | distl |
   EACH 
      WHILE [2,#0]|> DO [2,mod] END |
      IF [1, #1]|= THEN #1 ELSE #0 END 
   END | sum;

SHAR_EOF
if test -f '%DOC'
then
	echo shar: over-writing existing file "'%DOC'"
fi
cat << \SHAR_EOF > '%DOC'
This directory contains demonstration functions.  To use one, enter the
IFP command

     show input : function ;

where input is an appropriate object and function is one of the functions below:

     Abs - absolute value of a number
     cotan - find trigonometric cotangent of angle expressed in radians
     Debug - version of Fib with debugging messages
     Double - double a number
     Euler - Euler totient (phi) function
     Fib - find first n fibonacci numbers
     Inner - find inner product of two vectors
     Inter - set intersection
     Member - set membership
     PigLatin - converts sequence of words to Pig Latin
     PasTri - find first n rows of Pascal's triangle
     QuickSort - sort a sequence of numbers or sequence of strings
     Square - square a number
     Vowel - determine if a string is a vowel     

All IFP primitives are imported into this directory also, so you can
experiment with them.  Look in %IMPORT for their names.  The functions
are detailed in the file \IFP.TXT

SHAR_EOF
cd ..
if test ! -d 'math'
then
	mkdir 'math'
fi
cd 'math'
if test ! -d 'arith'
then
	mkdir 'arith'
fi
cd 'arith'
if test -f 'prod'
then
	echo shar: over-writing existing file "'prod'"
fi
cat << \SHAR_EOF > 'prod'
(*
 * prod
 *
 * Compute product of sequence.
 *
 * E.g. <10 2 3 4> : prod -> 240
 *)

DEF prod AS
   IF ../logic/null THEN #1
   ELSE
      INSERT * END
   END;
SHAR_EOF
cd ..
if test ! -d 'linear'
then
	mkdir 'linear'
fi
cd 'linear'
if test -f '%IMPORT'
then
	echo shar: over-writing existing file "'%IMPORT'"
fi
cat << \SHAR_EOF > '%IMPORT'
FROM /sys IMPORT
   apndl,apndr,cat,distr,distl,id,iota,length,tl,trans;

FROM /math/arith IMPORT
   +,-,*,%,exp,ln,sum;

FROM /math/logic IMPORT =,null;
SHAR_EOF
if test -f 'A'
then
	echo shar: over-writing existing file "'A'"
fi
cat << \SHAR_EOF > 'A'
(* Test case generator for L and U - check by trying A | [L,U] | MatMul *)

DEF A AS
   #<
       < 2.3  4.7 -2.7  5.7  7.4 2.1 12.7  1.1 32.1  4.5  1.1  8.3>
       < 1.7 -1.7  5.2  3.2  1.2 3.5  2.4  2.9  1.9  1.7 -4.5 -9.9>
       < 6.1  3.4  1.2 10.6  2.9 1.7  1.1 -0.3  1.2  3.2  1.6  1.3>
       <23.3 -9.7  2.4  5.2  7.6 1.1 86.2  1.7  3.2  9.7  1.2 87.1>
       < 1.2  3.4  4.5  6.7  9.8 0.1  2.1  5.7 -9.1 -5.2  0.2  1.7>
       <12.3  1.2  8.7 12.3 -4.7 -.1  3.2  2.1  4.3  1.8  1.9  2.3>
       < 5.7  4.7 -2.8  5.7  7.4 2.1 12.7  1.1 32.1  4.5  1.1  8.3>
       < 1.7 -6.7  5.6  7.4  1.2 3.5  2.7  2.8  1.9  1.7 -4.5 -9.9>
       < 3.1 -3.4 -9.2 10.6  8.9 1.7 -1.1 -0.3  3.2  3.2  1.6  1.3>
       <13.3 -9.7  5.2  7.6 1.1 86.2  1.3  3.2  9.7  1.2 87.1 -9.2>
       < 1.2  3.4 -4.5 -6.7  9.8 0.1 -2.1  5.8 -9.1 -5.2  0.2  1.7>
       <12.3  1.2 -8.7 12.3 -4.7 -.1 -3.2  1.8  1.9  2.3  3.1  4.3> 
   >;

SHAR_EOF
if test -f 'Aik'
then
	echo shar: over-writing existing file "'Aik'"
fi
cat << \SHAR_EOF > 'Aik'
(* Tail of matrix after gaussian elimination on (1|1) *)

DEF Aik AS 
   [
      MatTail, 
      [Li1|tl,U1k|tl] | Outer
   ] | MatSub;

SHAR_EOF
if test -f 'ApndlCol'
then
	echo shar: over-writing existing file "'ApndlCol'"
fi
cat << \SHAR_EOF > 'ApndlCol'
(* Append column (1) to left side of matrix (2) *)

DEF ApndlCol AS [1,2|trans] | apndl | trans;

SHAR_EOF
if test -f 'ApndrCol'
then
	echo shar: over-writing existing file "'ApndrCol'"
fi
cat << \SHAR_EOF > 'ApndrCol'
(* Append column (2) to right side of matrix (1) *)
DEF ApndrCol [1|trans,2] | apndr | trans;

SHAR_EOF
if test -f 'MatTail'
then
	echo shar: over-writing existing file "'MatTail'"
fi
cat << \SHAR_EOF > 'MatTail'
(* Deletes first row and column of matrix *)
DEF MatTail AS tl | EACH tl END;

SHAR_EOF
if test -f 'Outer'
then
	echo shar: over-writing existing file "'Outer'"
fi
cat << \SHAR_EOF > 'Outer'
(* Outer product of two vectors *)
DEF Outer AS Cart | EACH EACH * END END;

SHAR_EOF
if test -f '%DOC'
then
	echo shar: over-writing existing file "'%DOC'"
fi
cat << \SHAR_EOF > '%DOC'
This directory contains functions for linear matrix manipulation.
In particular, it contains L and U, which take the lower and upper 
parts of the LU decomposition of a matrix.
SHAR_EOF
if test -f 'Singleton'
then
	echo shar: over-writing existing file "'Singleton'"
fi
cat << \SHAR_EOF > 'Singleton'
(* Check if matrix is a singleton *)

DEF Singleton AS [length,#1]|=;

SHAR_EOF
if test -f 'U'
then
	echo shar: over-writing existing file "'U'"
fi
cat << \SHAR_EOF > 'U'
(* U part of LU decomposition of matrix *)

DEF U AS
   IF Singleton THEN id
   ELSE
      [
         U1k,
	 Aik | [EACH #0 END,U] | ApndlCol
      ] | apndl
   END;

SHAR_EOF
if test -f 'U1k'
then
	echo shar: over-writing existing file "'U1k'"
fi
cat << \SHAR_EOF > 'U1k'
(* First row of U part *)
DEF U1k AS 1;

SHAR_EOF
if test -f 'Cart'
then
	echo shar: over-writing existing file "'Cart'"
fi
cat << \SHAR_EOF > 'Cart'
(* Cartesian product of two vectors *)
DEF Cart AS distr | EACH distl END;

SHAR_EOF
if test -f 'Inner'
then
	echo shar: over-writing existing file "'Inner'"
fi
cat << \SHAR_EOF > 'Inner'
(* Inner product *)

DEF Inner AS 
   trans | EACH * END | 
   IF null THEN #0 
   ELSE INSERT + END 
   END;
SHAR_EOF
if test -f 'L'
then
	echo shar: over-writing existing file "'L'"
fi
cat << \SHAR_EOF > 'L'
(* L part of LU decomposition of matrix *)
DEF L AS
   IF Singleton THEN #<<1.0>>
   ELSE 
      [
         Li1,
	 Aik | [EACH #0 END,L] | apndl
      ] | ApndlCol
   END;

SHAR_EOF
if test -f 'LU'
then
	echo shar: over-writing existing file "'LU'"
fi
cat << \SHAR_EOF > 'LU'
(* 
 * LU
 *
 * [L,U] decomposition of matrix written as single function.
 * This function is functionally identical to [L,U]
 *)

DEF LU AS
   IF Singleton THEN [#<<1.0>>,id]        (* definition of L *)
   ELSE 
      [
         Li1,
         Aik | [EACH #0 END,LU],
	 U1k
      ] | 
      [
	 [
	    1,
	    2 | [1,2|1] | apndl
	 ] | ApndlCol,
	 [
	    3,
	    2 | [1,2|2] | ApndlCol
	 ] | apndl
      ]
   END;
SHAR_EOF
if test -f 'Li1'
then
	echo shar: over-writing existing file "'Li1'"
fi
cat << \SHAR_EOF > 'Li1'
(* First column of L part *)
DEF Li1 AS [EACH 1 END,1|1] | distr | EACH % END;

SHAR_EOF
if test -f 'MatAdd'
then
	echo shar: over-writing existing file "'MatAdd'"
fi
cat << \SHAR_EOF > 'MatAdd'
(* Matrix addition *)
DEF MatAdd AS MatCat | EACH EACH + END END;

SHAR_EOF
if test -f 'MatCat'
then
	echo shar: over-writing existing file "'MatCat'"
fi
cat << \SHAR_EOF > 'MatCat'
(* Converts pair of matrices to matrix of pairs *)

DEF MatCat AS trans | EACH trans END;

SHAR_EOF
if test -f 'MatMul'
then
	echo shar: over-writing existing file "'MatMul'"
fi
cat << \SHAR_EOF > 'MatMul'
DEF MatMul AS
   [1,2|trans] |
   distr |
   EACH distl |
      EACH Inner END
   END;  
SHAR_EOF
if test -f 'MatSub'
then
	echo shar: over-writing existing file "'MatSub'"
fi
cat << \SHAR_EOF > 'MatSub'
(* Matrix subtraction *)
DEF MatSub AS MatCat | EACH EACH - END END;

SHAR_EOF
if test -f 'VecAdd'
then
	echo shar: over-writing existing file "'VecAdd'"
fi
cat << \SHAR_EOF > 'VecAdd'
(* Vector addition *)
DEF VecAdd AS trans | EACH + END;

SHAR_EOF
if test -f 'VecSub'
then
	echo shar: over-writing existing file "'VecSub'"
fi
cat << \SHAR_EOF > 'VecSub'
(* Vector subtraction *)
DEF VecSub AS trans | EACH - END;

SHAR_EOF
cd ..
cd ..
cd ..
#	End of shell archive
exit 0

-- 

Rich $alz			"Anger is an energy"
Cronus Project, BBN Labs	rsalz@pineapple.bbn.com
Moderator, comp.sources.unix	sources@uunet.uu.net