/*
 *  mathematica.sli
 *
 *  This file is part of NEST.
 *
 *  Copyright (C) 2004 The NEST Initiative
 *
 *  NEST is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  NEST 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 NEST.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

/*
    SLI Interpeter initalization

*/

% ****************************************************************
% * SLI's Mathematica Style functions                            *
% * ---------------------------------                            *
% *                                                              *
% *                                                              *
% *                                                              *
% ****************************************************************

/mathematica /SLI ($Revision: 10098 $) provide-component
/mathematica /C++ (1.55) require-component


%% Mathematica style global Options

/* BeginDocumentation
Name: OptionsDictionary - Dictionary for global options
Synopsis: none

Description:
This dictionary contains the global option for
certain functions. Within the dictionary each
function name is associated with a dictionary
which contains the options for that function.

Note that the accessibility, i.e. the dicitonary
in which a function is defined is not accounted for.

It is suggested that you use a C++-like notation to indicate the
availability of the function, if the function is defined in some
"namespace" dictionary.
For example: "arr::Mean".

Diagnostics: None.
Author: M. O. Gewaltig

SeeAlso: GetOption, GetOptions, ShowOptions, SetOptions, Options, ResetOptions, SaveOptions, RestoreOptions
*/

/OptionsDictionary << >> def

/* BeginDocumentation
Name: Options - Define a new set of options for a given name.
Synopsis: /f  optiondict Options -> --

Description:
Options defines a set of options for a name.
The options are supplied in a dictionary. Old
option values are overwritten by this operation.
Options should be used to initially define a
set of options for a given name. Use SetOptions
to modify one or more options from this set.

In addition to the supplied options, Options adds
the options /DefaultOptions with the original option
values.

It is suggested that you use a C++-like notation to indicate the
availability of the function, if the function is defined in some
"namespace" dictionary.
For example: "arr::Mean".

Diagnostics: None
Author: M. O. Gewaltig

SeeAlso: GetOption, GetOptions, ShowOptions, SetOptions, ResetOptions, SaveOptions, RestoreOptions, OptionsDictionary
*/

/Options
trie [/literaltype /dictionarytype]
{
  systemdict
  begin
   OptionsDictionary
   begin
    2 copy
    def
   end
   begin % Open Options
    /DefaultOptions currentdict clonedict exch pop def
   end
   pop
  end
} bind addtotrie def

/* BeginDocumentation
Name: SetOptions - Set options for a given name
Synopsis: /f  optiondict SetOptions -> --

Description:
SetOptions set all option values given in
the supplied dictionary. Options which are not listed
in this dicitonary are not modified.
Note that only those options can be modified which were
initially defined by the Options command.

Use the option /DefaultOptions to retrieve the default
values for all options.

Usually, a C++-like notation is used to indicate the
availability of the function, if the function is defined in some
"namespace" dictionary.
For example: "arr::Mean".

Diagnostics: SetOptions gives a warning message for each unknown
             options it encounters.

Author: M. O. Gewaltig

SeeAlso: GetOption, GetOptions, ShowOptions, Options, ResetOptions, SaveOptions, RestoreOptions, OptionsDictionary
*/

/SetOptions
trie [/literaltype /dictionarytype]
{
  1 index GetOptions
    begin
    cva 2 2 Partition
    {
      arrayload pop
      exch cvlit
      dup DefaultOptions exch known
      {
        exch def
      }
      {
        M_WARNING exch (SetOptions) exch cvs (Unknown option for command ') 5 index cvs join (': ) join exch join message
        pop
      } ifelse
    } forall
    pop
    end
} bind addtotrie def

/* BeginDocumentation
Name: GetOptions - Get all options for a given name
Synopsis: /f  GetOptions -> optiondict

Description:
Usually, a C++-like notation is used to indicate the
availability of the function, if the function is defined in some
"namespace" dictionary.
For example: "arr::Mean".

Diagnostics:
Raises /NoOptionsAvailable if there are no
options associated with the name.

Author: M. O. Gewaltig

SeeAlso: GetOption, ShowOptions, SetOptions, Options, ResetOptions, SaveOptions, RestoreOptions, OptionsDictionary
*/

/GetOptions
{
  systemdict
  begin
    OptionsDictionary 1 index known
    {
      OptionsDictionary exch get
    }
    {
    end	/GetOptions /NoOptionsAvailable raiseerror
    } ifelse
  end
} bind def

/* BeginDocumentation
Name: ShowOptions - Display all options for a given name
Synopsis: /f  ShowOptions -> --

Description:
Usually, a C++-like notation is used to indicate the
availability of the function, if the function is defined in some
"namespace" dictionary.
For example: "arr::Mean".

Diagnostics: None
Author: M. O. Gewaltig
SeeAlso: GetOption, GetOptions, SetOptions, Options, ResetOptions, SaveOptions, RestoreOptions, OptionsDictionary
*/

/ShowOptions
{
  GetOptions info
} bind def

/* BeginDocumentation
Name: GetOption - get the value of a procedure option
Synopsis: /f /opt GetOption -> val

Description:
Retrieves the value for a specific option
of a function.

Usually, a C++-like notation is used to indicate the
availability of the function, if the function is defined in some
"namespace" dictionary.
For example: "arr::Mean".

Diagnostics: Raises UnknownOption if the supplied option
             is unknown.

SeeAlso: GetOptions, ShowOptions, SetOptions, Options, ResetOptions, SaveOptions, RestoreOptions, OptionsDictionary
*/

/GetOption
{
  1 index GetOptions % /f /opt << >>
  dup 2 index known
  {
    1 index get
    3 1 roll 2 npop
  }
  {
    2 npop
    /GetOption /UnknownOption raiseerror
  } ifelse
} bind def


%----------------------------------------------------------------------------
/* BeginDocumentation

Name: SaveOptions - temporarily save options of a command

Synopsis:
  /f SaveOptions -> -

Description:

Usually, a C++-like notation is used to indicate the
availability of the function, if the function is defined in some
"namespace" dictionary.
For example: "arr::Mean".

Author: Ruediger Kupper

FirstVersion: 7.3.2003

SeeAlso: GetOption, GetOptions, ShowOptions, SetOptions, Options, ResetOptions, RestoreOptions, OptionsDictionary
*/

/SaveOptions [/literaltype]
{
  %stack: /f
  GetOptions clonedict
  %stack: <<options>> <<copy-of-options>>
  dup /DefaultOptions undef
  /SavedOptions exch put
} def

%----------------------------------------------------------------------------
/* BeginDocumentation

Name: RestoreOptions - Restore the temporaryly saved options of a command

Synopsis:
  /f RestoreOptions -> -

Description:

Usually, a C++-like notation is used to indicate the
availability of the function, if the function is defined in some
"namespace" dictionary.
For example: "arr::Mean".

Author: Ruediger Kupper

FirstVersion: 7.3.2003

SeeAlso: GetOption, GetOptions, ShowOptions, SetOptions, Options, ResetOptions, SaveOptions, OptionsDictionary
*/

/RestoreOptions [/literaltype]
{
  %stack: /f
  dup dup /SavedOptions GetOption
  %stack: /f /f <<saved-options>>
  SetOptions
  %stack: /f
  GetOptions /SavedOptions undef
} def

%----------------------------------------------------------------------------
/* BeginDocumentation

Name: ResetOptions - Reset all options of a command to their default values.

Synopsis:
  /f ResetOptions -> -

Description:

Usually, a C++-like notation is used to indicate the
availability of the function, if the function is defined in some
"namespace" dictionary.
For example: "arr::Mean".

Author: Ruediger Kupper

FirstVersion: 28.3.2003, by copy-paste-and-modify from RestoreOptions

SeeAlso: GetOption, GetOptions, ShowOptions, SetOptions, Options, SaveOptions, RestoreOptions, OptionsDictionary
*/

/ResetOptions [/literaltype]
{
  %stack: /f
  dup /DefaultOptions GetOption
  %stack: /f <<default-options>>
  SetOptions
} def




/* BeginDocumentation
Name: JoinTo - Join an object to a container

Synopsis:
array literal JoinTo -> --
dict  literal JoinTo -> --
Description:
 Assignment like AddTo. Compared to Mathematica the order of
 arguments is reversed here, because its more readable to
 have the l-value close to the assignment operator,
 like in ... // Set[x,#]& .
 Allows for optimization of code.
Examples:
/j [4 5] def [6 7 8] /j JoinTo j --> [4 5 6 7 8]
/j << /C_m 250.0 /Tau_m 10.0 >> def
<< /Tau_m 25.0 /I_e 130.0 >> /j JoinTo j --> << /C_m 250.0 /Tau_m 25.0 /I_e 130.0 >>

SeeAlso: Set, AppendTo, MergeDictionary
*/
/JoinTo_cont
{
 dup load
 3 -1 roll
 join
 def
} bind def

/JoinTo_ald
{
 2 copy    % v l d l d
 5 2 roll  % l d v l d
 exch      % l d v d l
 get_d     % l d v a
 exch      % l d a v
 join      % l d av
 exch      % l av d
 rollu     % d l av
 put_d
} def

/JoinTo_d
{
  load     % d2 d1
  exch     % d1 d2
  join_d
} def

/JoinTo trie
[/arraytype /literaltype /dictionarytype] /JoinTo_ald load addtotrie
[/stringtype /literaltype /dictionarytype] /JoinTo_ald load addtotrie
[/arraytype /literaltype] /JoinTo_cont load addtotrie
[/stringtype /literaltype] /JoinTo_cont load addtotrie
[/dictionarytype /literaltype] /JoinTo_d load addtotrie
def


%
%  /j << /C_m 250.0 /Tau_m 10.0 >> def
%   j << /Tau_m 25.0 /I_e 130.0 >> join_d
%
%  --> << /C_m 250.0 /Tau_m 25.0 /I_e 130.0 >>
%
/join_d
{
 % d1 d2
  cva 2 2 Partition
  {
    1 index exch
    arrayload pop
    put
  } forall
 pop
} def


/join
 /join load
 [/dictionarytype /dictionarytype] /join_d load addtotrie
def









/* BeginDocumentation
Name: AppendTo - Append an object to a container

Synopsis: any literal AppendTo -> --

Description:
 Assignment like AddTo. Compared to Mathematica the order of
 arguments is reversed here, because its more readable to
 have the l-value close to the assignment operator,
 like in ... // Set[x,#]& .
 Allows for optimization of code.
Examples: /j [4 5] def  7 /j AppendTo j --> [4 5 7]
Author: Diesmann
FirstVersion: 8.5.01
SeeAlso: Set, JoinTo
*/
/AppendTo
[/anytype /literaltype]
{
 dup load
 3 -1 roll
 append
 def
}
def

/AppendTo
[/anytype /literaltype /dictionarytype]
{
 2 copy    % v l d l d
 5 2 roll  % l d v l d
 exch      % l d v d l
 get_d     % l d v a
 exch      % l d a v
 append    % l d av
 exch      % l av d
 rollu     % d l av
 put_d
} def




% documentation in sli/slicontrol.cc
/Set_ /Set load def

/Set trie
  [/anytype /literaltype] /Set_ load addtotrie
def

/Set
[/arraytype /arraytype]
{
2 arraystore Transpose
{
 arrayload ;
 Set
}
forall

}
def


/* BeginDocumentation
Name: ReplacePart - replaces particular elements of an array
Synopsis: array1 any integer ReplacePart -> array3
          array1 any array2  ReplacePart
Description:
 Replaces the elements of array1 specified by the integer or
 by array2 with the 2nd argument any and returns the resulting
 array.
Parameters:
 The integer specifies a position in array1. array2 specifies a
 multi-dimensional position [i, j,...] in array1 or a list of
 positions [ [i1,j1,...], [i2,j2,...], ...].
Examples:
 [3, {-11, 5}, {9}, 7] 4 2 ReplacePart
  -> [3 4 [9] 7]
 [3 [-11 5] [9] 7] 4 [2 1] ReplacePart
  -> [3 [4 5] [9] 7]
 [3 [-11 5] [9] 7] 4 [[2] [4]] ReplacePart
  -> [3 4 [9] 4]
 [3 [-11 5] [9] 7] 4 [[2 1] [3 1]] ReplacePart
  -> [3 [4 5] [4] 7]

Author: Diesmann
FirstVersion: 2007.11.28
Remarks:
 The variant of this function with four arguments is not implemented
SeeAlso: MapAt, ReplaceOccurrences, Part
References:
   [1] The Mathematica Book V4.0 "Part"
*/

/ReplacePart [/arraytype /anytype /integertype]
{
 % a v i
 ReplacePart_i_
} def

/ReplacePart_i_
{
 % a v i
 exch
 % a i v
 rollu
 % v a i
 2 copy
 % v a i a i
 [1] exch 1 sub append
 % v a i a [1 i-1]
 Take
 % v a i al
 rollu
 % v al a i
 [-1] exch 1 add prepend
 % v al a [i+1 -1]
 Take
 % v al ar
 rolld
 % al ar v
 prepend
 % al var
 join
} def

/ReplacePart [/arraytype /anytype /arraytype]
{
 % a v i
 dup First
 % a v i First(i)
 ArrayQ
 {
  % a v i First(i)
  pop
  % a v i, First(i) is an array: i is list of indices
  {
   % a v k, with k iterating over First(i)
   1 index
   % a v k v
   4 1 roll
   % v a v k
   ReplacePart_a_
   % v a
   exch
   % a v
  }
  forall
  % a v
  pop
  % a
 }
 {
  % a v i First(i)
  pop
  % a v i, First(i) is not an array: i is mult-dim index
  ReplacePart_a_
 }
 ifelse
} def

/ReplacePart_a_
{
 % a v i, i is multi-dim index
 dup length
 1 eq
 {
  % a v i, i has length 1
  First
  % a v ii
  ReplacePart_i_
 }
 {
  % a v i, i has more than 1 element
  exch
  % a i v
  rollu
  % v a i
  dup Rest
  % v a i ir
  rollu
  % v ir a i
  First
  % v ir a First(i)
  2 copy 2 copy
  % v ir a i a i a i
  [1] exch 1 sub append
  % v ir a i a i a [1 i-1]
  Take
  % v ir a i a i al
  5 1 roll
  % v ir al a i a i
  [-1] exch 1 add prepend
  % v ir al a i a [i+1 -1]
  Take
  % v ir al a i ar
  rollu
  % v ir al ar a i
  MathematicaToSliIndex_i get
  % v ir al ar ai
  5 -2 roll
  % al ar  ai v ir
  ReplacePart_a_
  % al ar vi
  prepend
  % al viar
  join
  % a
 }
 ifelse
} def




/* BeginDocumentation
Name: ReplaceOccurrences - replace the occurences of a key in a container
Synopsis:  l1 l2 l3 ReplaceOccurrences l4
Description:
 Replaces all occurences of l2 in l1 by l3 and
 returns the result. Works for strings and arrays.

Examples:
  (L: 'Where?') (') ('') ReplaceOccurrences (L: ''Where?'')
  [4 5 6 7 5 8 9] [5] [-1 -2]  ReplaceOccurrences
Author: -unknown- Diesmann? Hehl?
*/

/ReplaceOccurrences
{
<< >>
begin
 container /r Set_            % create empty object
 /v Set_                      % save replacement
 {
  search
  exch_                        % get pre save boolean
  /r JoinTo                   % append pre to r
  {r v join /r Set_     }      % append '' if ' leave post and match
  {exit}                      % ready
  ifelse
 } loop
 r
end
} bind def



% Map:   string procedure Map array
% ----
%
% Example:
%    (1 2 3) {1 add} Map_s --> (2!3!4)
%

/Map_s
{
 mark
 3 1 roll
 forall_s
 counttomark
 () exch
 {
   exch append
 } repeat
 reverse exch pop

} bind def


/Map_iter
{
 % i p
 exch size
 % p i s
 [] exch reserve
 % p i a
 rollu exch
 % a i p
 {append} join
 % a i p
 forall
 % a
} def


