A categorical programming language
修订版 | dbe659ea06d7ace0bb1d85f756f3de54a249aa33 (tree) |
---|---|
时间 | 2022-07-02 12:06:13 |
作者 | Corbin <cds@corb...> |
Commiter | Corbin |
Logarithms for floats.
@@ -3,7 +3,7 @@ import math | ||
3 | 3 | from rpython.rlib.jit import isconstant, we_are_jitted |
4 | 4 | # from rpython.rlib.rbigint import rbigint |
5 | 5 | |
6 | -from cammylib.elements import B, F, L, N, R, T | |
6 | +from cammylib.elements import B, F, N, T | |
7 | 7 | |
8 | 8 | |
9 | 9 | class Arrow(object): |
@@ -316,17 +316,11 @@ FZero = makeConstantF(0.0) | ||
316 | 316 | FOne = makeConstantF(1.0) |
317 | 317 | FPi = makeConstantF(math.pi) |
318 | 318 | |
319 | -def sign(f): return abs(f) == f | |
320 | 319 | class FSign(Arrow): |
321 | 320 | _immutable_ = True |
322 | 321 | def compile(self, compiler): compiler.sign() |
323 | 322 | def types(self, cs): return cs.concrete("F"), cs.concrete("2") |
324 | 323 | |
325 | -def floor(f): | |
326 | - try: | |
327 | - return L(F(float(math.floor(f)))) | |
328 | - except (ValueError, OverflowError): | |
329 | - return R(T()) | |
330 | 324 | class FFloor(Arrow): |
331 | 325 | _immutable_ = True |
332 | 326 | def compile(self, compiler): compiler.floor() |
@@ -408,8 +402,6 @@ class FATan2(Arrow): | ||
408 | 402 | f = cs.concrete("F") |
409 | 403 | return cs.functor("pair", [f, f]), f |
410 | 404 | |
411 | -def sqrt(f): | |
412 | - return L(F(math.sqrt(f))) if sign(f) else R(T()) | |
413 | 405 | class FSqrt(Arrow): |
414 | 406 | _immutable_ = True |
415 | 407 | def compile(self, compiler): compiler.sqrt() |
@@ -417,6 +409,13 @@ class FSqrt(Arrow): | ||
417 | 409 | f = cs.concrete("F") |
418 | 410 | return f, cs.functor("sum", [f, cs.concrete("1")]) |
419 | 411 | |
412 | +class FLog1Plus(Arrow): | |
413 | + _immutable_ = True | |
414 | + def compile(self, compiler): compiler.log1p() | |
415 | + def types(self, cs): | |
416 | + f = cs.concrete("F") | |
417 | + return f, cs.functor("sum", [f, cs.concrete("1")]) | |
418 | + | |
420 | 419 | |
421 | 420 | class BuildProblem(Exception): |
422 | 421 | def __init__(self, message): |
@@ -458,6 +457,7 @@ unaryFunctors = { | ||
458 | 457 | "f-cos": FCos(), |
459 | 458 | "f-atan2": FATan2(), |
460 | 459 | "f-exp": FExp(), |
460 | + "f-log1p": FLog1Plus(), | |
461 | 461 | } |
462 | 462 | |
463 | 463 | def buildUnary(name): |
@@ -1,9 +1,9 @@ | ||
1 | -from math import atan2, cos, exp, sin | |
1 | +import math | |
2 | 2 | |
3 | 3 | from rpython.rlib.jit import JitDriver |
4 | 4 | from rpython.rlib.rvmprof import get_unique_id, register_code, register_code_object_class, vmprof_execute_code |
5 | 5 | |
6 | -from cammylib.arrows import add, floor, mul, recip, sign, sqrt | |
6 | +from cammylib.arrows import add, mul, recip | |
7 | 7 | from cammylib.elements import B, F, L, N, P, R, T, equal |
8 | 8 | |
9 | 9 | # A basic CAM, as in the original paper: |
@@ -44,6 +44,18 @@ def lessThan(term): | ||
44 | 44 | f2 = term.second().f() |
45 | 45 | return B(True) if f1 == -0.0 and f2 == 0.0 else B(f1 < f2) |
46 | 46 | |
47 | +def floor(f): | |
48 | + try: | |
49 | + return L(F(float(math.floor(f)))) | |
50 | + except (ValueError, OverflowError): | |
51 | + return R(T()) | |
52 | + | |
53 | +def sign(f): return abs(f) == f | |
54 | + | |
55 | +def sqrt(f): return L(F(math.sqrt(f))) if sign(f) else R(T()) | |
56 | + | |
57 | +def log1p(f): return L(F(math.log1p(f))) if f > -1.0 else R(T()) | |
58 | + | |
47 | 59 | termOps = [ |
48 | 60 | # Core term ops. |
49 | 61 | TermOp("fst", lambda term: term.first()), |
@@ -73,11 +85,12 @@ termOps = [ | ||
73 | 85 | TermOp("fAdd", lambda term: add(term.first().f(), term.second().f())), |
74 | 86 | TermOp("mul", lambda term: mul(term.first().f(), term.second().f())), |
75 | 87 | TermOp("sqrt", lambda term: sqrt(term.f())), |
76 | - TermOp("sin", lambda term: F(sin(term.f()))), | |
77 | - TermOp("cos", lambda term: F(cos(term.f()))), | |
88 | + TermOp("sin", lambda term: F(math.sin(term.f()))), | |
89 | + TermOp("cos", lambda term: F(math.cos(term.f()))), | |
78 | 90 | TermOp("atan2", |
79 | - lambda term: F(atan2(term.first().f(), term.second().f()))), | |
80 | - TermOp("exp", lambda term: F(exp(term.f()))), | |
91 | + lambda term: F(math.atan2(term.first().f(), term.second().f()))), | |
92 | + TermOp("exp", lambda term: F(math.exp(term.f()))), | |
93 | + TermOp("log1p", lambda term: log1p(term.f())), | |
81 | 94 | ] |
82 | 95 | print "CAM: Created %d term ops" % len(termOps) |
83 | 96 |
@@ -0,0 +1 @@ | ||
1 | +(comp (comp (comp (pair id (fun/const f-one)) f/sub) f-log1p) (case id (comp (comp f-zero f-recip) f-negate))) | |
\ No newline at end of file |
@@ -0,0 +1,4 @@ | ||
1 | +#!/bin/sh | |
2 | + | |
3 | +find hive -name \*.cammy | awk '{ split($0,a,"."); print substr(a[1],6) }' > tab.txt | |
4 | +rlwrap -b ' ()' -f tab.txt result-bin/bin/cammy repl hive/ |
@@ -1,24 +1,3 @@ | ||
1 | -* Idea for new subcommands | |
2 | - * cammy dissolve | |
3 | - * Takes no arguments, just hive and input expr | |
4 | - * Returns equivalent to input, but using as much of hive as possible | |
5 | - * Implementation strategy: build up hash-cons structure in memory | |
6 | - * Iterate over hive, adding each expression to hash-cons | |
7 | - * Also build up partial dissolution map from hash-cons nodes to hive paths | |
8 | - * In unlikely case of ambiguity, guess | |
9 | - * Later on, we can make an informed guess by looking at neighboring nodes | |
10 | - * implemented as cammy freeze | |
11 | - * cammy crystallize | |
12 | - * Again, just hive and input | |
13 | - * Returns equivalent to input, mostly dissolved, but top few nodes are | |
14 | - deliberately tracked or expanded | |
15 | - * Each expanded node has its trail appended | |
16 | - * A weave is generated, including documentation | |
17 | - * Output is ready to feed to pandoc | |
18 | - * Output is a "crystal grown from $EXPR"; it explains the algorithm | |
19 | - incrementally, piece-by-piece | |
20 | - * Still not real literate programming, but getting closer | |
21 | - * Should use same underlying tools as dissolve | |
22 | 1 | * REPL improvements |
23 | 2 | * allow mid-functor newlines |
24 | 3 | * : commands |
@@ -33,6 +12,9 @@ | ||
33 | 12 | * Okasaki-style red-black trees? |
34 | 13 | * Skew heaps for priority queues https://themonadreader.files.wordpress.com/2010/05/issue16.pdf |
35 | 14 | * Efficient maps keyed by N |
15 | + * Attempted to implement them, but ran into a problem: tree traversals on | |
16 | + CAM are not obvious | |
17 | + * Defunctionalization might work: can the tree traversal be linearized? | |
36 | 18 | * I know how to compile to cats! |
37 | 19 | * For cat of interest, make hive/cats/cat/id, hive/cats/cat/comp, etc. |
38 | 20 | * Then, we'll apply a stack of functors by just looking up each layer in the |