Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

https://github.com/luser-dr00g/inca

an APL-style array calculator/interpreter in C based on the J-incunabulum, extended to allow propagating specifications a+2+a<3, more functions and operators.
https://github.com/luser-dr00g/inca

Last synced: 3 months ago
JSON representation

an APL-style array calculator/interpreter in C based on the J-incunabulum, extended to allow propagating specifications a+2+a<3, more functions and operators.

Lists

README

        

newest (incomplete) version is code-named 'olmec'. See olmec/README.md .

inca
====

This document describes the interpreter implemented in inca.c,
or inca "1". A revised and expanded version is implemented in inca2.c,
and documented in README2.md and in
[the wiki page](https://github.com/luser-dr00g/inca/wiki).

A third rewrite has begun in inca3.c. Its documentation is (predictably)
named README3.md.

The newest (incomplete) version is code-named 'olmec'. See olmec/README.md .

The final two commits of inca.c illustrate the problem inherent in
the design. Add the new feature (user-function call without the ' or ''
function-call functions) broke the existing code in tea.sh
(the "use-case"). And so, the project was begun anew with a better design.

It may surprise or amuse readers to learn that even the earliest inca.c was not my first brush with APL. Some years ago I read a great deal of the J wiki and then could not get it to compile and completely forgot. A few years later, having issued a programming challenge and received a few J answers, I looked again and wrote two postscript programs to simulate what I thought was going on. https://gist.github.com/luser-dr00g/9382217 and https://gist.github.com/luser-dr00g/9502855

And some time later I stumbled upon some very old source code of mine which attempted (anticipated?) a similar arbitrary-dimensional system in C++. https://groups.google.com/d/topic/comp.lang.apl/3VNPOzcQMMI/discussion

Summary:
monadic functions: + id { size ~ iota < box # shape > unbox | abs ! not @ rev
dyadic function: + add { from ~ find < assign # reshape , cat ; rowcat - minus . time
   * pow % divide | mod & and ^ or = eq / compress \ expand
mon ops: / reduce (.-|/\+><)@ transpose dy op: . matrix product
variable ` (backtick) is set to result of the previous command. (was underscore)

An online version is available courtesy of Thomas Baruchel.
http://baruchel.hd.free.fr/apps/apl/inca/
which is awesome and even handles cut+paste.

The program is based on and directly derived from the J-incunabulum,
http://www.jsoftware.com/jwiki/Essays/Incunabulum
and extended to allow propagating specifications "a+2+a<3",
new functions minus,times,unbox. multi-digit integers.
identity element for monadic use of minus,times,cat.
Most extensions have been incorporated "ad-hoc", with
an attempt to maintain consistency of style, balanced
against a need (demand) for more commentary and more visible
type identifiers.

The name "inca" was chosen for its similarity to "incunabulum",
as well as its obvious (to me) decomposition "In C, A",
as well as the apparent similarity between array-structured data
and the ancient Incan data-storage device, the quipu.
http://en.wikipedia.org/wiki/Quipu

The file inca.c compiles for me with cygwin32 gcc.
The code does not consistently adhere to any particular
version of the C standard, and may fail to compile with -pedantic,
or any other options to enforce standards-conformance.

I first found the J incunabulum through this SO question:
http://stackoverflow.com/questions/13827096/how-can-i-compile-and-run-this-1989-written-c-program
And I've added links to various explanatory pages as comments to that question, and a bugfix
for the original. Here are the helpful links:
http://www.jsoftware.com/papers/AIOJ/AIOJ.htm
https://groups.google.com/d/msg/sayeret-lambda/Oxffk3aeUP4/QEuZocgVh5UJ
http://archive.vector.org.uk/trad/v094/hui094_85.pdf

Inca has been submitted for critique on comp.lang.c and and comp.lang.apl.
And *some* of the advice given has been followed. It has not been tested
with a 64-bit intptr_t. The code may make 32bit assumptions, although I've
tried to be careful not to do this. I may not have been completely succesful.
The basis of the interpreter is the ability to treat a pointer as an integer
and pack them in the same-sized fields. Additionally, it assumes that pointer
values may be distinguished from character values from their integer
representations. This assumption is not guaranteed by the standard, but
appears empirically to be true on my cygwin and ubuntu gnu linux testbeds.
The original code also assumed that these pointer values will be positive,
which is empirically *not* true on cygwin. Not sure about ubuntu, the code
was fixed to use abs(intptr) before the range::type comparison well before
it was ported.

Inca will also accept command-line arguments into the program. These are
available in the 'a' variable as a box-array of command-string arrays.
Also included with the distribution is the small lib.inca file which
accumulates a few functions that arose in postings to comp.lang.apl.
If inca is invoked thusly:

./inca `cat lib.inca`

Then the library can be executed by putting the box-array a in a box '<',
making it executeable '$', and executing it ';'.

;$1){(<:1);<:('fy-1)+'fy-2

Factorial function:

f<:;(y>1){(<:1);<:y.fy-1

In the run-length-encoded triangular matrix example, the rows were all the
same length, so rowcat has an easy time to combine rows. But here, the two
code sequences

:1
:('fy-1)+'fy-2

are different lengths. So we box them, so rowcat doesn't screw things up.
(FIXME: fix rowcat to pad unequal widths).

<:1
<:('fy-1)+'fy-2

rowcat them together `((...);...)`, select one using a boolean expression `(y>1){`, and execute
the resulting expression `;`.

And also *not* executing a command-string prints the string, so:

:Hello World!
Hello World!

Recalling the syntax for *executing* code from the command-line.

;$ 1
{ size 1 1 1 => 3
~ iota ~9 => 0 1 2 3 4 5 6 7 8
< box <1 1 1 => <1 1 1 (bad example)
# shape #~9 => 9
> unbox ><1 1 1 => 1 1 1
| absolute |-12 => 12
! not !0 1 0 => 1 0 1
@ reverse @~9 => 8 7 6 5 4 3 2 1 0
: yield array of remaining command string
; execute command string array
$ convert array to command-string type
'w call function w with y as right arg
function may be a variable containing code (with colon :), eg. square
s<:y.y
's6
36
or a parenthesized expression, without colon :
'(y.y)6
36

dyadic functions d AdW

+ plus
{ from 2 3{@~9 => 6 5
~ find 6 5~@~9 => 2 3
< assign if a is a var (not really a function, but an interpreter action)
# reshape
, cat
; rowcat
- minus (monadic: a=0)
. times (monadic: a=1)
* power (monadic: a=2) <-- this will be e with floating-point
% divide (monadic: a=1) <-- this will make more sense with floating-point
| modulus (reverse of C: w%a, divisor on the right)
& and
^ or
= equals?
! not-equal?
: match
< less-than (if a is not a var, see assign above)
/ compress
\ expand
"w call function w with x as left arg and y as right arg
function may be a variable containing code (with colon :), eg x+1-y
f<:x+1-y
3"f2
2
or a parenthesized expression, without colon :
3"(x+1-y)2
2

monadic operators

/ reduce f/W => w0 f (w1 f (w2 f ( ... wn-2 f wn-1)))
\ scan f\W => (w0 f w1), ((w0 f w1) f w2), ... ) f wn-2) f wn-1)
@ transpose .@ identity transpose
-@ vertical transpose
|@ horizontal transpose
\@ y=x transpose
/@ y=-x transpose
+@ horz then vert
>@ horz then y=x
<@ horz then y=-x

dyadic operator

. matrix product Af.gW => f/Ag\@W
( @ for the left function designates "jot-dot", a null-scan over the matrix product )
eg. plus over times: +..
plus over plus: +.+
addition table: @.+
multiplication table: @..

over multidigit numbers and variables

`
(backtick), and [a-z]
`
(backtick) is set to the result of the previous line. (was underscore)

The interpreter also implements a non-greedy "cat" for
number vectors separated by spaces. Hence `1 2 3+~3` => `1 3 5`
where `~` is the zero-based iota. Spaces must only be used between
numbers. You may not pad operators with extra space or it will be
misinterpreted.

If the length of the command string exceeds 998 characters,
the behavior is undefined.

If array operands have incompatible sizes, the behavior
is undefined.

Example sessions:

monadic functions.

josh@Z1 ~/inca
$ !.
./inca
+5

5
{1 2 3
1
3
~9
9
0 1 2 3 4 5 6 7 8
~0
0

<12

<
12
#1 2 3;4 5 6
2
2 3
|-25

25
!4

0
!0

1
\@1 2 3;4 5 6;7 8 9;10 11 12
3 4
1 4 7 10
2 5 8 11
3 6 9 12
\@4 3#1+~12
3 4
1 4 7 10
2 5 8 11
3 6 9 12
@`
3 4
12 9 6 3
11 8 5 2
10 7 4 1

josh@Z1 ~/inca
$

Example session: dyadic functions and operators.
(output has been augmented with a type-specifier then colon : then dims)

$ ./inca
2 3+7 6
0:2
9 9
1{52 53 54
0:
53
5~4+~9
0:
1
4+~9
0:9
4 5 6 7 8 9 10 11 12
a<10
0:
10
b+a+b<6
0:
22
b
0:
6
~64
0:64
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
8 8#`
0:8 8
0 1 2 3 4 5 6 7
8 9 10 11 12 13 14 15
16 17 18 19 20 21 22 23
24 25 26 27 28 29 30 31
32 33 34 35 36 37 38 39
40 41 42 43 44 45 46 47
48 49 50 51 52 53 54 55
56 57 58 59 60 61 62 63
`,~9
0:73
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 0 1 2 3 4 5 6 7 8
12 6#`
0:12 6
0 1 2 3 4 5
6 7 8 9 10 11
12 13 14 15 16 17
18 19 20 21 22 23
24 25 26 27 28 29
30 31 32 33 34 35
36 37 38 39 40 41
42 43 44 45 46 47
48 49 50 51 52 53
54 55 56 57 58 59
60 61 62 63 0 1
2 3 4 5 6 7
5.-2
0:
-10
2*3
0:
8
3*2
0:
9
*3
0:
8
**3
0:
256
2*2*3
0:
256
+/~9
0:
36
./~9
0:
0
./1+~9
0:
362880
./1+~4
0:
24
1.2.3.4
0:
24
1 2 3 4+..5 6 7 8
0:
70
1.5
0:
5
`+2.6
0:
17
`+3.7
0:
38
`+4.8
0:
70

Example session: general transpose operator.

$ ./inca
3 4#~12
0:3 4
0 1 2 3
4 5 6 7
8 9 10 11
>@`
0:4 3
8 4 0
9 5 1
10 6 2
11 7 3
\@`
0:3 4
8 9 10 11
4 5 6 7
0 1 2 3
-@`
0:3 4
0 1 2 3
4 5 6 7
8 9 10 11
<@`
0:4 3
3 7 11
2 6 10
1 5 9
0 4 8
/@`
0:3 4
8 9 10 11
4 5 6 7
0 1 2 3
-@`
0:3 4
0 1 2 3
4 5 6 7
8 9 10 11
+@`
0:3 4
11 10 9 8
7 6 5 4
3 2 1 0
|@`
0:3 4
8 9 10 11
4 5 6 7
0 1 2 3
-@`
0:3 4
0 1 2 3
4 5 6 7
8 9 10 11
.@`
0:3 4
0 1 2 3
4 5 6 7
8 9 10 11