/Map_ /Map load def
/Map trie
[/arraytype /proceduretype] /Map_ load addtotrie
[/iteratortype /proceduretype] /Map_iter load addtotrie
[/stringtype /proceduretype] /Map_s load addtotrie
def


/* BeginDocumentation
Name: MapAt - applies a function to some of the elements of its argument
Synopsis: array1 proc array2 MapAt -> array3
Description:
 MapAt successively applies proc to the elements of array1
 specified by array2 and replaces the original values by the
 return value of proc. The return value array3 has exactly the
 same shape as the first argument array1.

 Compared to languages like Matlab MapAt constitutes an lhs
 assignment operator for constructs like a(i)=f(a(i)), where
 i may be an array of indices. However, unlike in Matlab no
 temporary object a(i) for the rhs expression is created.
 Consequently, if the index ii occurs in array i n times the
 final value of a(ii) returned by MapAt is the cumulative effect
 of f operating n times on the original value of a(ii):
   a(ii) <- f(f(...f(a(ii))...))
             n times
 In Matlab the result is f(a(ii)), independent of n.
 The behavior of MapAt is, for example, useful in counting
 processes like the construction of a histogram as shown in the
 last example of the examples section.

 Parameters:
  array1 is an arbitrarily shaped array. In particular
  it does not need to be rectangular.
  array2 specifies a multi-dimensional position [i, j,...]
  in array1 or a list of positions [ [i1,j1,...], [i2,j2,...], ...].
  The same element may be specified multiple times in array2 at
  arbitrary positions.

  The first element on each level has index 1. Indices can also
  be specified counting from the end of the array, in this case the
  last element has index -1. Positive and negative indices can
  arbitrarily be intermixed.

Examples:

  [3 4 5 6 7] {dup mul} -2 MapAt
   -> [3 4 5 36 7]
  [3 [-9 -12] 5 6 7] {dup mul} [2 2] MapAt
   -> [3 [-9 144] 5 6 7]
  [3 4 5 6 7] {dup mul} [[1] [3]] MapAt
   -> [9 4 25 6 7]
  [[3 9] 4 [5 -11] 6 7] {dup mul} [[1 2] [3 1]] MapAt
   -> [[3 81] 4 [25 -11] 6 7]

  [0 0 0 0 0] {1 add} [2 4 5 2 3 2 2 5] 1 1 Partition MapAt
   -> [0 4 1 1 2]

Author: Diesmann
FirstVersion: 2007.08.12
Remarks:
 This function is an implementation of Mathematica's MapAt function.
 Mathematica-style functions in SLI use Mathematica index notation.
SeeAlso: ReplacePart, Part, Map, Partition
References:
 [1] The Mathematica Book V4.0 "Part"
*/

/MapAt [/arraytype /proceduretype /integertype]
{
 % a f i
 MapAt_i_
} def

/MapAt_i_
{
 % a f i
 exch
 % a i f
 rollu
 % f a i
 2 copy
 % f a i a i
 5 2 roll
 % a i f a i
 MathematicaToSliIndex_i get
 % a i f ai
 exch
 % a i ai f
 exec
 % a i v
 exch
 % a v i
 ReplacePart_i_
} def


/MapAt [/arraytype /proceduretype /arraytype]
{
 % a f i
 dup First
 % a f i First(i)
 ArrayQ
 {
  % a f i First(i)
  pop
  % a f i, First(i) is an array: i is list of indices
  {
   % a f k, with k iterating over First(i)
   1 index
   % a f k f
   4 1 roll
   % f a f k
   MapAt_a_
   % f a
   exch
   % a f
  }
  forall
  % a f
  pop
  % a
 }
 {
  % a f i First(i)
  pop
  % a f i, First(i) is not an array: i is mult-dim index
  exch
  % a i f
  2 index
  % a i f a
  2 index
  % a i f a i
  Part
  % a i f ai
  exch
  % a i ai f
  exec
  % a i aif
  exch
  % a aif i
  ReplacePart_a_
 }
 ifelse
} def

/MapAt_a_
{
 % a f i, i is multi-dim index
 dup length
 1 eq
 {
  % a f i, i has length 1
  First
  % a f ii
  MapAt_i_
 }
 {
  % a f i, i has more than 1 element
  exch
  % a i f
  2 index
  % a i f a
  2 index
  % a i f a i
  First
  % a i f a ii
  MathematicaToSliIndex_i get
  % a i f ai
  exch
  % a i ai f
  2 index
  % a i ai f i
  Rest
  % a i ai f ir
  MapAt_a_
  % a i aif
  exch
  % a aif i
  First
  % a aif ii
  ReplacePart_i_
 }
 ifelse
} def



/* BeginDocumentation
 Name: Range - Generate array with range of numbers
 Synopsis:  [N] Range  -> [1 ... N]
            [N1 N2] Range -> [N1 ... N2]
            [N1 N2 d] Range -> [N1 N1+d N1+2d ...]
 Description:
    Range accepts an array which contains either
    1) a single integer
    2) an interval specified by two integers or two doubles
    3) an interval and a stepsize, specified by three integers or
       three doubles.

    Range generates an array with numbers which are in the specified
    range. The type of the result corresponds to the type used for
    specifying the interval.

    Range returns an empty array if the set specified by N1, N2 and d
    does not contain any element. This behavior is essential if
    Range is used in combination with functional operators like
    FoldList and NestList.

 Examples:
          [5] Range    -> [1 2 3 4 5]
        [2 5] Range    -> [2 3 4 5]
        [5 2] Range    -> []
        [5 2 -1] Range -> [5 4 3 2]
        [1.0 10.0 2.5] Range -> [1 3.5 6 8.5]
 Bugs:
 Author: Gewaltig, Diesmann
 Remarks: Resembles the function Range of Mathematica
 SeeAlso:  Map, Table
*/

/Range_ /Range load def
/Range trie
[/arraytype] /Range_ load addtotrie
def

/RangeIterator
[/arraytype]
{
 size 1 eq
 {
  1 prepend 1 append RangeIterator_a
 }
 {
  size 2 eq
  {
   1 append RangeIterator_a
  }
  {
   RangeIterator_a
  } ifelse
 } ifelse
}
def



/* BeginDocumentation
 Name: Table - Generate an array according to a given function
 Synopsis:  [N]       {f} Table  -> [f(1) ... f(N)]
            [N1 N2]   {f} Table  -> [f(N1) ...f(N2)]
            [N1 N2 d] {f} Table -> [ f(N1) f(N1+d) f(N1+2d) ...]
 Description:
    Table accepts an array which contains either
    1) a single integer
    2) in interval specified by two integers or two doubles
    3) an interval and a stepsize, specified by three integers or
       three doubles.
    and a procedure object which is to be applied. From the
    interval specification an array of numbers is generated, using Range.
    The supplied procedure is the applied to each number in the array.

 Examples:
          [5] {2 mul} Table  -> [2 4 6 8 10]
        [2 5] {2 mul} Table  -> [4 6 8 10]
        [1.0 10.0 2.5] {2 mul} Table  -> [2.0 7.0 12.0 17.0]
 Bugs:
 Author: Gewaltig
 Remarks: Resembles the function Table of Mathematica
 References:
 SeeAlso: Map, MapIndexed, Range, forall, forallindexed
*/

/Table_
{
 mark
 3 1 roll
 exch_ Range exch_
 forall_a
 counttomark
 arraystore
 exch_ pop_
} bind def

/Table trie
[/arraytype /proceduretype] /Table_ load addtotrie def

/*
BeginDocumentation

   Name: MapIndexed - Apply a function  to each element of a list/string

   Synopsis:
     [v0 ... vn] {f} Map -> [ f(0,v0) ... f(n,vn) ]

   Parameters:
     [v0 ... vn] - list of n+1 arbitrary objects or string.

     {f}         - function of two arguments and one return value.

   Description:
     For each element of the input array, MapIndexed calls f with
     two arguments, the current index and the element. It replaces
     the element with the result of f.
     MapIndexed works similar to Map, however, in adition to the
     element its index within the array is also passed to the function.
     Note that the index starts with 0, according to PostScript convention.
     The result of MapIndexed is a list with the same number of values as the
     argument list.
     If f does not return a value, MapIndexed fails.
     If f returns more than one value, the result of MapIndexed is
     undefined.

     Alternatives: Function MapIndexed_a for lists and  MapIndexed_s
     for strings (both undocumented) -> behaviour and synopsis are
     the same.

   Examples:

   [1 2 3 4 5]  {add} MapIndexed -> [1 3 5 7 9]
   (abcd) {add} MapIndexed -> (aceg)

   Diagnostics: None

   Bugs:

   Author:
    Marc-Oliver Gewaltig

   References: The Mathematica Book

   SeeAlso: Map, Table, forall, forallindexed

*/

/*
/MapIndexed_a
{
  mark
  3 1 roll
  forallindexed_a
  counttomark
  arraystore
  exch_ pop_
} bind def
*/

/MapIndexed_s
{
 mark
 3 1 roll
 forallindexed_s
 counttomark
 () exch_
 {
   exch_ append_s
 } repeat_
 reverse exch_ pop_
} bind def

/MapIndexed trie
[/arraytype /proceduretype] /MapIndexed_a load addtotrie
[/stringtype /proceduretype] /MapIndexed_s load addtotrie
def

/MapThread trie
 [/arraytype /proceduretype] /MapThread_a load addtotrie
def

% * List Operations
/*BeginDocumentation
Name: First - Return the first element of an array or string.

Synopsis: string First -> char
array First -> arrayelement

Examples: (train) First -> 104
[1 2 3] First -> 1
[(this) (is) (an) (example)] First -> (this)

Author: docu edited by Sirko Straube

SeeAlso: Last, Rest, Most
*/

/First { 0 get }    bind def

/*BeginDocumentation
Name: Last - Return the last element of an array or string

Synopsis: string Last -> char
array Last -> arrayelement

Examples: (train) Last -> 110
[1 2 3] Last -> 3
[(this) (is) (an) (example)] Last -> (example)

Author: docu edited by Sirko Straube

SeeAlso: First, Rest, Most
*/
/Last  { size 1 sub_ii get } bind def

/*BeginDocumentation
Name: Rest - Remove the first element of an array or string and return
the rest.

Synopsis: string Rest -> string
array Rest -> array

Examples: (train) Rest -> (rain)
[1 2 3] Rest -> [2 3]
[(this) (is) (an) (example)] Rest -> [(is) (an) (example)]

Author: docu edited by Sirko Straube

SeeAlso: First, Last, Most
*/
/Rest  { 0 1 erase} bind def




/*BeginDocumentation
Name: Most - Remove the last element of an array or string and return the rest.
Synopsis: string Most -> string
array Most -> array

Examples: (computer) Most -> (compute)
[1 2 3] Most -> [1 2]
[(this) (is) (an) (example)] Rest -> [(this) (is) (an)]

Remarks:
In 2003 this function did not exist in Mathematica and was
introduced as LRest by Kupper. Mathematica 5 introduced the
function and its SLI Name was changed for compatibility
(Apr 2008, Diesmann).

Author: Ruediger Kupper, docu edited by Sirko Straube

FirstVersion: 10.3.2003
SeeAlso: First, Last, Rest
*/
/Most [/arraytype]  { size 1 sub 1 erase } bind def
/Most [/stringtype] { size 1 sub 1 erase } bind def

/LRest
{
 M_WARNING (LRest) (LRest deprecated, use Most for Mathematica compatibility) message
 Most
}
def


/Flatten_ /Flatten load def

% a
/Flatten_a
{
 /Flatten_ load  % a p
 FixedPoint__p
} def

% a i
/Flatten_a_i
{
 /Flatten_ load  % a n p
 exch            % a p n
 FixedPoint__p_i
} def

/*BeginDocumentation
Name: Flatten - flatten out a nested list
Synopsis:
         array         Flatten -> array
         array integer Flatten -> array
Description:
Flatten called with one argument flattens out all levels of
the argument. Flatten called with two arguments flattens out
the first n levels.
Examples:
        [3 [4 [5 [6]]] 7] Flatten   -->  [3 4 5 6 7]
        [3 [4 [5 [6]]] 7] 1 Flatten -->  [3 4 [5 [6]] 7]
        [3 [4 [5 [6]]] 7] 2 Flatten -->  [3 4 5 [6] 7]
Author: Gewaltig, Diesmann
FirstVersion: Gewaltig
References:
  [1] The Mathematica Book V4.0 "Flatten"
SeeAlso: Partition, FixedPoint
*/

/Flatten trie
[/arraytype /integertype]
 /Flatten_a_i load  addtotrie
[/arraytype ]
 /Flatten_a load  addtotrie
def


% x f
/FixedPoint__p
{
 exch    % f x
 {
  dup    % f x x
  2 pick % f x x f
  exec   % f x f(x)
  dup    % f x f(x) f(x)
  rolld  % f f(x) f(x) x
  eq     % f f(x) bool
  {
   exit
  }
  if     % f f(x)
 } loop
 exch pop % f(x)
} def


% x f n
/FixedPoint__p_i
{
 rollu
 exch
 rolld   % f x n
 {
  dup    % f x x
  2 pick % f x x f
  exec   % f x f(x)
  dup    % f x f(x) f(x)
  rolld  % f f(x) f(x) x
  eq     % f f(x) bool
  {
   exit
  }
  if     % f f(x)
 } repeat
 exch pop   % f(x)
} def

/*BeginDocumentation
Name: FixedPoint - applies a procedure repeatedly until the result is an invariant
Synopsis:
         any proc         FixedPoint -> any
         any proc integer FixedPoint -> any
Description:
FixedPoint called with three arguments applies the procedure not more
than n times. The first argument is the initial value.
Examples:
 (kaeschperle) {Rest (_) join} FixedPoint   --> (___________)
 (kaeschperle) {Rest (_) join} 1 FixedPoint --> (aeschperle_)
 (kaeschperle) {Rest (_) join} 3 FixedPoint --> (schperle___)
Remarks:
Compared to Mathematica the first two arguments are reversed
for better conformance with RPN.
Author: Diesmann
FirstVersion: May 21 2001
References:
  [1] The Mathematica Book V4.0 "Flatten"
SeeAlso: Flatten
*/

/FixedPoint trie
[/anytype /proceduretype /integertype]
 /FixedPoint__p_i load  addtotrie
[/anytype /proceduretype ]
 /FixedPoint__p load  addtotrie
def


/*
BeginDocumentation

   Name: Partition - Partition list into n element pieces

   Synopsis:
     array n Partition
     array n d Partition

   Description:
     Partition works like the corresponding Mathematica function. Partition
     creates subarrays with n elements, and offset d.

   Parameters:
     n - length of subarray.
     d - offset of subarray, defaults to n.
   Examples:

   [1 2 3 4 5 6 7 8 9 10]  2 2 Partition -> [[1 2] [3 4] [5 6] [7 8] [9 10]]
   [1 2 3 4 5 6 7 8 9 10]  1 2 Partition -> [[1] [3] [5] [7] [9] [10]]
   [1 2 3 4 5 6 7 8 9 10]  2 1 Partition ->
              [[1 2] [2 3] [3 4] [4 5] [5 6] [6 7] [7 8] [8 9] [9 10]]

   [4 5 6 7 8] 2     Partition  ->  [[4 5] [6 7]]
   [4 5 6]     2 5   Partition  ->  [[4 5]]
   [4 5 6]     5 1   Partition  ->  []
   [4 5 6]     5 7   Partition  ->  []


   Diagnostics:
     Raises error if n<0 or d<1

   Remarks: Still implements only part of Mathematica's functionality.

   Author: Gewaltig, Diesmann

   FirstVersion:  Jun 29 1999, Marc-Oliver Gewaltig

   References: "The Mathematica Book"
   SeeAlso: Flatten
*/
/Partition trie
[/arraytype /integertype /integertype] /Partition_a_i_i load addtotrie
[/arraytype /integertype ] {dup} /Partition_a_i_i load append addtotrie
def




%% array TensorRank -> n
/TensorRank_
{
  1
  {
    exch_ 0 get_a
    dup_ type
    /arraytype neq
    {
      pop_ exit
    } if
    exch_ 1 add_ii
  } loop
} bind def

/*BeginDocumentation
Name: TensorRank - Determine the level to which an array is a full vector
Synopsis: [array] TensorRank -> n
Examples:
           [1 2 3] TensorRank -> 1
           [[1 2] [3 4]] TensorRank -> 2
SeeAlso: Dimensions
*/
/TensorRank trie
 [/arraytype] /TensorRank_ load addtotrie
def

/TensorRank [/intvectortype] {; 1} def
/TensorRank [/doublevectortype] {; 1} def

/*BeginDocumentation
Name: Dimensions - determine dimenstions of a (hyper-rectangular) SLI array
Synopsis: [array] Dimensions -> [d1 d2 ... dn]
Description:
Dimensions corresponds to the Mathematica function of
the same name. It takes a sli array and returns a list with
dimensions [d1 d2 ... dn] where di gives the dimension of the
array at level i.
The length of the dimensions-list corresponds to the TensorRank of
the array.
Note: Dimensions assumes that the array is hyper-rectangular
      (rectangle,cuboid, ...), i.e., all subarrays at a given level
      have the same number of elements.
      Dimensions does not check, if the array really is hyper-rectangular. It
      will not fail if this is not the case. Instead, the dimensions
      that are returned correspond to the number of elements of the
      first subarray in each level.

Examples:
SLI ] [1 2 3]                    Dimensions -> [3]
SLI ] [[1 2 3] [4 5 6]]          Dimensions -> [2 3]
SLI ] [[[1 2][3 4]][[5 6][7 8]]] Dimensions -> [2 2 2]

SeeAlso: TensorRank, MatrixQ
*/

/Dimensions
trie [/arraytype]
{
  [] exch_
  %% [] obj
  {
    %% [] obj
    dup_ type
    %% [] obj type
    /arraytype neq
    { pop_ exit } if
    size_a
    dup
    0 gt
    {
     %% [] array s
     exch_ 0 get_a
     %% [] s obj
     3 1 roll
     %% obj [] s
     append_a exch_
    }
    {
     %% [] array s
     exch_ pop
     append_a
     exit
    } ifelse
  } loop
} bind addtotrie def

/Dimensions [/intvectortype] { length 1 arraystore } def
/Dimensions [/doublevectortype] { length 1 arraystore } def

/*BeginDocumentation
Name: MatrixQ - Test whether a nested array i a matrix
Synopsis: [array] MatrixQ -> true | false
Examples: [1 2 3] MatrixQ -> true
          [[1 2] [3 4]] MatrixQ -> true
          [[1] [2 3]] MatrixQ ->False
Bugs: This version fails on the third example
Author: Marc-Oliver Gewaltig
*/
/MatrixQ
trie [/arraytype]
{
  dup type
  /arraytype eq
  {
    %% array
    dup Dimensions
    %% array [dims]
    length 1 eq
    {
      true exch
      {
	MatrixQ not and
      } forall
    }
    {
      %% array
      true exch
      {
        MatrixQ and
 %       dup =
      } forall
    } ifelse
  }
  {
    pop false
  } ifelse
} bind addtotrie
[/anytype] {pop false} addtotrie
 def

/MatrixQ [/intvectortype] false def
/MatrixQ [/doublevectortype] false def

/* BeginDocumentation
  Name: FindRoot - numerically find a root in an interval
  Synopsis: proc double1 double2 double3 FindRoot -> double
  Description:
     Numerically searches for a root of a function
     specified by proc in the interval [double1, double2].
     The search stops when the absolute value of proc
     is less or equal double3.
  Parameters:
  Examples:
    cout 15 setprecision                   % for display only
    {dup mul 2 sub} -3.0 7.0 0.00000000001 FindRoot
  Bugs:
   - should raise error when there is no sign reversal
   - tracing should be optional
   - specification of precision should be optional
  Author: Diesmann, Hehl
  FirstVersion: 29.7.1999
  Remarks:
   FindRoot currenly supports only a single method for
   root finding: the "bisection method" (see [2]). The
   Mathematica implementation uses different methods (see [1]).
  SeeAlso:
  References:
   [1] The Mathematica Book "FindRoot"
   [2] Numerical Recipes in C. 2nd ed. sec. 9.1
       "Bracketing and Bisection"
*/

/FindRoot
{
 << >> begin
 /prec Set
 /xmax Set
 /xmin Set
 /f    Set

 xmin f xmax f gt {xmin xmax /xmin Set /xmax Set} if

 {
  /x xmax xmin add 2 div def
  x ==
  x f /y Set
  y prec gt
  {/xmax x def}
  {
   y prec neg lt
   {/xmin x def}
   {x exit }
   ifelse
  }
  ifelse
 } loop
end
} def




%---------------------------------------------------------------------------------- <- end of line (C84) is maximum width for LaTeX-include1
/*
BeginDocumentation

Name: MathematicaToSliIndex - Convert Mathematica-like indices to SLI indices

Synopsis: [array] mathematicaIndex MathematicaToSliIndex -> [array] sliIndex

Description:
   "MathematicaToSliIndex" converts Mathematica-like indices
   to SLI indices.
   For an array of size N, valid SLI indices are in the range 0..N-1
   while valid Matematica indices are in the range -N..-1, 1..N
   (negative indices indicating backward indexing from the end of the
   array).

   The given array is left untouched, solely its length is taken to
   correctly map negative Mathematica indices to the correct SLI
   indices.

   Alternatives: Function MathematicaToSliIndex_i if index is a
   number (example 1) and  MathematicaToSliIndex_a if index is an
   array (example 2) (both undocumented) -> behaviour and synopsis are
   the same.

Examples:
   [3 5 6 9 11] -2       MathematicaToSliIndex -> [3 5 6 9 11] 3
   [3 5 6 9 11] [ -2 2 ] MathematicaToSliIndex -> [3 5 6 9 11] [3 1]

Author: Markus Diesmann (?)

Remarks: Commented Ruediger Kupper

SeeAlso: SliToMathematicaIndex

*/

% array integer MathematicaToSliIndex
/MathematicaToSliIndex_i
{
 dup
 0 lt
 {exch size 3 -1 roll add}
 {1 sub}
 ifelse
} bind def

/MathematicaToSliIndex_a
{
 { MathematicaToSliIndex_i } Map
}
bind def


/MathematicaToSliIndex trie
 [/arraytype /integertype ] /MathematicaToSliIndex_i load addtotrie
 [/arraytype /arraytype ]   /MathematicaToSliIndex_a load addtotrie
def

%---------------------------------------------------------------------------------- <- end of line (C84) is maximum width for LaTeX-include1
/*
BeginDocumentation

Name: SliToMathematicaIndex - Convert SLI indices to Mathematica-like indices

Synopsis: sliIndex MathematicaToSliIndex -> mathematicaIndex

Description:
   "SliToMathematicaIndex" converts SLI indices to Mathematica-like
   indices.
   For an array of size N, valid SLI indices are in the range 0..N-1 while
   valid Matematica indices are in the range -N..-1, 1..N (negative
   indices indicating backward indexing from the end of the array).

   Note that this routine will always return positive indices.

Examples:
     3     SliToMathematicaIndex -> 4
   [ 3 1 ] SliToMathematicaIndex -> [ 4 2 ]


Author: Ruediger Kupper

FirstVersion: 11.3.2003

Remarks:
   Note the difference in the argument list compared to
   "MathematicaToSliIndex". Only one argument, the index(array)
   itself, is needed.

   The implementation is _most_ simple (add 1 to the index), but the
   Routine is supplied for symmetry reasons.

   Note that this routine will always return positive indices. Hence,
   the sequence
   [array] MathematicaToSliIndex SliToMathematicaIndex
   is NOT identity.

SeeAlso: MathematicaToSliIndex

*/

/SliToMathematicaIndex [/integertype]
{
  1 add
} bind def

/SliToMathematicaIndex [/arraytype]
{
  {SliToMathematicaIndex} Map
} bind def





/Part_a
{
  dup
  First
  3 -1 roll exch
  %
  % indexarray array First[indexarray]
  %
  dup /All eq
  {
   pop size [1] exch append Range
  }
  if
  %
  %
  dup type /arraytype eq
  {
   {
    1 index exch
    MathematicaToSliIndex_i get
    %
    % indexarray array subarray
    %
   2 index Rest
   empty {pop} {Part} ifelse

   } Map
   %
   % indexarray array subarray
   %
   3 1 roll pop pop
  }
  {
    MathematicaToSliIndex_i get
    exch Rest
    empty {pop} {Part} ifelse
  }
  ifelse

} def

/* BeginDocumentation
  Name: Part - returns a sub-array of an array
  Synopsis: array1 array2 Part -> array3
  Description:
   Part returns a sub-array of array1 specified by
   array2. This function is an implementation of
   Mathematica's Part function. It can also be used
   to rearrange or copy parts of array1. Note,
   Mathematica-style functions in SLI use Mathematica
   index notation.
  Parameters:
   array1 is an arbitrarily shaped array. In particular
   it does not need to be rectangular.

   array2 is an array [i,j, ...] where the i,j specify the
   selected elements on each level. Any i,j can itself be
   an array [i1,i2,....] specifying a list of elements on
   that level. When i is the literal /All, all elements on
   the corresponding level are returned. The first element
   on each level has index 1. Indices can also be specified
   counting from the end of the array, in this case the last
   element has index -1. Positive and neative indices can
   arbitrarily be intermixed.

   Alternatives: Function Part_a (undocumented) -> behaviour and
   synopsis are the same.

  Examples:

    5 /mul 3 /eq 15

   [ [3 5 6 9] [11 4 7 2] [-9 1 8 10] ]  [ [1 3] [2 3] ] Part
    [[5 6] [1 8]]  eq

   [ [3 [-12 -19] 6 9] [11 4 7 2] [-9 1 8 10] ]  [ 1 2 2] Part
     -19  eq

   [3 4 5 6 7] [-2] Part
     6 eq

   [3 [-9 -12] 5 6 7] [2] Part   -->     [-9 -12]

   [3 [-9 -12] 5 6 7] [2 2] Part -->     -12

   [3 [-9 -12] 5 6 7] [[2 3]] Part    [[-9 -12] 5]   eq

   [3 [-9 -12] 5 6 7] [[2 3 2]] Part  [[-9 -12] 5 [-9 -12]] eq

   [ [3 5 6 9] [11 4 7 2] [-9 1 8 10] ]  [ 1 []  ] Part [] eq

   [ [3 5 6 9] [11 4 7 2] [-9 1 8 10] ]  [ [] 1 ] Part  [] eq

   [3 [5 -12] 6 9]  [ [ 2 ] ] Part [[5 -12]] eq

   [3 [5 -12] 6 9]  [ [ 2 ] 2] Part  [-12] eq

   [ [3 5 6 9] [11 4 7 2] [-9 1 8 10] ]  [ /All [3 2]  ] Part
     [[6 5] [7 4] [8 1]] eq

  Bugs:
  Author: Diesmann
  FirstVersion: 29.9.1999

  Remarks:
   Literal /All plays the role of the index specifier ':'
   in Matlab when used without arguments. Note, that
   Matlab in addition provides specifier 'end'.
   This is not necessary in the formalism of Mathematica
   because indices counting from the end of the array can be
   expressed by negative values.
  SeeAlso: MathematicaToSliIndex
  References:
   [1] The Mathematica Book V4.0 "Part"
*/
/Part trie
 [/arraytype /arraytype ]
  /Part_a load
 addtotrie
def


/Transpose_ /Transpose load def
/Transpose trie
[/arraytype ] /Transpose_ load addtotrie
def


%% array n  Take - take first n elements of array
%% array -n Take - take last n elements of array
/Take_a_i
{
  dup 0 gt
  {
    0 exch_  getinterval_a
  }
  {
    dup neg
    getinterval_a
  } ifelse

} bind def

/switchbegin mark def

/Take_a_a
{
  dup TensorRank
  1 eq
  {
   size
   switchbegin
   1 index 1 eq
   {
     pop arrayload pop
     MathematicaToSliIndex
     get
   } case

   1 index 2 eq
   {
     pop arrayload pop

%
%    a i j
     rollu                         % j a i
     MathematicaToSliIndex         % j a im
     rollu                         % im j a
     exch                          % im a j
     MathematicaToSliIndex         % im a jm

     rolld                         % a jm im
     dup                           % a jm im im
     rollu                         % a im jm im
     sub 1 add                     % a im (jm - im +1)

     getinterval
   } case

   1 index 3 eq
   {
     pop
     dup rollu Most MathematicaToSliIndex rolld Last append
     Range
     {
       1 index
       exch
       get
     } Map
     exch pop
   } case

   {
      pop
      /Take /IllegalSequenceSpecification raiseerror
   }
  switchdefault
 }
 {
   %% array sarr
   {Range} Map
   Part
 } ifelse
} bind def

/*BeginDocumentation
Name: Take - extract element sequences from an array
Synopsis:
 array  n Take                  return the first n elements
 array -n Take                  return the last n elements
 array [n1 n2] Take             return elements n1 through n2
 array [n1 n2 s] Take           return elements n1 through n2 in steps of s
 array [[seq1]...[seqn]] Take   return a nested list in which elements
                                specified by seqi are taken at level i in list.
Examples:
 [4 9 -7 3 2 11] 2 Take
  -> [4 9]
 [4 9 -7 3 2 11] -2 Take
  -> [2 11]
 [1 2 3 4 5] [-2] Take
  -> 4
 [1 2 3 4 5] [1 -2] Take
  -> [1 2 3 4]
 [1 2 3 4 5] [1 -2 2] Take
  -> [1 3]
 [1 2 3 4 5] [1 -1 2] Take
  -> [1 3 5]

Author: Diesmann
Bugs:
 The scheme for a list of sequences is not fully consistent with Mathematica.
 See Drop for a more advanced implementation.
References:
   [1] The Mathematica Book V4.0 "Take"
SeeAlso: Drop, Part, MathematicaToSliIndex, getinterval, get
*/

/Take trie
[/arraytype /integertype] /Take_a_i load addtotrie
[/arraytype /arraytype]   /Take_a_a load addtotrie
def



/*BeginDocumentation
Name: Drop - remove element sequences from an array
Synopsis:
 array  n Drop                  remove the first n elements
 array -n Drop                  remove the last n elements
 array [n] Drop                 remove the nth element
 array [n1 n2] Drop             remove elements n1 through n2
 array [n1 n2 s] Drop           remove elements n1 through n2 in steps of s
 array {[seq1]...[seqn]} Drop   return a nested list in which elements
                                specified by seqi are removed at level i in list.
Examples:
 [4 9 -7 3 2 11] 2 Drop
  -> [-7 3 2 11]
 [4 9 -7 3 2 11] -2 Drop
  -> [4 9 -7 3]
 [1 2 3 4 5] [-2] Drop
  -> [1 2 3 5]
 [1 2 3 4 5] [1 -2] Drop
  -> [5]
 [1 2 3 4 5] [1 -2 2] Drop
  -> [2 4 5]
 [1 2 3 4 5] [1 -1 2] Drop
  -> [2 4]

 [[-9 -12] [6 7]] {[2] [1]} Drop
  -> [[-12]]

Author: Diesmann
FirstVersion: 2007.11.28
Bugs:
 The list of sequences is represented by a procedure. This has delayed
 evaluation which may cause undesired effects. Should be replaced in a
 future versionby a new container type for parameter lists of undefined
 length. Candidate delimiters are <...> with cva as the only access method.
 Just using [...] as the container is ambiguous.
References:
   [1] The Mathematica Book V4.0 "Take"
SeeAlso: Take, Part, MathematicaToSliIndex, erase
*/

/Drop [/arraytype /integertype]
{
 Drop_sequence_a_i_
}
def

/Drop [/arraytype /arraytype]
{
 % a [i]
 Drop_sequence_a_a_
}
def

/Drop_preposti_
{
 % a [i]  -> pre_a post_a ai

 2 copy            % a [i] a [i]

 Take              % a [i] ai
 rollu             % ai a [i]
 First             % ai a i


 dup               % a i i
 1 sub
 [1] exch append   % a i [1 i-1]
 2 index           % a i [1 i-1] a
 exch Take         % a i pre_a
 rollu             % pre_a a i
 1 add             % pre_a a i+1
 1 index length    % pre_a a i+1 l
 2 arraystore      % pre_a a [i+1 l]
 Take              % pre_a post_a

 rolld             % pre_a post_a ai
}
def



/Drop [/arraytype /proceduretype]
{
 /mark exch  exec counttomark arraystore exch pop
 Drop_sequences_
}
def


/Drop_sequence_ [/arraytype /integertype]
{
 Drop_sequence_a_i_
}
def

/Drop_sequence_ [/arraytype /arraytype]
{
 Drop_sequence_a_a_
}
def


/Drop_sequence_a_i_
{
 % 1 2 | 3 4 5:  2 Drop == -length +  2 = -3 Take
 %              -3 Drop ==  length + -3 =  2 Take
 dup Sign neg   % a n -s
 2 index length % a n -s l
 mul            % a n l
 add            % a n
 Take
}
def

% array seq -> array explicit_range
/MathematicaSequenceToExplicitRange_a_a_
{
 size  % a s
 dup 1 eq
 {
  pop MathematicaToSliIndex
 }
 {
  dup 2 eq
  {
   pop MathematicaToSliIndex Range
  }
  {
   pop dup rollu Most MathematicaToSliIndex rolld Last append Range
  }
  ifelse
 }
 ifelse
}
def

/Drop_sequence_a_a_
{                       % a s
 MathematicaSequenceToExplicitRange_a_a_  % a s(explicit and <-sorted)
 {                      % a si i
  sub                   % a si(corrected for previous erasions)
  1 erase
 } forallindexed
}
def

/Drop_sequences_
{
           % a p
 empty
 {
  pop
 }
 {                  % a p
  exch              % p a
  1 index           % p a p
  First             % p a s
  Drop_sequence_    % p as
  exch              % as p
  Rest              % as pr
  exch              % pr ar
  {                 % pr ai
   1 index          % pr ai pr
   Drop_sequences_  % ar
  } Map             % pr aar
  exch              % aar pr
  pop               % aar
 }
 ifelse
}
def




/* BeginDocumentation
Name: NestList - gives a list of the results of applying f to x 0 through n times.
Synopsis: x f n NestList ->  [x, x f,  x f f,..., x f1 ... fn]
Parameters: x - any object to which f can be applied
            f - an executable object.
Description: NestList repeatedly applies f to the supplied argument and returns
             the result als well as all intermediate results in a list.
             Note that f must expect and return exactly one argument.
Examples:   1 {2 mul} 3 NestList -> [1 2 4 8]
SeeAlso: Map, forall
*/
%% x proc n NetList -> [x proc, x proc proc, x proc1 ... procn]
/NestList trie
[/anytype /anytype /integertype]
{
  [] 1 index 1 add reserve % reserve array-space for n+1 elements
  4 -1 roll append         % add initial value to the array
  exch
  %% proc [x] n            % iterate over n
  {
    dup Last               % extract the last lement from the array
    2 index exec           % apply function and
    append                 % append the result to the array
  } repeat
  exch pop                 % remove spare function object
} bind addtotrie def


/*BeginDocumentation
Name: Nest - apply a function n times
Synopsis: x f n Nest -> f( ...n times... f(f(x)) ...)
Examples:0.2 {dup 1 exch sub mul 3.3 mul} 10 Nest
Author: Diesmann
FirstVersion: 9.2.01
Remarks:Nest is a restricted variant of repeat.
It is implemented to demonstrate the use of repeat as a
functional operator and for compatibility with Mathematica.
SeeAlso: repeat, forall, NestList, Fold
*/
%% x f n Nest
/Nest trie
[/anytype /proceduretype /integertype]
{
 exch repeat
} bind addtotrie def



/*BeginDocumentation
Name: Fold - result of repeatedly applying a function with two arguments
Synopsis: x [a b c ...] f Select -> f( ...n times... f(f(f(x,a),b),c) ...)
Examples: 1 [2 x] Range {mul} Fold
         computes faculty of integer x
Author: Diesmann
FirstVersion: 9.2.01
Remarks:Fold is a restricted variant of forall.
It is implemented to demonstrate the use of forall as a
functional operator and for compatibility with Mathematica.
SeeAlso: forall, repeat, FoldList, Nest
*/
%% x a p
/Fold [/anytype /arraytype /proceduretype] /forall load def
/Fold [/anytype /intvectortype /proceduretype] /forall load def
/Fold [/anytype /doublevectortype /proceduretype] /forall load def




/*BeginDocumentation
Name: FoldList - repeatedly apply a function with two parameters
Synopsis: x [a b c ...] f FoldList -> [f(x,a) f(f(x,a),b) ...]
Examples: 0 [1 2 3 4] {add} FoldList gives the cumulative sums of the list.
         0 [1 2 3 4] {add} FoldList -> [0 1 3 6 10]
Remarks: This function is Mathematica compatible.
SeeAlso: NestList, Fold, Map, forall
*/
%% x array f FoldList
/FoldList trie
[/anytype /arraytype /anytype]
{
  exch
  % x f array
  []
  % x f array []
  4 -1 roll append
  % f array [x]
  exch
  % f [x] array
  {
    1 index Last
    % f [x] ai x
    exch
    % x ai
    3 index exec
    % f [x] f(x,ai)
    append
  } forall
  exch pop
} bind addtotrie def



/*BeginDocumentation
Name: Select - reduces an array to elements which fulfill a criterion
Synopsis: array proc Select -> array
Examples:[4 -2 0.3 -1.7 -3 0 7] {0 lt} Select -> [-2 -1.7 -3]
         [4 -2 0.3 -1.7 -3 0 7] {0 gt} Select -> [ 4  0.3  7]
Remarks: Mathematica compatible
Author: Diesmann
FirstVersion: 9.2.01
SeeAlso: Take, Split
*/
%% a f Select
/Select trie
[/arraytype /proceduretype]
{
 exch
 container
 rollu exch
 {dup} exch join { {append } {pop} ifelse } join
 forall
}  bind addtotrie def



/*BeginDocumentation
Name: Split - splits array into subarrays of sequences of identical elements
Synopsis: array  Split     -> [array1 ... arrayn]
          array proc Split -> [array1 ... arrayn]
Examples:
         [1 1 1 2 2 3 3 3 3 4 4 4] Split -> [[1 1 1] [2 2] [3 3 3 3] [4 4 4]]
         [1.1 1.3 1.7 2.1 2.3 2.7] {floor exch floor eq} Split ->
             [[1.1 1.3 1.7] [2.1 2.3 2.7]]
         [1] Split -> [[1]]
         [] Split  -> []
Remarks: Mathematica compatible
Author: Diesmann
FirstVersion: 13.2.01
SeeAlso: Take, Select
*/
/Split_
{
 exch
 container
 exch
 empty
 {
  rollu pop pop
 }
 {
  dup [[1]] Part exch
  2 1 Partition

  {                    % 1. part of forall's argument
   dup arrayload pop
  }

  5 -1 roll            % 2. part, the criterion
  join

  {                    % 3. part
   {1 get append}
   {rollu append exch [[2]] Part }
   ifelse
  }
  join

  forall

  append
 } ifelse

} bind def

/Split trie
 [/arraytype /proceduretype] /Split_ load addtotrie
 [/arraytype ] { {eq} } /Split_ load  join  addtotrie
def




/*BeginDocumentation
Name: MergeLists - merges sorted lists
Synopsis: array array      MergeLists  -> array
          array array proc MergeLists  -> array
Examples:
  [1 3 5] [2 7] MergeLists -> [1 2 3 5 7]
  [[-9 1] [1 3] [4 5]]  [[3 2] [0 7]] {exch 1 get exch 1 get lt} MergeLists ->
         [[-9 1] [3 2] [1 3] [4 5] [0 7]]
Description:
 MergeLists is unlike Union which removes repeated elements and does
 not require the arguments to be sorted. However, the result of
 Union is also sorted. MergeLists does not appear in Mathematica V4.0,
 Union does.
Author: Diesmann
FirstVersion: 8.5.01
References:
   [1] The Mathematica Book V4.0 "Union"
SeeAlso: Select, Split
*/
/MergeLists_
{
 % l1 l2 crit

 {% part 1 of loop procedure

  % loop invariant is:
  %  [result] [remainder l1] [remainder l2]

  empty      {pop join exit} if
  exch empty {pop join exit} { exch } ifelse

  % get first element of l1 and l2
  %
  1 pick First
  1 pick First

  % [] l1 l2 e1 e2
 }

 exch % l1 l2 p1 crit

 {% part 2 of loop procedure
  { % e1 < e2
    % [] l1 l2

   rollu
   dup First
   exch rollu
   append

   rollu
   Rest
   exch

  }
  { % e1 >= e2
    % [] l1 l2

   rolld exch
   dup First
   rolld exch
   append

   rollu
   Rest

  }
  ifelse
 }
            % l1 l2 p1 crit p2
 join join  % l1 l2 p

 exch container rolld
 4 2 roll
 rolld

%  container rollu  % [] l1 l2 p

 loop

} def


/MergeLists trie
 [/arraytype /arraytype /proceduretype] /MergeLists_ load addtotrie
 [/arraytype /arraytype ] { {lt} } /MergeLists_ load join  addtotrie
def




/* BeginDocumentation
  Name: Times - represents/computes product of terms
  Synopsis: array Times -> double
                        -> integer
  Description:
   Times represents or computes the product of its
   arguments v1,-,vn. The arguments are supplied
   by an array [v1, -,vn]. The product of an empty
   argument list is defined to be unity.
   Times is an implementation of Mathematica's Times [1].
  Parameters:
  Examples:
%
         [4 3 2 5 6] Times --> 720
         [] Times          --> 1

  Bugs:
   not yet protected by trie
  Author: Diesmann
  FirstVersion: 31.5.2000
  Remarks:
  SeeAlso: Plus
  References:
   [1] The Mathematica Book "Times"
*/
/Times { 1 exch { mul } forall } bind def


/* BeginDocumentation
  Name: Plus - represents/computes sum of terms
  Synopsis: array Plus -> double
                       -> integer
  Description:
   Plus represents or computes the sum of its
   arguments v1,-,vn. The arguments are supplied
   by an array [v1, -,vn]. The sum of an empty
   argument list is defined to be zero.
   Plus is an implementation of Mathematica's Plus [1].
  Parameters:
  Examples:

         [4 3 2 5 6] Plus -->  20
         [ ] Plus         -->   0

  Bugs:
   not yet protected by trie
  Author: Diesmann
  FirstVersion: 31.5.2000
  Remarks:
  SeeAlso: Times
  References:
   [1] The Mathematica Book "Plus"
*/
/Plus { 0 exch { add } forall } bind def

% v1 vn n astore
/astore
{
 length arraystore
 (astore is obsolete:\n)
 (In contrast to PostScript SLI arrays are dynamic\n)
 (use arraystore instead.) join join M_INFO message
} def


/aload
{
 arrayload array
 (aload is obsolete:\n)
 (In contrast to PostScript SLI arrays are dynamic\n)
 (use arrayload instead.) join join M_INFO message
} def

/* BeginDocumentation
  Name: Dot - product of vectors, matrices, and tensors
  Synopsis: array array Dot -> array
                              -> double
                              -> integer
  Description:

    A B Dot contracts the last index in A with the first
    index in B. Indices in mathematical notation, leftmost
    index describes first level objects. For peole used to
    strict (row,column) notation as in Matlab [2] effects
    of this generalized product may be surprising (see
    examples (1) to (3).
    Dot is an implementation of Mathematica's Dot [1].
  Parameters:
  Examples:

 (1)
   [ 4 3 7 ] [ 2 5 8] Dot ==79

 (2)
   [ 4 3 7 ] [ [ 2] [ 5 ] [ 8 ] ] Dot ==  [79]

 (3)
   [ [ 4 ] [ 3 ] [ 7 ] ] [  2  5   8  ] Dot ==  [8 6 14]
      Error: /DimensionMismatch in Dup
 (4)
   [ [ 5 3 2 ] [ 5 4 1 ] ] [ [ 2 ] [ 3 ] [ 9 ] ] Dot == [[37] [31]]

 (5)
   [ [ 5 3 2 ] [ 5 4 1 ] ] [ 2  3 9  ] Dot ==   [37 31]

 (6)
   [ 7 8 ] [ [ 5 3 2 ] [ 5 4 1 ] ]  Dot == [75 53 22]

 (7)
   [  [ 5 3 ]  [ 1 2 ] [ 5 4 ] ]
   [ [ [ 2 1 ]  [ 5 3 ] [ 3  4 ] [ 7 5 ]] [ [ 3 1 ]  [ 7 4] [8 9] [1 8] ] ]
    Dot ==
   [ [ [19 8] [46 27] [39 47] [38 49] ]
     [ [8 3]  [19 11] [19 22] [9 21]  ]
     [ [22 9] [53 31] [47 56] [39 57] ]
    ]

  Bugs: Bad performace: TensorRank should be rewritten in C++
   not yet protected by trie
  Author: Diesmann
  FirstVersion: 31.5.2000
  Remarks:
  SeeAlso: Times, Plus, OuterProduct
  References:
   [1] The Mathematica Book "Dot"
   [2] The MathWorks, Matlab User's Guide
*/
/Dot  % A B Dot
{
 dup Dimensions First  2 index Dimensions  Last neq
 {/Dot /DimensionMismatch raiseerror } if
 exch
 dup TensorRank 1 eq  % of A
 {
  exch_ dup_ TensorRank 1 eq  % of B
  {
    Dot1D
  }
  {
   Transpose_   % of B
   {1 index exch_ Dot } Map_ exch_ pop_
  }
  ifelse_
 }
 { % B A
  { 1 index Dot } Map_ exch_ pop_
 }
 ifelse_
} bind def

/* BeginDocumentation
   Name: Dot1D - Compute the inner product of two vectors.
   Synopsis: array array Dot1D -> num
   Description: 
   Dot1D expects two one dimensional arrays or vectors and computes the
   inner product of the two arguments.
   Dot1D works equally well for arrays, doublevectors and intvectors.

   Example:
    <. 1 2 3 .> <. 1 2 3 .> Dot1D -> 14
   SeeAlso: Dot, OuterProduct
   Author: Marc-Oliver Gewaltig
   FirstVersion: Dec 18 2012
*/
/Dot1D
{
  mul
  0 exch
  { add } forall
} def


/* BeginDocumentation
  Name: OuterProduct - outer product
  Synopsis: array array OuterProduct -> array

  Description:
   A B OuterProduct computes the outer product of A
   and B by forming all possible combinations of the
   lowest level elements (rightmost indices) in both
   lists.
   OuterProduct is compatible to Mathematica's
   Outer[Times,A,B] [1]
  Parameters:
  Examples:

    [3 4 5] [6 7 8 9] OuterProduct ->
       [
        [18 21 24 27]
        [24 28 32 36]
        [30 35 40 45]
       ]

  Bugs:
   not yet protected by trie
  Author: Marc-Oliver Gewaltig, Diesmann
  FirstVersion: 31.5.2000, rewritten Dec 18 2012
  
  Remarks:
  SeeAlso: Times, Dot
  References:
   [1] The Mathematica Book "Outer"
*/
/OuterProduct
{
 exch
 { 1 index mul } Map 
 exch pop
} bind def


/*BeginDocumentation
Name: LayoutArray - build a multidimensional array
Synopsis: [d1 d2 ...] val LayoutArray -> [...]
Parameters: [d1 d2 ...] - Array with dimensions.
            val         - initialisation value for array entries
Description:
  LayoutArray generates a multi-dimensional array which is
  initialised to val.

Examples:
   [5] 1 LayoutArray -> [1 1 1 1 1]
   [2 3] 1.0 LayoutArray -> [ [1.0 1.0 1.0] [1.0 1.0 1.0]]

Author: Marc-oliver Gewaltig
FirstVersion: 20.6.02
SeeAlso: ArrayShape, Range, Table, Dimensions
*/
/LayoutArray
{
  << >> begin
  /val exch def
  size /n_dim Set
 /dim  Set
  n_dim 1 eq
  {
    [ dim 0 get {val} repeat ]
  }
  {
    dim 0 get array
    { ;
      dim Rest val LayoutArray
    } Map
  } ifelse
 end
} bind def



/*BeginDocumentation
Name: ArrayShape - reduce a multidimensional array to a desired shape
Synopsis: array1 [d1 d2 ...] LayoutArray -> array2
Parameters:
 array1      - array to operate on
 [d1 d2 ...] - array with specification of dimensions, where
               di is an integer or /All
 array2      - reduced array1
Description:
 The function is useful if an operation needs to be performed on an
 array of data which contains rows with insufficient data and rows
 with trailing superfluous entries.

 The algorithm is as follows:
  - if dim empty return []
  - take first d1 elements of a if available
    return [] otherwise
  - forall these elements
     - do nothing if [d2 ...dn] empty
     - otherwise apply [d2 ...dn] and remove
       if result is []

Examples:
 [ [ 3 6 9] 100 [ 8 2 3 7 1] ] [2] ArrayShape
  -> [[3 6 9] 100]
 [ [ 3 6 9] [ 8 2 3 7 1] ] [/All 2] ArrayShape
  -> [[3 6] [8 2]]
 [ [ 3 6 9] [ 8 2 3 7 1] ] [/All 3] ArrayShape
  -> [[3 6 9] [8 2 3]]
 [ [ 3 6 9] [ 8 2 3 7 1] ] [/All 4] ArrayShape
  -> [[8 2 3 7]]

 [[[ 6 2 3] [-7 4 5] ] [[8 3 2] [2 -9 -5] 3 7 1]] [/All 2 3] ArrayShape
  -> [[[6 2 3] [-7 4 5]] [[8 3 2] [2 -9 -5]]]

Remarks:
 The Mathematica function ArrayDepth (not implemented) tests whether its
 argument has the required dimensions. This is unlike the function Dimensions
 which assumes that all elements of the array at a given level have identical
 shape and, therefore, inspects only the first element at each level.
Author: Diesmann
FirstVersion: 2007.11.28
SeeAlso: LayoutArray, Part, Table, Dimensions
*/

/ArrayShape
{
 empty  % array dims
 {
  exch pop  % return empty array
 }
 {
  dup Rest rollu  % array dims
  First           % dims_remain array dims
                  % dims_remain array dim

  dup /All eq {pop dup length} if  % dims_remain array dim
  dup 2 index length  % dims_remain array dim dim length

  leq
  { % array has sufficient length
   Take                      % dims_remain array dim
   1 index                   % dims_remain array
   length                    % dims_remain array dims_remain
   0 eq                      % dims_remain array length
   {                         % dims_remain array
    exch pop                 % remove dims_remain
   }
   {
    container        % dims_remain array
    exch             % dims_remain array []
    {
     2 index         % dims_remain result_array array_element
     ArrayShape      % dims_remain result_array array_element dims_remain
     empty           % dims_remain result_array array_element
     {pop}
     {append}
     ifelse
    }
    forall
    exch pop         % dims_remain result_array
   }
   ifelse
  }
  {
   pop       % dims_remain array dim
   container % dims_remain array
   rollu     % dims_remain array []
   pop       % [] dims_remain array
   pop       % [] dims_remain
  }
  ifelse
 }
 ifelse
} def



/* BeginDocumentation
Name: add - add two numbers or vectors
Synopsis: n1 n2  add -> n3
          a1 a2  add -> a3
Description: add can be used to add numbers and arrays.

  If applied to numbers, add returns the sum of the numbers. If one
  of the arguments is a double, the result is also a double.

  Applied to arrays, add perfoms a per-component addition of the two
  arrays. The components must be numbers, however, integer and double
  values may be mixed.

  Note that the two arrays must be of the same size.


Examples:
           1 2   add -> 3
           1.0 2 add -> 3.0
           [1 2] [3 4] add -> [4 6]
           1 [3 4] add -> [4 5]
Author: M-O Gewaltig
SeeAlso: Dot, Plus, Times
*/


/add_a_a
{
  2 arraystore
  { add } MapThread
}  bind def

/add_i_a
{
  {
    1 index add
  } Map
  exch pop
} bind def

/add_a_i
{
  exch_ add_i_a
} bind def

/add [/arraytype /arraytype] /add_a_a load def
/add [/doubletype /arraytype] /add_i_a load def
/add [/arraytype /doubletype] /add_a_i load def
/add [/integertype /arraytype] /add_i_a load def
/add [/arraytype /integertype] /add_a_i load def

/*BeginDocumentation
Name: sub - subtract two numbers or vectors

Synopsis: n1 n2  sub -> n3
          a1 a2  sub -> a3

Description: sub can be used to subtract numbers and arrays.

  If applied to numbers, sub returns the difference of the numbers. If one
  of the arguments is a double, the result is also a double.

  Applied to arrays, sub perfoms a per-component subtraction of the two
  arrays. The components must be numbers, however, integer and double
  values may be mixed.

  Note that the two arrays must be of the same size.


Examples:
           5 2   sub -> 3
           5.0 2 sub -> 3.0
           [5 7] [3 4] sub -> [2 3]
           [3 4] 1 sub -> [2 3]

Author: docu by Sirko Straube (adopted from add)

SeeAlso: add, mul, div
*/

/sub_a_a
{
  2 arraystore
  { sub } MapThread
}  bind def

/sub_i_a
{
  {
    1 index exch_ sub
  } Map
  exch pop
} bind def

/sub_a_i
{
  exch_
  {
    1 index sub
  } Map
  exch_ pop
} bind def

/sub [/arraytype /arraytype] /sub_a_a load def
/sub [/doubletype /arraytype] /sub_i_a load def
/sub [/arraytype /doubletype] /sub_a_i load def
/sub [/integertype /arraytype] /sub_i_a load def
/sub [/arraytype /integertype] /sub_a_i load def

/*BeginDocumentation
Name: mul - multiply two numbers or vectors (point-wise)

Synopsis: int int mul -> int
int double mul -> double
array int/double mul -> array

Examples: 3 4 mul -> 12
3.33 3 mul -> 9.99
[1 2.2 3] 4 mul -> [4 8.8 12]

Author: docu by Sirko Straube

SeeAlso: add, sub, div, Dot
*/
/mul_a_a
{
  2 arraystore
  { mul } MapThread
}  bind def

/mul_i_a
{
  {
    1 index mul
  } Map
  exch pop
} bind def

/mul_a_i
{
  exch_ mul_i_a
} bind def

/mul [/arraytype /arraytype] /mul_a_a load def
/mul [/doubletype /arraytype] /mul_i_a load def
/mul [/arraytype /doubletype] /mul_a_i load def
/mul [/integertype /arraytype] /mul_i_a load def
/mul [/arraytype /integertype] /mul_a_i load def

/*BeginDocumentation
Name: div - divide two numbers or vectors (point-wise)

Synopsis: int int div -> int
int double div -> double
array int/double div -> array

Examples: 9 2 div -> 4
9 3.3 div -> 2.727273
[10 11.5 12] 4 div -> [2 2.875 3]

Author: docu by Sirko Straube

SeeAlso: add, sub, mul, Dot
*/
/div_a_a
{
  2 arraystore
  { div } MapThread
}  bind def

/div_i_a
{
  {
    1 index div
  } Map
  exch pop
} bind def

/div_a_i
{
  exch_ div_i_a
} bind def

/div [/arraytype /arraytype] /div_a_a load def
/div [/doubletype /arraytype] /div_i_a load def
/div [/arraytype /doubletype] /div_a_i load def
/div [/integertype /arraytype] /div_i_a load def
/div [/arraytype /integertype] /div_a_i load def

/*BeginDocumentation
Name: ArrayQ - returns true if top object is an array
SeeAlso: NumberQ, LiteralQ
*/

/ArrayQ trie [/arraytype] true  addtotrie
             [/anytype]   false addtotrie
def
/*BeginDocumentation
Name: LiteralQ - returns true if top object is a literal
SeeAlso: NumberQ, ArrayQ, StringQ
*/
/LiteralQ trie [/literaltype] true  addtotrie
               [/anytype]   false   addtotrie
def

/*BeginDocumentation
Name: NumberQ - returns true if top object is a number (int or double)
Synopsis: int    NumberQ -> true
          double NumberQ -> true
          any    NumberQ -> false
SeeAlso: IntegerQ, DoubleQ, LiteralQ, ArrayQ, StringQ
*/

/NumberQ trie
 [/integertype] true  addtotrie
 [/doubletype]  true  addtotrie
 [/anytype]     false addtotrie
def

/*BeginDocumentation
Name: IntegerQ - returns true if top object is an integer (int)
Synopsis: int    IntegerQ -> true
          any    IntegerQ -> false
SeeAlso: NumberQ, DoubleQ, LiteralQ, ArrayQ, StringQ
*/
/IntegerQ trie
 [/integertype] true  addtotrie
 [/anytype]     false addtotrie
def

/*BeginDocumentation
Name: DoubleQ - returns true if top object is a double
Synopsis: double DoubleQ -> true
          any    DoubleQ -> false
SeeAlso: IntegerQ, DoubleQ, FiniteQ, LiteralQ, ArrayQ, StringQ
*/
/DoubleQ trie
 [/doubletype] true  addtotrie
 [/anytype]    false addtotrie
def

/*BeginDocumentation
Name: FiniteQ - returns true if top object is finite number
Synopsis: double FiniteQ -> true/false
          int    FiniteQ -> true
Description:
For numeric arguments, returns true if the value is finite
(neither +inf, -inf, or nan). Integers are always finite.
It is an error to call this function on anything except numbers.
SeeAlso: IntegerQ, DoubleQ, LiteralQ, ArrayQ, StringQ
*/
/FiniteQ trie
 [/doubletype]  /finite_q_d load addtotrie
 [/integertype] true       addtotrie
 [/anytype]     { /FiniteQ /IllegalArgument raiseerror } addtotrie
def


/*BeginDocumentation
Name: StringQ - returns true if top object is a string
Synposis: string StringQ -> true
          any    StringQ -> false
SeeAlso: NumberQ, LiteralQ, ArrayQ
*/
/StringQ trie [/stringtype] true  addtotrie
       	      [/anytype]    false addtotrie
def

/*BeginDocumentation
Name: DictQ - returns true if top object is a dictionary
Synposis: dictionary DictQ -> true
          any        DictQ -> false
SeeAlso: NumberQ, LiteralQ, ArrayQ
*/
/DictQ trie 
  [/dictionarytype] true addtotrie
  [/anytype]        false addtotrie
def

/*BeginDocumentation
Name: MemberQ - checks if array contains a specific element
Synopsis:
array any MemberQ -> true
                  -> false
Examples:
[3 8 2 9 -1] 2 MemberQ --> true
[3 8 9 -1]   2 MemberQ --> false
Author: Diesmann
FirstVersion: 10.5.2001
Remarks: The Mathematica implementation is much more general
References:
   [1] The Mathematica Book "MemberQ"
SeeAlso: LiteralQ, NumberQ, ArrayQ, MatrixQ, HasDifferentMemberQ
*/
/MemberQ
{
 << >> begin
  /member Set
  /array Set

 false
 array {/member load eq {pop true exit} if} forall
 end
} def

/*BeginDocumentation
Name: HasDifferentMemberQ - checks if array contains different element(s)
Synopsis:
array any HasDifferentMemberQ -> true
                          -> false
Examples:
[3 8 2 9 -1] 2 HasDifferentMemberQ --> true
[2 2 2]      2 HasDifferentMemberQ --> false
Author: Plesser, based on MemberQ
FirstVersion: 20 Sept 2010
SeeAlso: LiteralQ, NumberQ, ArrayQ, MatrixQ, MemberQ
*/
/HasDifferentMemberQ
{
 << >> begin
  /member Set
  /array Set

 false
 array {/member load neq {pop true exit} if} forall
 end
} def

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

/* BeginDocumentation
   Name: SubsetQ - Test if one dictinary is a subset of another

   Synopsis:
   dict1 dict2 SubsetQ -> bool

   Parameters:
   dict1 - dictionary
   dict2 - dictionary

   Description:
   The functions returns true, if all entries of dict2 are present in dict1
   with the same values.

   Examples:
   << /a 1 /b 2 /c 2 >> << /c 2 >> SubsetQ -> true
*/

/SubsetQ
[/dictionarytype /dictionarytype]
{
  << >> begin
  cva 2 Partition
  /properties Set
  /object Set

  true
  properties
  {
    arrayload ;
    /val Set
    cvlit /key Set
    object dup key known
    {
      key get
      val eq and
    }
    {
     pop pop false exit
    } ifelse
  } forall
  end
} bind def

/*BeginDocumentation
Name: ToMathematicaExpression - converts SLI data to Mathematica input
Synopsis:
any ToMathematicaExpression -> string

Description:
An error is raised for unsupported SLI data types. In particular,
the function also converts heterogeneous arrays and dictionaries.

Examples:

[3.4 (hello) [2 3] ] ToMathematicaExpression -->
     ({ImportString["3.4","List"][[1]], "hello", {2, 3}})
<< /i 6 /s (hello) >> ToMathematicaExpression -->
     ({i -> 6, s -> "hello"})

Author: Diesmann
Remarks:
The conversion of doubles does not yet guarantee the existence
of the decimal point and an appropriate number of digits.
References:
   [1] The Mathematica Book
*/
/ToMathematicaExpression
{
 dup                           % we need type and value
 <<
   /arraytype
     {
      ({) exch empty not
      {
       {                        % we at least one element to operate on
        dup Rest exch           % save the reminder of the array
        First                   % get the next element to operate on
        ToMathematicaExpression % convert to Mathematica input format
        rolld exch join exch    % append to converted part
        empty
        {exit} if               % last element does not need a separator
        (, )                    % separator
        rolld exch join exch    % append to converted part
       } loop
      } if
      pop                       % the empty array is still on the stack
      (}) join
     }
   /dictionarytype
     {
      cva 2 Partition           % create a list of tuples
      ({) exch empty not
      {
       {                        % we at least one element to operate on
        dup Rest exch           % save the reminder of the array
        First                   % get the next element to operate on

        dup 0 get cvs           % convert the name of the key
        ( -> ) join exch        % append the rule symbol
        1 get
        ToMathematicaExpression % convert to Mathematica input format
        join                    % append value in Mathematica input format

        rolld exch join exch    % append to converted part
        empty
        {exit} if               % last element does not need a separator
        (, )                    % separator
        rolld exch join exch    % append to converted part
       } loop
      } if
      pop                       % the empty array is still on the stack
      (}) join
     }
   /stringtype
     { (") exch join (") join }
   /booltype
     { {(True)} {(False)} ifelse }
   /integertype
     { cvs }
   /doubletype
     { cvs (ImportString[") exch join (","List"][[1]]) join }
   /literaltype
     { cvs }
 >>
 dup rolld type known not       % argument not in the list of convertible types?
 {
  /ToMathematicaExpression      % supply the error handler with appropriate
  /NoMathematicaRepresentation  % information about the problem
  raiseerror
 } if
 exch dup rollu type get exec   % apply conversion rule
} def

%----------------------------------------------------------------------------
/* BeginDocumentation

Name: UnitStep - The unit step function (aka Heavyside function)

Synopsis:
              x  UnitStep -> 0   ;if  x <  0
                          -> 1   ;if  x >= 0
     [x1 x2 ...] UnitStep -> 0   ;if xi <  0 for any xi in [x]
                          -> 1   ;if xi >= 0 for all xi in [x]

Description:
     "x UnitStep" represents the unit step function,
     equal to 0 for x<0 and 1 for x>=0.

     "[x1 x2 ...] UnitStep" represents the multidimensional unit step
     function which is 1 only if none of the xi are negative.

     Alternatives: Function UnitStep_i for integers, UnitStep_d for
     doubles, UnitStep_ia for integer arrays, UnitStep_da for double
     arrays (all undocumented) -> behavior and synopsis are the same,
     except that no warnings or error messages are thrown.

Diagnostics:
     When called on an empty array, /ArgumentType is raised.

     When first element of the array is not of type integer or double,
     /ArgumentType is raised.

     Will break if called on an array containing non-numerical values.

Author: Ruediger Kupper

FirstVersion: 13.3.2003

Remarks:
     This is the SLI version of the Mathematica function "UnitStep".
     Documentation taken from the Mathematica Book.

     Implementation of the type variants can be found in file
     synod2/sli/slimath.cc.
SeeAlso: Sign, abs
References:
     The Mathematica Book

*/

/UnitStep [/integertype] /UnitStep_i load def
/UnitStep [/doubletype]  /UnitStep_d load def
/UnitStep [/arraytype]
{
  size 0 eq
  {
    M_ERROR (UnitStep) (Array must not be empty.) message
    /UnitStep /ArgumentType raiseerror
  } if

  dup 0 get type
  mark
  1 pick /integertype eq {pop UnitStep_ia exit} case
  1 pick /doubletype  eq {pop UnitStep_da exit} case
  {
    pop
    M_ERROR (UnitStep) (Array must be a homogeneous integer or double array.) message
    /UnitStep /ArgumentType raiseerror
  }
  switchdefault
} bind def




/*BeginDocumentation
Name: Sign - returns the sign of its argument
Synopsis:
 integer Sign -1,0, or 1
 double  Sign -1,0, or 1
Parameters:
 The return value is always an integer
Description:
 The C++ standard library does not define a sign function because
 there is no general agreement on the return value for 0. The function
 Sign implements the decision made for Mathematica: if the argument is
 0, Sign returns 0.
Author: Diesmann
FirstVersion: 2007.11.28
References:
   [1] The Mathematica Book "Sign"
SeeAlso: UnitStep, abs
*/

/Sign
{
 dup
 0 eq
 {pop 0 }
 {0 gt {1}{-1} ifelse }
 ifelse
}
def


/* BeginDocumentation
Name: IntegerPart - Return integer part of the argument.
Synopsis: double IntegerPart -> integerpart
Description:
     In effect sets all digits to the right of the decimal point to
     zero. The sign is preserved. The output value is of type integer.
Parameters:
     The input value must be of type double,
     the output value is of type double.
Examples:
     -2.3 IntegerPart -> -2.0
SeeAlso: FractionalPart

*/
/IntegerPart trie
 [/doubletype] { int_d double_i } addtotrie
def

/* BeginDocumentation
Name: FractionalPart - Return fractional part of the argument.
Synopsis: double FractionalPart -> fractionalpartpart
Description:
     In effect sets all digits to the left of the decimal point to
     zero. The sign is preserved. The output value is of type double.
Parameters:
     The input value must be of type double,
     the output value is of type double.
Examples:
     -2.3 FractionalPart -> -0.3
SeeAlso: IntegerPart

*/
/FractionalPart trie
 [/doubletype] {dup_ int_d double_i sub_dd} addtotrie
def


/*BeginDocumentation
Name: Max - returns the largest element of an array
Synopsis:
 array Max -> max element
Parameters:
 array
Description:
  This function finds the largest element in a list, DoubleVector or IntVector. To process
  heterogeneous arrays, the operator gt must be supported between any pair of objects in
  the list.

Examples:
 [8 4 3 6 9 5] Max --> 9
Remarks:
 Replacess arr::Max in future versions.
Author: Gewaltig
FirstVersion: 2008.2.12 (Diesmann)
References:
   [1] The Mathematica Book "Max"
SeeAlso: Min, Sort
*/
/Max
{
   size 0 eq
   {  
     /Max /RangeCheck raiseerror
   } if
   dup 0 get  % start value as sentinel
   exch 
   { 
      dup 2 index gt % compare current element with sentinel
     { 
       exch pop % if element is greater than sentinel, make it new sentinel
     } 
     {
        pop  %else discard
     } ifelse 
   } forall 
} def

/*BeginDocumentation
Name: Min - returns the smallest element of an array
Synopsis:
 array Min -> min element
Parameters:
 array
Description:
 This function finds the smallest element in a list, DoubleVector or intVector.
 To process heterogeneous arrays, the operator lt must be supported between
 any pair of objects in the list.

Examples:
 [8 4 3 6 9 5] Min --> 3
Remarks:
 Replacess arr::Min in future versions.

Author: Gewaltig
FirstVersion: 2008.2.12 (Diesmann)
References:
   [1] The Mathematica Book "Min"
SeeAlso: Max, Sort, Mean, Variance
*/
/Min
{
   size 0 eq
   {  
     /Max /RangeCheck raiseerror
   } if
   dup 0 get  % start value as sentinel
   exch 
   { 
      dup 2 index lt % compare current element with sentinel
     { 
       exch pop % if element is less than sentinel, make it new sentinel
     } 
     {
        pop  %else discard
     } ifelse 
   } forall 
}
def


/*BeginDocumentation
Name: Total - returns the sum of the elements of an array
Synopsis:
 array Total -> sum of elements
Parameters:
 array
Description:
 The function is implemented in SLI and based on the
 overloaded operator add.
Examples:
 [8 4 3 6 9 5] Total --> 35
Remarks:
 The Mathematica version is more general.
 Replacess arr::Sum in future versions.
Author: Diesmann
FirstVersion: 2009.2.22
References:
   [1] The Mathematica Book "Total"
SeeAlso: Max, Sort, Mean, Variance
*/
/Total
{
 0 exch {add} Fold
} def

/*BeginDocumentation
Name: Mean - returns the mean of the elements of an array
Synopsis:
 array Mean -> double, mean of elements
Parameters:
 array
Description:
 The function is implemented in SLI and based on the
 operator Total.
Examples:
 [8 4 3 6 9 5] Mean --> 5.833
Remarks:
 The Mathematica version is more general
 Replaces arr:Mean in future versions.
Author: Diesmann
FirstVersion: 2009.2.22
References:
   [1] The Mathematica Book "Mean"
SeeAlso: Max, Sort, Total, Variance
*/
/Mean
{
 size cvd exch Total exch div
} def

/*BeginDocumentation
Name: Variance - returns the variance of the elements of an array
Synopsis:
 array Variance -> double, unbiased estimate of variance of elements
Parameters:
 array
Description:
 The function is implemented in SLI using Mean and Total
Examples:
 [8 4 3 6 9 5] Variance --> 5.366
Remarks:
 The Mathematica version is more general.
 Replaces arr::Var in future versions.
Author: Diesmann
FirstVersion: 2009.2.22
References:
   [1] The Mathematica Book "Variance"
SeeAlso: Max, Sort, Total, Mean, StandardDeviation
*/
/Variance
{
 dup size 1 sub cvd rollu
 Mean
 sub
 {sqr} Map
 Total
 exch
 div
} def


/*BeginDocumentation
Name: StandardDeviation - returns the standard deviation of the elements of an array
Synopsis:
 array StandardDeviation -> double, standard deviation
Parameters:
 array
Description:
 The function is implemented in SLI using Variance
Examples:
 [8 4 3 6 9 5] StandardDeviation --> 2.3166
Remarks:
 The Mathematica version is more general.
 Replaces arr::SDev in future versions.
Author: Diesmann
FirstVersion: 2009.2.22
References:
   [1] The Mathematica Book "StandardDeviation"
SeeAlso: Max, Sort, Total, Variance
*/
/StandardDeviation
{
 Variance sqrt
} def





% the following two definitions are used to make escaping of
% SLI strings in Mathematica easier
% e.g, see extras/mathematica/LinkMathematica.m
% Diesmann, 1.4.2003
%
/NewLine (\n) def
/DoublyEscapedNewLine (\\\\n) def



/* BeginDocumentation
  Name: CompileMath - converts traditional math to postfix notation
  Synopsis: string CompileMath -> proc
  Description:
   CompileMath converts a string containing a mathematical expression
   in traditional infix notation to a procedure using the
   standard postfix notation of SLI. The algorithm is:
    1. replace traditonal operators like "-" and "+" with
       SLI literals like /sub and /add
    2. decompose the string into tokens using the standard
       SLI scanner
    3. compile the sequence of tokens to a SLI postfix expression
       using the predictive recursive-descent parser described in
       chapter 2 of the Dragon Book.
   The result is the unevaluated expression. This enables the user
   to store the expression for later reevaluation.
  Parameters:
   string, is the mathematical expression
   proc, is the unevaluated expression in SLI postfix notation
  Examples:
    ( 5 + 3 * 7 )      CompileMath  exec  --> 26
    ( 5 * (3 + 7) )    CompileMath  exec  --> 50
    ( 5 + x * 7 )      CompileMath        --> {5 x 7 mul add}
    ( 3 + exp 5 )      CompileMath        --> {3 5 exp add}
    ( 3 + exp (  x ) ) CompileMath        --> {3 x exp add}
    ( 3 + exp ( -x ) ) CompileMath        --> {3 x neg exp add}
    ( 3 * exp (sin 2)) CompileMath        --> {3 2 sin exp mul}
    ( 3 * exp sin 2 )  CompileMath        --> {3 2 sin exp mul}
    (4 * - 7)          CompileMath exec   --> -28
    (2^3)              CompileMath        --> {2 3 pow}
    (5+3*2^3)          CompileMath        --> {5 3 2 3 pow mul add}
    (5+3*2^3-4)        CompileMath        --> {5 3 2 3 pow mul add 4 sub}
    (5+3*2^3/4)        CompileMath        --> {5 3 2 3 pow mul 4 div add}
    (5+3*2^-3)         CompileMath        --> {5 3 2 3 neg pow mul add}
    (4)                CompileMath        --> {4}
    ()                 CompileMath        --> {}
    (a=7+3)            CompileMath        --> {/a 7 3 add dup rolld Set}
    (a=7+3;)           CompileMath        --> {/a 7 3 add dup rolld Set pop}
    (a=7+3;6)          CompileMath        --> {/a 7 3 add dup rolld Set pop 6}
    (a=7+4;b=2*exp(-2.0/10)) CompileMath  --> {/a 7 4 add dup rolld Set pop /b 2 2.0 neg 10 div exp mul dup rolld Set}
    (Function({x+2},'x)) CompileMath      --> {{x 2 add} /x Function}
    (f=Function({x+2},'x)) CompileMath    --> {/f {x 2 add} /x Function dup rolld Set}
    (f={#+2})              CompileMath    --> {/f {<< >> begin /# Set # 2 add end} dup rolld Set}
    ([4,3,2])              CompileMath    --> {[4 3 2]}
    (x=7+[4,3,2]*2)        CompileMath    --> {/x 7 [ 4 3 2 ] 2 mul add dup rolld Set}
    ([])                   CompileMath    --> {[]}
    (<< 'x : [-3, 9]*2, 'y : 7 >>) CompileMath --> {<< /x [ 3 neg 9 ] 2 mul /y 7 >>}
    (<< >>)                CompileMath    --> {<< >>}
    (5+3 // Function( {2*x+1},'x)  ) CompileMath exec  --> 17
    (1+(5+3 // Function( {2*x+1},'x))  ) CompileMath exec  --> 18
    ( [ 3, [ 2, 1], -9] // Flatten) CompileMath exec --> [3 2 1 -9]
    ( [ 3, [ 2, 1], -9] // Flatten // {Select(#,{#<3})}  ) CompileMath exec --> [2 1 -9]
    (5+3 // {#+1}  ) CompileMath exec --> 9

  Bugs:
   The present version fails for doubles with negative exponents
   because the lexer just replaces all "-" with /sub. A slightly
   smarter lexer using a regular expression can solve this problem.
  Remarks:
   The function can be improved by using a more powerful parsing
   scheme. The predictive recursive parsing scheme is used here
   as an educational example.
  Author: Diesmann
  FirstVersion: 090117

  SeeAlso: Inline, ExecMath, cst, cvx, exec
  References:
   [1] The Dragon Book, 1988, chapter 2
*/

({)  symbol pop /BeginProcedureSymbol Set pop
(})  symbol pop /EndProcedureSymbol Set pop
([)  symbol pop /BeginArraySymbol Set pop
(])  symbol pop /EndArraySymbol Set pop
([)  token pop  /BeginArrayToken Set pop
(])  token pop  /EndArrayToken Set pop
(<<)  symbol pop /BeginDictionarySymbol Set pop
(>>)  symbol pop /EndDictionarySymbol Set pop


% for debugging, displays call sequence
/pdef
{
% % l p
% 1 index {==} exch prepend exch join
 def
}
def

/CompileMath
{
<</out [] >> begin currentdict /cdict Set

/lexan
{
 [
  (/)  ( /div )       % this first because "/" leads literals
  (/div  /div) (/pipe)   % for //
  (')  ( /lit /)      % operator /literal followed by SLI notation literal value
  (^)  ( /pow )
  (**) ( /pow )   % as in python
  (*)  ( /mul )
  (-)  ( /sub )
  (+)  ( /add )
  (x) 0 40 put ( /openparenthesis )
  (x) 0 41 put ( /closeparenthesis )
  (<<) ( /BeginDictionary )
  (>>) ( /EndDictionary )
  (==) ( /eq )
  (!=) ( /neq )
  (<=) ( /leq )
  (<)  ( /lt )
  (>=) ( /geq )
  (>)  ( /gt )
  (=)  ( /def )
  (;)  ( /sepexpr )
  (,)  ( /comma )
  (:)  ( /colon )
  (" /openparenthesis )  (x) 0 40 put
  ( /closeparenthesis ") (x) 0 41 put

  (#)  ( /argument )
 ] 2 Partition

 {arrayload pop ReplaceOccurrences} Fold

 css   % alternative: do this stepwise with symbol
}
def


/gettoken {
 in empty not
 {
  First
  cdict /in in Rest put_d
 } if
} def

/match
{
 /lookahead load eq         % avoid immediate lookup of identifier
 {cdict /lookahead gettoken put_d}
 { /match /SyntaxError raiseerror }
 ifelse
} def

/seq
{
 delayedexpr
 {
  lookahead /comma eq
  {
   /comma match seq  % no output for comma
  }
  {
   exit
  }
  ifelse
 } loop
} pdef


% algorithm to compile a pure function:
% -------------------------------------
%
% (1) match the BeginProcedureSymbol
% (2) determine the current length of the compiled code
% (3) compile the body of the function
% (4) extract the previously compiled code from out
% (5) determine length of compiled body
% (6) extract code of compiled body from out
% (7) make it a literal procedure object
% (8) append procedure object to previously compiled code
% (9) store result in out variable
%
%

/purefunction
{
 BeginProcedureSymbol match
   out length                          % length

   << /n_args 0 >> begin

% expr
    expr_sequence                        % length


%n_args ==

     dup out exch Take                   % length first
     exch                                % first length
     out length sub  out exch Take       % first last
     cvx

     n_args 0 gt                         % the procedure has arguments
     {
      {<< >> begin /# Set} exch join {end} join
     }
     if

     cvlp_p                             % first proc  (7)

     append /out cdict                   % v l d  (8)
     exch                                % v d l
     rolld                               % d l v
     put_d

  end

 EndProcedureSymbol match
} pdef


/expr_sequence
{
 {
  /lookahead load EndProcedureSymbol eq {exit} if

  expr
  /lookahead load /sepexpr eq
  {
   /sepexpr  match /pop cvn /out cdict AppendTo
  }
  if

 } loop
} pdef


/delayedexpr
{
 /lookahead load BeginProcedureSymbol eq
 {
  purefunction
 }
 {
  litarg
 }
 ifelse
} pdef


/litarg
{
 /lookahead load /lit eq
 {
  /lit match
  lookahead /out cdict AppendTo  % the current symbol is the literal
  lookahead match
 }
 {
  expr
 }
 ifelse
} pdef


% An expression is an inequality followed by a piped sequence
% of operations on the result of the inequality:
%    ie // a // b // c ...
% The operations are either specified by an individual function name or direct
% generators of pure functions:
%    ie // Flatten
%    ie // Function({x+1},'x)
%    ie // {#+1}
%
/expr
{
 inequality

 {
  /lookahead load /pipe eq
  {
   /pipe match
   /lookahead load type /nametype eq
   {
    /lookahead load /Function cvn eq
    {
     inequality /exec cvn /out cdict AppendTo
    }
    {
     /lookahead load /out cdict AppendTo
     /lookahead load match
    }
    ifelse % pure function starting with 'Function'
   }
   {
    purefunction /exec cvn /out cdict AppendTo
   }
   ifelse  % nametype
  }
  {
   exit
  }
  ifelse

 } loop     % /pipe
} pdef



/inequality
{
 equality
 {
  /lookahead load /lt eq
  {
   /lt match equality /lt cvn /out cdict AppendTo
  }
  {
   /lookahead load /leq eq
   {
    /leq match equality /leq cvn /out cdict AppendTo
   }
   {
    /lookahead load /gt eq
    {
     /gt match equality /gt cvn /out cdict AppendTo
    }
    {
     /lookahead load /geq eq
     {
      /geq match equality /geq cvn /out cdict AppendTo
     }
     {
      exit
     }
     ifelse
    }
    ifelse
   }
   ifelse
  }
  ifelse

 } loop     % /lt, /leq, /gt, /geq
} pdef


/equality
{
 sum
 {
  /lookahead load /eq eq
  {
   /eq match sum /eq cvn /out cdict AppendTo
  }
  {
   /lookahead load /neq eq
   {
    /neq match sum /neq cvn /out cdict AppendTo
   }
   {
    exit
   }
   ifelse
  }
  ifelse
 } loop     % /eq, /neq
} pdef



/sum
{
 term
 {
  /lookahead load /add eq
  {
   /add match term /add cvn /out cdict AppendTo
  }
  {
   /lookahead load /sub eq
   {
    /sub match term /sub cvn /out cdict AppendTo
   }
   {
    exit
   }
   ifelse
  }
  ifelse
 } loop     % /add, /sub
} pdef



/factor
{
 signedfactor power
} pdef

/power
{
 {
  /lookahead load /pow eq
  {
   /pow match signedfactor /pow cvn /out cdict AppendTo
  }
  {
   exit
  }
  ifelse
 } loop
} pdef


/signedfactor
{
 /lookahead load /sub eq
 {
  /sub match unsignedfactor /neg cvn /out cdict AppendTo
 }
 {
  unsignedfactor
 } ifelse
} pdef


/array
{
 /BeginArrayToken load /out cdict AppendTo
 lookahead match

 lookahead /EndArraySymbol load eq
 {
  /EndArrayToken load /out cdict AppendTo
  lookahead match
 }
 {

  {
   delayedexpr     % expr
   lookahead /comma eq
   {
    /comma  match
   }
   {
    exit
   }
   ifelse
  }
  loop

  lookahead /EndArraySymbol load eq
  {
   /EndArrayToken load /out cdict AppendTo
   lookahead match
  }
  {
   /array /EndArrayExpectedError raiseerror
  }
  ifelse

 }
 ifelse

} pdef


/dictionaryentry
{
 litarg

 lookahead /colon eq
 {
  lookahead match
 }
 {
  /dictionaryentry /ColonExpectedError raiseerror
 }
 ifelse

 expr

} pdef



/dictionary
{
 /BeginDictionarySymbol load /out cdict AppendTo
 lookahead match

 lookahead /EndDictionary eq
 {
  /EndDictionarySymbol load /out cdict AppendTo
  lookahead match
 }
 {

  {
   dictionaryentry
   lookahead /comma eq
   {
    /comma  match
   }
   {
    exit
   }
   ifelse
  }
  loop

  lookahead /EndDictionary eq
  {
   /EndDictionarySymbol load /out cdict AppendTo
   lookahead match
  }
  {
   /array /EndDictionaryExpectedError raiseerror
  }
  ifelse

 }
 ifelse

} pdef





/unsignedfactor    %  x =
{
 /lookahead load type /nametype eq % avoid immediate lookup of identifiers
 {
  /lookahead load                   % leave id on stack
  /lookahead load match  assign  % factorarg /out AppendTo % assign  % /out AppendTo
 }
 {
  lookahead /argument eq
  {
   (#) cvn /out cdict AppendTo
   /argument match
   1 /n_args Set
  }
  {
   lookahead /openparenthesis eq
   {
    /openparenthesis match expr /closeparenthesis match
   }
   {
    lookahead type /integertype eq
    lookahead type /doubletype  eq or
    lookahead type /stringtype  eq or
    {
     lookahead /out cdict AppendTo
     lookahead match
    }
    {
     lookahead /BeginArraySymbol load eq
     {
      array
     }
     {
      lookahead /BeginDictionary eq
      {
       dictionary
      }
      {
       /unsignedfactor /SyntaxError raiseerror
      } ifelse
     } ifelse
    } ifelse
   } ifelse
  } ifelse
 } ifelse
} pdef


/assign
{
 /lookahead load /def eq
 {
  % the id is still on the stack, make literal for assignment
  cvlit /out cdict AppendTo /def match delayedexpr {dup rolld Set} cvlit /out cdict JoinTo
              % version without return value:
              %                       /def cvn /out AppendTo
 }
 { % the id is still on the stack
  factorarg /out cdict AppendTo
 }
 ifelse
} pdef


/factorarg
{
 /lookahead load type /nametype eq % avoid immediate lookup of identifiers
 {
  /lookahead load
  /lookahead load match factorarg /out cdict AppendTo
 }
 {
  lookahead /openparenthesis eq
  {
   /openparenthesis match
   /lookahead load /closeparenthesis eq
   {
    /closeparenthesis match
   }
   {
    seq /closeparenthesis match
   }
   ifelse
  }
  {
   lookahead type /integertype eq
   lookahead type /doubletype  eq or
   lookahead type /stringtype  eq or
   {
    lookahead /out cdict AppendTo
    lookahead match
   }
   {
    lookahead /BeginArraySymbol load eq
    {
     array
    }
    {
     lookahead /BeginDictionary eq
     {
      dictionary
     }
     if                      % epsilon
    } ifelse
   } ifelse
  } ifelse
 } ifelse

} pdef



%
/term
{
 factor
 {
  /lookahead load /mul eq
  {
   /mul match factor /mul cvn /out cdict AppendTo
  }
  {
   /lookahead load /div eq
   {
    /div match factor /div cvn /out cdict AppendTo
   }
   {
    exit
   }
   ifelse
  }
  ifelse

 } loop
} pdef


/statement
{
 {
  /lookahead load [] eq {exit} if

  expr
  /lookahead load /sepexpr eq
  {
   /sepexpr  match /pop cvn /out cdict AppendTo
  }
  if

 } loop
} pdef



%
% main of CompileMath
%

lexan /in Set

gettoken /lookahead Set

statement  % expr


out cvx

end
}
def

/*BeginDocumentation
 Name: ExecMath - execute a math expression.
 Synopsis: (expr) ExecMath -> val
 Description:
  ExecMath is equivalent to the sequence
  CompileMath exec
 SeeAlso: CompileMath, Inline
*/
/ExecMath
{
  CompileMath exec
} def


/fsprompt
{
  (fSLI )
  count 1 gt_ii      % counter has to be corrected for operative
  {                  % objects on the stack
    ([) join_s
    count 1 sub_ii cvs join_s
  } if
  (] ) join_s
} bind def

/* BeginDocumentation
Name: mathexecutive - start interactive math session
Description:
Starts an interactive shell similar to the standard shell of SLI
provided by the command executive. You can leave the shell by
typing exit.

In contrast to executive, mathexecutive accepts an infix mathematical
notation. The input is compiled with command CompileMath prior to
execution.  See the documentation of CompileMath for the details of
the syntax.

Remarks:
The syntax accepted by this command is experimental, be prepared for
substantial changes.

Author: Diesmann
FirstVersion: March 2010
SeeAlso: executive, exit, CompileMath
*/


%% check whether GNU readline is installed. If so,
%% use it for the executive command.

systemdict /GNUreadline known
{

 /mathexecutive
 {
  (The syntax accepted by this command is experimental,\nsee the documentation of CompileMath for details.)
   M_WARNING  message
  {  %% loop with stopped context to catch signals
   {
    callback
    fsprompt GNUreadline
    {
      dup GNUaddhistory
      CompileMath stopped  {handleerror} if
    } if
   } stopped {handleerror} if % to catch signals
  } loop
% exithook
 } bind def

}
{

 /mathexecutive
 {
  (The syntax accepted by this command is experimental,\nsee the documentation of CompileMath for details.)
  M_WARNING  message
  {
   {
     callback
     fsprompt readline
     {
      CompileMath stopped {handleerror} if
     } if
   } stopped {handleerror} if % to catch signals
  } loop
%  exithook
 } bind def

} ifelse




/*BeginDocumentation
Name: Inline - Replace names in a procedure with their definitions.

Synopsis:
   {proc} <<dict>> Inline -> {proc'}

Parameters:
   {proc}    - procedure to be transformed
   <<dict>>  - dictionary with names and definitions for the names to be inlined.
   {proc'}   - the transformed procedure with all names replaced.

Description:

Transform the input procedure {proc} such that all names that are
defined in <<dict>> are placed by their definitions.

Inline can be used to inline the code of procedures or to replace
names of constants with their literal values. All names that are not
defined in <<dict>> are unchanged.

Inline is particularly useful in combination with CompileMath.

Inline is similar to bind, but there are two big differences:
1. bind uses the current dictstack to determine which names are placed.
2. bind only replaces names that refer to C++-functions or tries.

Examples:
SLI ] {a b add} <</a 1 /b 2 >> Inline ==
{1 2 add}

SLI ] {1 2 3 stack} << /stack dup load  >> Inline ==
{1 2 3 0 1 -count- 3 -sub_ii- /{-index- =} -for-}

Version: January 19 2008
Author: marc-Oliver Gewaltig
SeeAlso: bind, CompileMath
*/
/:Inline
{
   [
     exch  % swap position of mark and array
     cvlit % convert procedure to array
     {
       dup
       type /nametype eq
       {
         dup cvlit
         currentdict exch known
         {
           cvlit currentdict exch get
           dup type /proceduretype eq
           {
             cvlit arrayload pop
           } if
         } if
       }
       {
         dup type /literalproceduretype eq
         {
	   exec
           currentdict
           Inline cvlp
         } if
       } ifelse

     } forall
   ] cvx
} def

/Inline
[/proceduretype /dictionarytype]
{
  begin
    :Inline
  end
} def

/* BeginDocumentation
Name: Apply - calls a function with the elements of an array as arguments
Synopsis: array proc Apply -> any
Description:
 Apply interprets the elements of the input array a as the list
 of arguments of the supplied function f,
   f(a(1),a(2), ...,a(n))

 This is to be distinguished from Map which individually applies
 the function to the elements of the array,
   [f(a(1),f(a(2), ...,f(a(n))] 

Parameters:
  array is an arbitrarily shaped heterogeneous array. 
  proc is any procedure object (pure function).

Examples:

  [1 2] {add} Apply --> 3
  [1 2] {dup mul} Map --> [1 4]
  [(hell world) 4 (o)] {insert} Apply --> (hello world)

Author: Diesmann
FirstVersion: unknown, documented 121124
Remarks:
 This function is an implementation of Mathematica's Apply function.
SeeAlso: Map, MapAt, MapThread
References:
 [1] The Mathematica Book V4.0 "Apply"
*/
% a f
/Apply
{
 exch       % f a
 arrayload  % f a1 ... an n
 1 add      % f a1 ... an n+1
 -1 roll    % a1 ... an f
 exec
}
def



/*BeginDocumentation
Name: Function - creates pure function with named arguments

Synopsis:
   {proc} literal_1 ... literal_n    Function -> proc'
   string literal_1 ... literal_n    Function -> proc'
   [literal_1 ... literal_n] {proc}  Function -> proc'
   [literal_1 ... literal_n] string  Function -> proc'


Parameters:
   proc       - code body using variables
   string     - code body using variables in infix notation
   literal_i  - the name of the ith argument
   proc'      - pure function with named arguments

Description:
 Pure functions are one of the most powerful features of SLI. They are
 first class objects and can be assembled at run time like arrays. Some
 times pure functions are constructed for one time execution, however more
 often they are used as arguments of functional operators like Map and Fold
 executing the pure function many times.
 If a pure function has several arguments or a particular argument is used many
 times in the code managing the location of the arguments on the stack can be
 cumbersome. In these situations operator Function is helpful, it assigns each
 argument of the pure function to a formal name which can be used in the body
 of function. If the pure function is specified as a string, Compile Math is
 called for conversion to rpn. Note that the example combining Function and Map
 is efficient. The pure function is constructed from the string only once but
 executed 4 times with different arguments. In the alternative syntax the variables
 are declared by an array prior to the body of the function. This notation increases
 the readability of definitions of  named functions because in most programming
 languages the declaration of variables preceeds the function body. In combination
 with operator def also the type of the arguments can be specified. The definition
 of a function without arguments is useful if the body of the function introduces
 local variables and therefore profits from the automatic restriction of scope by
 operator Function. This is shown in the last example. Without the empty array the
 arguments of Function would not be unique.
 The availability of the alternative version ExecFunction with immediate execution
 highlights the fact that a pure function with named arguments maybe used
 for clarity even in situations where it needs to be evaluated only once.

Examples:
 2   {x 1 x add mul} /x    Function exec --> 6
 2 3 {x 1 x add mul} /x /y Function exec --> 6
 2 3 {x y x add mul} /x /y Function exec --> 10
 2 3   ( x*(y+x) )   /x /y Function exec --> 10

 ( x*(y+x) ) /x /y Function --> {<< >> begin /y Set /x Set x y x add mul end}

 [2. 3. 4. 5.]  (x + (1+x)^3) /x Function Map --> [29. 67. 129. 221.]

 /f ( x*(y+x) )  /x /y  Function def
 /f [/x /y] ( x*(y+x) ) Function def

 /f [/doubletype /doubletype] [/x /y] (y+x^2) Function def
 /f [/doubletype /doubletype] [/x /y] {y x dup mul add} Function def


 /f [] (x=sin(0.7);x^2-3*x) Function def


Version: 090302
Author: Diesmann
References:
   [1] The Mathematica Book "Function"
SeeAlso: CompileMath, Inline, ExecFunction
*/
/Function_
{
 {<< >> begin}

 {
  exch
  dup type
  /literaltype neq
  {
   dup type
   /stringtype eq
   {
    CompileMath
   } if
   exit
  } if
  append {Set} join
 } loop

 join
 {end} join
}
def

/Function
[/literaltype]
{
 Function_
} def

/Function
[/arraytype /anytype]
{
 exch arrayload pop Function_
}
def



/*BeginDocumentation
Name: ExecFunction - immediately execute a pure function with named arguments
Synopsis:
   {proc} literal_1 ... literal_n ExecFunction -> val
   string literal_1 ... literal_n ExecFunction -> val

Description:
  ExecFunction is equivalent to the sequence
  Function exec
Examples:
 2   {x 1 x add mul} /x    ExecFunction --> 6
 2 3 {x 1 x add mul} /x /y ExecFunction --> 6
 2 3 {x y x add mul} /x /y ExecFunction --> 10
 2 3   ( x*(y+x) )   /x /y ExecFunction --> 10

Version: 090304
Author: Diesmann
 SeeAlso: Function, CompileMath, Inline
*/
/ExecFunction
{
 Function exec
} def


/*BeginDocumentation
Name: LambertW - simple iteration implementing the Lambert-W function
Synopsis:
   double double LambertW -> double
Parameters:
The first parameter is the argument of the Lambert-W function, the
second argument is the start value of the iteration. 0.0 is a good initial
value for the principal branch of the Lambert-W function. -2.0 is a good
choice to select the non-principal branch.

Description:
The Lambert-W function is the inverse function of x=W*exp(W). For real values of
x and W, the function W(x) is defined on [-1/e,\infty). On the interval [-1/e,0)
it is double valued. The two branches coincide at W(-1/e)=-1. The so called
principal branch LambertW0 continuously grows (W>=-1) and crosses the origin (0,0).
The non-principal branch LambertWm1 is defined on [-1/e,0) and declines to -\infty for
growing x.

LambertW uses Halley's method described in [1] (see also [2]) to
implement the functions for the two branches LambertW0 and LambertWm1
if NEST has no access to the GSL [3].

Version: 090818
Author: Diesmann
References:
[1] Corless, R. M., Gonnet, G. H., Hare, D. E. G., Jeffrey, D. J., & Knuth, D. E.
    (1996). On the lambert w function. Advances in Computational Mathematics 5,
     329--359.
[2] Wikipedia (2009). Lambert W function ---wikipedia, the free encyclopedia.
[3] Galassi, M., Davies, J., Theiler, J., Gough, B., Jungman, G., Booth, M.,
    & Rossi, F. (2006). GNU Scientific Library Reference Manual (2nd Ed.).
    Network Theory Limited.

SeeAlso: LambertWm1, LambertW0, testsuite::test_lambertw, CompileMath
*/
/LambertW
[/doubletype /doubletype] [/x /start]
{
 1e-12 /prec Set
 start /w    Set
 100   % maxiters
 (we=w*E**w; w1e=(w+1)*E**w; abs((x-we)/w1e)) CompileMath
 {prec leq {w exit} if }
 (w=w-(we - x) / (w1e - (w + 2) * (we - x) / (2*w + 2));) CompileMath

 join join
 repeat
}
Function def




/*BeginDocumentation
Name: LambertW0 - principal branch of the Lambert-W function
Synopsis:
   double LambertW0 -> double
Description:
The Lambert-W function [1] is the inverse function of x=W*exp(W). For real values of
x and W, the function W(x) is defined on [-1/e,\infty). On the interval [-1/e,0)
it is double valued. The two branches coincide at W(-1/e)=-1. The so called
principal branch LambertW0 continuously grows (W>=-1) and crosses the origin (0,0).
The non-principal branch LambertWm1 is defined on [-1/e,0) and declines to -\infty for
growing x.

NEST uses the GSL [2] implementations of LambertW0 and LambertWm1 if available and
falls back to to the iterative scheme LambertW suggested in [1] if not.
The GSL interfaces for LambertW0 and LambertWm1 are in the SpecialFunctionsModule
of SLI.

Examples:

The Lambert-W function has applications in many areas as described in [1] and [3].
For example, the solution of
     exp(s) = 1 + a*s
with respect to s can be written in closed form as
  s=1/a * (-aW(-exp(-1/a)/a) -1 )

Version: 090818
Author: Diesmann
References:
[1] Corless, R. M., Gonnet, G. H., Hare, D. E. G., Jeffrey, D. J., & Knuth, D. E.
    (1996). On the lambert w function. Advances in Computational Mathematics 5,
     329--359.
[2] Galassi, M., Davies, J., Theiler, J., Gough, B., Jungman, G., Booth, M.,
    & Rossi, F. (2006). GNU Scientific Library Reference Manual (2nd Ed.).
    Network Theory Limited.
[3] Wikipedia (2009). Lambert W function ---wikipedia, the free encyclopedia.


SeeAlso: LambertWm1, LambertW, testsuite::test_lambertw
*/
statusdict/have_gsl :: not
{
 /LambertW0  [/doubletype] {0.  LambertW} def
}
if

/*BeginDocumentation
Name: LambertWm1 - non-principal branch of the Lambert-W function
Synopsis:
   double LambertWm1 -> double
Description:
The Lambert-W function [1] is the inverse function of x=W*exp(W). For real values of
x and W, the function W(x) is defined on [-1/e,\infty). On the interval [-1/e,0)
it is double valued. The two branches coincide at W(-1/e)=-1. The so called
principal branch LambertW0 continuously grows (W>=-1) and crosses the origin (0,0).
The non-principal branch LambertWm1 is defined on [-1/e,0) and declines to -\infty for
growing x.

NEST uses the GSL [2] implementations of LambertW0 and LambertWm1 if available and
falls back to to the iterative scheme LambertW suggested in [1] if not.
The GSL interfaces for LambertW0 and LambertWm1 are in the SpecialFunctionsModule
of SLI.

Examples:

The Lambert-W function has applications in many areas as described in [1] and [3].
For example, the problem of finding the location of the maximum of the postsynaptic
potential generated by an alpha-function shaped current can be reduced to the
equation
     exp(s) = 1 + a*s .
Here, s is the location of the maximum in scaled time s=b*t, where
b= 1/tau_alpha - 1/tau_m and a is the ratio of the time constants tau_m/tau_alpha.
In terms of the Lambda_W function the solution is
  s=1/a * (-aW(-exp(-1/a)/a) -1 ) .
The solution is guaranteed to live on the non-principal branch because the scaled time
needs to be positive. This requires W < -1/a which is trivially fulfilled for the
non-principal branch and there is no solution on the principal branch.


Version: 090818
Author: Diesmann
References:
[1] Corless, R. M., Gonnet, G. H., Hare, D. E. G., Jeffrey, D. J., & Knuth, D. E.
    (1996). On the lambert w function. Advances in Computational Mathematics 5,
     329--359.
[2] Galassi, M., Davies, J., Theiler, J., Gough, B., Jungman, G., Booth, M.,
    & Rossi, F. (2006). GNU Scientific Library Reference Manual (2nd Ed.).
    Network Theory Limited.
[3] Wikipedia (2009). Lambert W function ---wikipedia, the free encyclopedia.
SeeAlso: LambertW0, LambertW, testsuite::test_lambertw
*/
statusdict/have_gsl :: not
{
 /LambertWm1 [/doubletype] {-2. LambertW} def
}
if

%----------------------------------------------------------------------------
/* BeginDocumentation
Name: ScanThread - execute a function to corresponding elements of n arrays
Synopsis: [[a11 ... a1n]...[am1 ... amn]] {f} ScanThread -> -
Description: ScanThread applies the given function to corresponding elements
             of m argument arrays. This is similar to MapThread, but no results
	     are returned.

Parameters: the first parameter is a list of m arrays of equal size n.
            The second parameter is a procedure which takes m arguments and
	    returns nothing.

Examples:   [[(a) (b) (c)] [1 2 3]] { exch (: ) join exch cvs join == } ScanThread

	    generates the following output and leaves nothing on the stack.

References: This function implements the simple version of Mathematica's ScanThread
SeeAlso: MapThread, forall, Map, MapIndexed, NestList, FoldList
*/

/ScanThread
[/arraytype /proceduretype]
{
  << >> begin
    /proc Set
    /args Set

    args length 0 gt
    {
      % ensure all arrays have equal length
      args { length } Map
      dup First /l0 Set
      Rest true exch { l0 eq and } Fold
      not
      {
        /ScanThread /ArraysMustHaveEqualLength raiseerror
      } if

      args Transpose
      { arrayload ; proc } forall
    }
    if
  end
} def

%% Functions on Integer and double vectors

/cva [/intvectortype] /intvector2array load def
/cva [/doublevectortype] /doublevector2array load def

/**
* BeginDocumentation:
* Name: cv_iv - convert array of integers to an IntVector.
*/
/cv_iv[/arraytype]  { {cvi} Map array2intvector } def

/**
* BeginDocumentation:
* Name: cv_dv - convert array of integers to a DoubleVector.
*/

/cv_dv[/arraytype] { {cvd} Map array2doublevector } def

/neg [/intvectortype] /neg_iv load def
/neg [/doublevectortype] /neg_dv load def
/inv_ /inv load def

/inv [/doublevectortype] /inv_dv load def
/inv [/doubletype] /inv_ load def

/add [/intvectortype /intvectortype] /add_iv_iv load def
/add [/integertype /intvectortype] /add_i_iv load def
/add [/intvectortype /integertype] {exch_ add_i_iv} def
/add [/doublevectortype /doublevectortype] /add_dv_dv load def
/add [/doubletype /doublevectortype] /add_d_dv load def
/add [/doublevectortype /doubletype] {exch_ add_d_dv} def
/sub [/intvectortype /intvectortype] /sub_iv_iv load def
/sub [/integertype /intvectortype] { neg_iv add_i_iv} def
/sub [/intvectortype /integertype] { neg_i exch_ add_i_iv} def
/sub [/doublevectortype /doublevectortype] /sub_dv_dv load def
/mul [/intvectortype /intvectortype] /mul_iv_iv load def
/mul [/integertype /intvectortype] /mul_i_iv load def
/mul [/intvectortype /integertype] {exch_ mul_i_iv} def
/mul [/doubletype /intvectortype]  /mul_d_iv load def
/mul [/intvectortype /doubletype ]  {exch_ mul_d_iv} def
/mul [/doubletype /doublevectortype] /mul_d_dv load def
/mul [/doublevectortype /doubletype] {exch_ mul_d_dv} def
/mul [/doublevectortype /doublevectortype] /mul_dv_dv load def
/div [/intvectortype /integertype] { exch_ { 1 index div_ii } Map exch_ ; } def
/div [/intvectortype /intvectortype] /div_iv_iv load def
/div [/doublevectortype /doublevectortype] /div_dv_dv load def
/div [/doubletype /doublevectortype] { inv_dv mul_d_dv } def
/div [/doublevectortype /doubletype] { inv_d exch_ mul_d_dv}  def

/add [/intvectortype /arraytype] {cv_iv add_iv_iv} def
/mul [/intvectortype /arraytype] {cv_iv mul_iv_iv} def
/sub [/intvectortype /arraytype] {cv_iv sub_iv_iv} def
/div [/intvectortype /arraytype] {cv_iv div_iv_iv} def

/add [/arraytype /intvectortype] {exch cv_iv add_iv_iv} def
/mul [/arraytype /intvectortype] {exch cv_iv mul_iv_iv} def
/dub [/arraytype /intvectortype] {exch cv_iv exch sub_iv_iv} def
/div [/arraytype /intvectortype] {exch cv_iv exch div_iv_iv} def

/add [/doublevectortype /arraytype] {cv_dv add_dv_dv} def
/mul [/doublevectortype /arraytype] {cv_dv mul_dv_dv} def
/sub [/doublevectortype /arraytype] {cv_dv sub_dv_dv} def
/div [/doublevectortype /arraytype] {cv_dv div_dv_dv} def

/add [/arraytype /doublevectortype] {exch cv_dv add_dv_dv} def
/mul [/arraytype /doublevectortype] {exch cv_dv mul_dv_dv} def
/dub [/arraytype /doublevectortype] {exch cv_dv exch sub_dv_dv} def
/div [/arraytype /doublevectortype] {exch cv_dv exch div_dv_dv} def

/length [/doublevectortype] /length_dv load def
/length [/intvectortype] /length_iv load def
/size [/intvectortype] {dup length_iv} def
/size [/doublevectortype] {dup length_dv} def

/eq [/intvectortype /intvectortype]
{
  intvector2array exch intvector2array eq
} def

/eq [/doublevectortype /doublevectortype]
{
  doublevector2array exch doublevector2array eq
} def

/forall [/doublevectortype /proceduretype] /forall_dv load def
/forall [/intvectortype /proceduretype] /forall_iv load def

/Map [/doublevectortype /proceduretype] /Map_ load def
/Map [/intvectortype /proceduretype] /Map_ load def
 
/arrayload_ /arrayload load def

/arrayload [/arraytype] /arrayload_ load def
/arrayload [/intvectortype] {intvector2array arrayload_} def
/arrayload [/doublevectortype] {doublevector2array arrayload_} def

/get [/doublevectortype /integertype] /get_dv_i load def
/get [/doublevectortype /intvectortype] /get_dv_iv load def
/get [/intvectortype /integertype] /get_iv_i load def
/get [/intvectortype /intvectortype] /get_iv_iv load def
/get [/intvectortype /arraytype] {cv_iv get_iv_iv} def
/get [/doublevectortype /arraytype] {cv_iv get_dv_iv} def

/put  [/doublevectortype /integertype /doubletype] /put_dv_i_d load def
/put  [/intvectortype /integertype /integertype] /put_iv_i_i load def

/* BeginDocumentation
Name: zeros - Return a DoubleVector filled with zeros.
Synapsis: n zeros -> [. 0. 0. ... .]
Author: Marc-Oliver Gewaltig
FirstVersion: Dec. 4 2012
SeeAlso: ones, arange
*/
/zeros [/integertype] /zeros_dv load def

/* BeginDocumentation
Name: ones - Return a DoubleVector filled with ones.
Synapsis: n ones -> [. 1. 1. ... .]
Author: Marc-Oliver Gewaltig
FirstVersion: Dec. 4 2012
SeeAlso: zeros, arange
*/

/ones [/integertype] /ones_dv load def

/* BeginDocumentation
Name: arange - Return a Int/DoubleVector filled with a range of numbers.
Synapsis: [n] arange -> [ 1  ... 10 ]
          [a b] arange -> [a ... b]
          [a b s] arange -> [a a+s ...]
Description:
arange is identical to Range, except that the returned object is a DoubleVector or IntVector, depending on the type of the
range specification.

Author: Marc-Oliver Gewaltig
FirstVersion: Dec. 4 2012
SeeAlso: zeros, ones, Range
*/
/arange_ /arange load def
/arange [/arraytype] /arange_ load def

/getinterval [/intvectortype /integertype /integertype]
{
   2 arraystore arange 
   get_iv_iv 
} def 

/getinterval [/doublevectortype /integertype /integertype]
{
   2 arraystore arange 
   get_dv_iv 
} def 

/<. mark def
/<# mark def

/.> { ] cv_dv } bind def
/#> { ] cv_iv } bind def

/< mark def
/* BeginDocumentation
Name: <> - Construct an array or vector, depending on the element type.
Synopsis: < obj1 ... obj n > -> [obj1, ... , objn]
          < int1 ... intn >  -> <# int1 ... intn #>
          < double1 ... doublen > -> <. d1 ... dn .>
Description:
Create an array, intvector, or doublevector, depending on the type of the entered elements.
This constructor uses the type of the first element in the sequence to determine the target type. All other
elements will be converted.
FirstVersion: Dec 18 2012
Author: Marc-Oliver Gewaltig
*/ 
/> 
{
  counttomark arraystore exch ;
  dup 0 get type 
  switchbegin
  1 index /doubletype eq { pop cv_dv exit} case
  1 index /integertype eq { pop cv_iv exit} case
  { pop } switchdefault

} bind def


%----------------------------------------------------------------------------
/* Begin(LOESCHMISCH!)Documentation

Name:

Synopsis:

Description:

Parameters: In :
            Out:

Examples:

Diagnostics:

Bugs:

Author:

FirstVersion:

Remarks:

References:

Variants:

SeeAlso:

*/

%% NOTE: There must be a carriage return after the last line, i.e., here: