├── .github └── workflows │ └── c-cpp.yml ├── .gitignore ├── A.S ├── Doxyfile ├── README.md ├── a.c ├── a.h ├── b.c ├── b.h ├── c.h ├── d ├── attic.c ├── card.pdf ├── cosmo.md ├── crypto.pdf ├── ec25519-optimizations.pdf ├── elf.md ├── howto.md ├── index.html ├── jucs05.pdf ├── mxcsr.md ├── rv-calling-convention.pdf ├── rvgreen-patterson.pdf └── sidenotes.md ├── ec ├── .gitignore ├── e.c ├── e.go ├── e.h ├── h.h ├── index.html ├── makefile ├── sha.c ├── sha.h ├── t.c ├── t.h ├── wop └── wop2 ├── h.c ├── h.h ├── l ├── ._l.c ├── ._l.h ├── l.c ├── l.h └── t.c ├── m.c ├── m.h ├── m ├── .gitignore ├── BENCH.md ├── README.md ├── RESULTS.md ├── cfrac │ ├── README.md │ ├── asm16bit.h │ ├── atop.c │ ├── atop.o │ ├── cfrac │ ├── cfrac.c │ ├── cfrac.o │ ├── errorp.c │ ├── errorp.o │ ├── getopt.c │ ├── getopt.h │ ├── getopt.o │ ├── itop.c │ ├── itop.o │ ├── ltop.c │ ├── ltop.o │ ├── pabs.c │ ├── pabs.o │ ├── padd.c │ ├── padd.o │ ├── pcfrac.c │ ├── pcfrac.o │ ├── pcmp.c │ ├── pcmp.o │ ├── pconst.c │ ├── pconst.o │ ├── pcvt.h │ ├── pdefs.h │ ├── pdivmod.c │ ├── pdivmod.o │ ├── pfactor.c.bak │ ├── pfactor.h │ ├── pfactor.o │ ├── pfloat.c │ ├── pfloat.o │ ├── pgcd.c │ ├── pgcd.o │ ├── phalf.c │ ├── phalf.o │ ├── picmp.c │ ├── picmp.o │ ├── pidiv.c │ ├── pidiv.o │ ├── pimod.c │ ├── pimod.o │ ├── pio.c │ ├── pio.o │ ├── pmul.c │ ├── pmul.o │ ├── pneg.c │ ├── pneg.o │ ├── podd.c │ ├── podd.o │ ├── pops.c │ ├── pops.o │ ├── ppowmod.c │ ├── ppowmod.o │ ├── precision.h │ ├── primes.c │ ├── primes.h │ ├── primes.o │ ├── psqrt.c │ ├── psqrt.o │ ├── psub.c │ ├── psub.o │ ├── ptoa.c │ ├── ptoa.o │ ├── ptob.c │ ├── ptob.o │ ├── ptou.c │ ├── ptou.o │ ├── seive.h │ ├── utop.c │ └── utop.o ├── m.c ├── m.h ├── makefile ├── mk ├── stress.c └── t.c ├── makefile ├── mk ├── p.c ├── r.c ├── t.b ├── t.c ├── t ├── dat │ ├── t.fio.b │ ├── t.lldb │ └── t.utf.b ├── lib │ ├── unity.c │ ├── unity.h │ └── unity_internals.h ├── t.c ├── t.env.c ├── t.err.c ├── t.fio.c ├── t.h ├── t.hsh.c ├── t.mem.c ├── t.prs.c ├── t.sym.c └── t.utf.c ├── tiso.b └── u.c /.github/workflows/c-cpp.yml: -------------------------------------------------------------------------------- 1 | name: C CI 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build-lin: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: make 17 | run: make l 18 | 19 | build-osx: 20 | 21 | runs-on: macos-latest 22 | 23 | steps: 24 | - uses: actions/checkout@v2 25 | - name: make 26 | run: make l 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.dSYM 2 | *DS_Store 3 | b 4 | tmp 5 | *.profraw 6 | t/obj 7 | w 8 | ec/e32 9 | ec/e64 10 | *.bin 11 | c 12 | -------------------------------------------------------------------------------- /A.S: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | #define __NR_read 0 5 | #define __NR_write 1 6 | #define __NR_open 2 7 | #define __NR_close 3 8 | #define __NR_fstat 5 9 | #define __NR_mmap 9 10 | #define __NR_munmap 11 11 | #define __NR_exit 60 12 | */ 13 | 14 | #define S(n) .globl n;n:;mov %rcx,%r10;mov $__NR_##n,%rax;syscall;ret; 15 | S(read)S(write)S(open)S(close)S(fstat)S(mmap)S(munmap)S(exit) 16 | 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## a `b` compiler 2 | 3 | 4 | `bcc` is an interactive compiler of a language called `b`. 5 | 6 | it produces compact and fast object code that uses very little stack. 7 | 8 | b aims to offer same types, ops and control as c. 9 | 10 | `t.b` and `t.c`: 11 | 12 | ``` 13 | run compile(ms) runsize 14 | b 230 .06 1K 15 | gcc-O1 320 60.00 3K 16 | gcc-O2 230 90.00 3K 17 | gcc-O9 230 200.00 8K 18 | ``` 19 | 20 | b syntax is more compact than c and has no precedence rules: 21 | 22 | ``` 23 | b : +-*%^&|<> = / \ $[c;t;f] 24 | c = +-*/^&|<> == << >> if(c)t;else f; 25 | ``` 26 | 27 | argtypes for `x,y,z` are declared, local types and result type are inferred. 28 | 29 | ### examples 30 | 31 | bsearch: 32 | 33 | ``` 34 | b: b[Ii]{h:#x;l:0;W(h>l)$[y>x[i:/l+h];l:i+1;h:i];l} 35 | c: I b(I*x,I y){I h=x[-1],i,l=0;while(h>l)if(y>x[i=l+h>>1])l=i+1;else h=i;R l;} 36 | ``` 37 | 38 | ackermann: 39 | 40 | ``` 41 | b: a[ii]$[x;a[-x;$[y;a[x;-y];1]];+y] 42 | c: I a(I x,I y){R x?a(x-1,y?a(x,y-1):1):y+1;} 43 | 44 | b 85ff741c85f6740e83ee0157e8efffffff5f8bf0eb05be0100000083ef01ebe08d4601c3 (36) 45 | clang -Os 534889f04885ff7423488d5fff4885c0740d48ffc84889c6e8e3ffffffeb05b8010000004889df4885db75dd48ffc05bc3 (49) 46 | ``` 47 | 48 | that is: 49 | 50 | ``` 51 | 0: 85 ff test edi,edi 52 | 2: 74 1c je 0x20 53 | 4: 85 f6 test esi,esi 54 | 6: 74 0e je 0x16 55 | 8: 83 ee 01 sub esi,1 56 | b: 57 push rdi 57 | c: e8 ef ff ff ff call 0 58 | 11: 5f pop rdi 59 | 12: 8b f0 mov esi,eax 60 | 14: eb 05 jmp 0x1b 61 | 16: be 01 00 00 00 mov esi,1 62 | 1b: 83 ef 01 sub edi,1 63 | 1e: eb e0 jmp 0 64 | 20: 8d 46 01 lea eax,[rsi+1] 65 | 23: c3 ret 66 | 67 | 564: 53 push %rbx 68 | 565: 48 89 f0 mov %rsi,%rax 69 | 568: 48 85 ff test %rdi,%rdi 70 | 56b: 74 23 je 590 71 | 56d: 48 8d 5f ff lea -0x1(%rdi),%rbx 72 | 571: 48 85 c0 test %rax,%rax 73 | 574: 74 0d je 583 74 | 576: 48 ff c8 dec %rax 75 | 579: 48 89 c6 mov %rax,%rsi 76 | 57c: e8 e3 ff ff ff callq 564 77 | 581: eb 05 jmp 588 78 | 583: b8 01 00 00 00 mov $0x1,%eax 79 | 588: 48 89 df mov %rbx,%rdi 80 | 58b: 48 85 db test %rbx,%rbx 81 | 58e: 75 dd jne 56d 82 | 590: 48 ff c0 inc %rax 83 | 593: 5b pop %rbx 84 | 594: c3 retq 85 | ``` 86 | 87 | ### usage 88 | 89 | 90 | 91 | 92 | ### code 93 | 94 | `b` uses an idiomatic dialect of ansi c. 95 | 96 | `c.h` dialect 97 | `a.h` accessors 98 | 99 | `a.S` kernel interface 100 | `a.c` runtime 101 | `m.c` malloc 102 | `p.c` parser 103 | `b.c` compiler 104 | `h.c` hash table 105 | `u.c` unicode 106 | 107 | `d` reference 108 | `t` tests 109 | `m` bench 110 | 111 | `p()` parse 112 | `d()` to register (constant or global) 113 | `e()` to register 114 | `f()` force 115 | 116 | `ex()` run 117 | 118 | ### build 119 | 120 | llvm, gcc, tcc: 121 | ``` 122 | make l g t 123 | make test 124 | ``` 125 | 126 | ### ports 127 | 128 | for riscv, arm, xtensa we need: 129 | 130 | ``` 131 | jmp() tst() cmp() o2() 132 | ret() cll() psh() pop() 133 | ``` 134 | 135 | ### faq 136 | 137 | there is no license. use at our own risk. 138 | 139 | the [original](http://kparc.com/b) software was apparently meant as a friendly joke. 140 | 141 | the name of this project is an insider pun and stands for `blind carbon copy`. 142 | 143 | this work is prompted by a formidable anonymous [effort](https://docs.google.com/document/d/1W83ME5JecI2hd5hAUqQ1BVF32wtCel8zxb7WPq-D4f8/mobilebasic) of the [following](http://yiyus.info/cv.pdf) origin. 144 | 145 | `/:~` 146 | -------------------------------------------------------------------------------- /a.c: -------------------------------------------------------------------------------- 1 | #ifndef COSMO 2 | #include 3 | #include 4 | #endif 5 | 6 | #include"a.h"// read/write mmap/munmap printf/scanf malloc/free 7 | #include"m.h" 8 | #include"h.h" 9 | 10 | //S mmap();I open(),close(),fstat(),munmap();J read(),write();V exit(); 11 | V w2(S s){write(2,s,sl((char*)s));}ZS r2(S s){ZC b[256];I i;w2(s);i=read(0,b,256);b[i-1]=0;R 13==b[i-2]?b[i-2]=0,b:b;} 12 | K dmp(S s,S x,J n){I d=open((V*)s,O_RDWR|O_CREAT|O_TRUNC,S_IRWXU);Qs(0>d,(S)s)write(d,x,n);R close(d),0;} 13 | 14 | //! printf/scanf (almost:) 15 | ZC b[24];ZS ng(S s){R*--s='-',s;} 16 | ZS pu(S s,J i){J j;do*--s='0'+i-10*(j=i/10);W(i=j);R s;} 17 | ZF x(I n){F e=1;N(n,e*=10)R e;} //P(NI==f||0>(j|k),nf) 18 | S pi(J i){R 0>i?ng(pi(-i)):pu(b+23,i);} //!< current state of the art is ryu 19 | S pf(F f){P(0>f,ng(pf(-f)))P(!f,(S)"0.0")I n=6;W(f<1e6)--n,f*=10;W(f>=1e7)++n,f/=10;S p=n?p=pi(n),*--p='e',p:b+23;n=f+.5;W(99>4;s[i]="0W"[9>=8);R s;} 21 | F fp(S p,I n){P('-'==*p,-fp(p+1,n-1))I l=scn(p,'e',n),m=scn(p,'.',l),f=lf?k/x(-f):k*x(f);} 22 | 23 | //! repl daz ftz \wtfvl: \w wssize \t[:n] timer[ntimes] \f funs \v vars \l loadfile \-var release 24 | 25 | V dis(K,I);K es();ZK K0;K k0(){R r1(K0);} 26 | #ifndef SYMS 27 | K GGG[26]; //!< global namespace 28 | K vf(I f){K r=kS(0);N(26,K x=GGG[i];if(NL-x)if(f^!FN(x))r=j2(r,ks(i)))R r;} 29 | #else 30 | HT GT; //!< global namespace 31 | K vf(I f){AB("nyi");}//K vf(I f){K x,r=kS(0);N(26,x=GGG[i];if(NL-x){K y=nm(x);O("vf y %.*s xt %d \n",yn,(S)y,yt);if(f^!FN(*GG(x)))r=j2(r,ks(i));})R r;} 32 | #endif 33 | 34 | K Li(K x,I i){R!xt||KS>16&(J)x)));Y0(write(2,(V*)y,yn)),nl();R x;}K1(pr){if(NL-x)r0(o(x));R x;} 61 | ZS1(ld){J n;s=(S)mf(s,&n);Q((K)s)S t=s,u;I a,d=0;W(u=sc(t,10),t=0){if(u)*u++=0;a=t[1]?0:(*t=='/')-(*t=='\\');if(!d&&!a&&'/'-*t)Q(pr(es(t)))d+=a,t=u;if(!t)break;}if(n)munmap(s,n);R NL;} 62 | ZS1(tm){S t=sc(s,' ');Qs(!t,s)*t=0;I n=':'-*s++?1:10u>*s-'0'?ip(s,t-s):(J)es(s);K x='\\'-*++t?ps(t):0,r;F a=ms();N(n,Q(r=x?ex(x):ld(t+3))r0(r))if(x)r0(x);R ki(ms()-a);} 63 | ZS1(rg);S1(es){K x;P('\\'-*s,!*s?NL:(x=ps(s))&&NL-x&&QQ-Ax?X0(ex(x)):x)if(!*++s||'\\'==*s)exit(0);R!s[1]?'w'==*s?ki(ws()):sc("vf",*s)?vf('f'==*s):qs(s):'t'==*s?tm(s+1):'-'==*s?rg(s+1):'l'==*s?ld(s+2):qs(s);} 64 | 65 | #ifndef SYMS 66 | ZS1(rg){UI i=*s-'a';Qs(26k)Qs((y=GG(x))&&A(z=*y),"nyi")P(!zr,gset(b,NL))R qs("0>52?KF:15&_j>>48;}) 95 | #define FN(x) (!Ax&&!xt) 96 | #define I(x) (I)(J)(x) //(-1UL>>16&(J)(x)) 97 | #define Q(x) P(QQ==A(x),x) //#define Q(c,i) P(c,qi(i)) //error index(nyi,rank,length,type,..) 98 | #define Qs(c,s) P(c,qs((S)s)) //error string 99 | #define N1(n,a...) {I i=0,_n=(n);do{a;}while(++i<_n);} 100 | 101 | // access x y z r 102 | #define Ax A(x) 103 | #define xi I(x) 104 | #define xj (J)(x) 105 | #define xf *(F*)&x 106 | #define xm xC[-8] //mem 107 | #define xr xC[-7] //ref 108 | #define xu xC[-6] 109 | #define xt xC[-5] 110 | #define xn xI[-1] 111 | #define xx xK[0] 112 | #define xy xK[1] 113 | #define xz xK[2] 114 | #define xxu ptr(xx)[-6] 115 | #define xyu ptr(xy)[-6] 116 | #define xI ((I*)x) 117 | #define xF ((F*)x) 118 | #define xK ((K*)x) 119 | #define Xc ((S)x)[i] 120 | #define Xi xI[i] 121 | #define Xj xJ[i] 122 | #define Xx xK[i] 123 | #define X0(e) ({typeof(e)_e=(e);r0(x);_e;}) 124 | #define Ay A(y) 125 | #define yi I(y) 126 | #define yj (J)(y) 127 | #define yr yC[-7] //ref 128 | #define yu yC[-6] 129 | #define yt yC[-5] 130 | #define yn yI[-1] 131 | #define yx yK[0] 132 | #define yy yK[1] 133 | #define yI ((I*)y) 134 | #define yK ((K*)y) 135 | #define yF ((F*)y) 136 | #define Yc ((S)y)[i] 137 | #define Yi yI[i] 138 | #define Yx yK[i] 139 | #define Y0(e) ({typeof(e)_e=(e);r0(y);_e;}) 140 | #define Az A(z) 141 | #define zi I(z) 142 | #define zr zC[-7] //ref 143 | #define zu zC[-6] 144 | #define zt zC[-5] 145 | #define zn zI[-1] 146 | #define zx zK[0] 147 | #define zy zK[1] 148 | #define zI ((I*)z) 149 | #define zF ((F*)z) 150 | #define zK ((K*)z) 151 | #define Zc ((S)z)[i] 152 | #define Zi zI[i] 153 | #define Zx zK[i] 154 | #define Z0(e) ({typeof(e)_e=(e);r0(z);_e;}) 155 | #define Ar T(r) 156 | #define ri I(r) 157 | #define rr rC[-7] 158 | #define rt rC[-5] 159 | #define rn rI[-1] 160 | #define rI ((I*)r) 161 | #define rK ((K*)r) 162 | #define rx rK[0] 163 | #define ry rK[1] 164 | #define rz rK[2] 165 | #define Rc ((S)r)[i] 166 | #define Ri rI[i] 167 | #define Rx rK[i] 168 | #define R0(e) ({typeof(e)_e=(e);r0(r);_e;}) 169 | 170 | #define xJ ((J*)x) 171 | #define zJ ((J*)z) 172 | 173 | Z_ K1(k1){K r=kK(1);R rx=x,r;}Z_ K2(k2){K r=kK(2);R rx=x,ry=y,r;}Z_ K3(k3){K r=kK(3);R rx=x,ry=y,rz=z,r;}Z_ K3(j3){R j2(j2(x,y),z);}Z_ K2(jk){R j2(x,k1(y));}Z_ K cj(C c,K y){R j2(c1(c),y);}Z_ K u(I u,K x){R xu=u,x;} 174 | 175 | #if 0 176 | //! TODO malloc override 177 | #include"m.h" 178 | #define bmalloc aw_malloc 179 | #define bcalloc aw_calloc 180 | #define brealloc aw_realloc 181 | #define bfree aw_free 182 | #else 183 | /* 184 | #define bmalloc malloc 185 | #define bcalloc calloc 186 | #define brealloc realloc 187 | #define bfree free 188 | */ 189 | #endif 190 | 191 | 192 | //:~ 193 | -------------------------------------------------------------------------------- /b.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include"a.h" 3 | 4 | #define k2c(o,x) k2(kc(o),x) 5 | 6 | #define BLIM 16 //L 20 | #define D st->D 21 | #define T st->T 22 | #define M st->M 23 | #define sN st->N 24 | #define sA st->A 25 | #define Pt st->Pt 26 | #define Pn st->Pn 27 | #define D0 D[0] 28 | #define D1 D[1] 29 | #define Di D[i] 30 | #define Li L[i] 31 | #define Ti T[i] 32 | 33 | //:~ -------------------------------------------------------------------------------- /c.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef COSMO 3 | #include 4 | #include 5 | #endif 6 | 7 | #ifndef QUIET 8 | #define O printf 9 | #else 10 | #define O 11 | #endif 12 | 13 | #define ptr(x) (*(S*)&x) 14 | #define xC ptr(x) 15 | #define yC ptr(y) 16 | #define zC ptr(z) 17 | #define fC ptr(f) 18 | #define rC ptr(r) 19 | 20 | typedef unsigned long long K,UJ;typedef unsigned char C,*S;typedef int I,CP;typedef long long J;typedef double F;typedef void V;typedef unsigned int UI; 21 | 22 | enum UCL{UQ,Ul,Ug,Uc,Um,Ua};//!< QQ Āɏ Ая Αω ∀⋿ ⌀⍺ (err, lat, cyr, gre, mth, apl) 23 | #define UR(cp,s,l) (l>cp-s) //!< unicode range: codepoint, range start, range length+1 24 | #define UC(x) (9082_b?_a:_b;}) 36 | 37 | #define ZI static I 38 | #define ZC static C 39 | #define ZS static S 40 | #define ZJ static J 41 | #define ZF static F 42 | #define ZK static K 43 | #define ZV static V 44 | 45 | #define Z_ static inline 46 | 47 | #ifdef SIGHANDLER 48 | #include 49 | #define AB(s) (w2((S)"AB: "),w2((S)s),raise(SIGABRT),(K)0L) //abort string 50 | #else 51 | #define AB(s) (w2((S)"AB: "),w2((S)s),nl(),exit(1),(K)0L) //abort string 52 | #endif 53 | 54 | #define ZV1(f) ZV f(K x) 55 | #define S1(f) K f(S s) 56 | #define ZS1(f) ZK f(S s) 57 | #define ZK1(f) ZK f(K x) 58 | #define ZK2(f) ZK f(K x,K y) 59 | #define ZK3(f) ZK f(K x,K y,K z) 60 | #define V1(f) V f(K x) 61 | #define I1(f) I f(K x) 62 | #define K1(f) K f(K x) 63 | #define K2(f) K f(K x,K y) 64 | #define K3(f) K f(K x,K y,K z) 65 | 66 | //#ifndef __APPLE__ 67 | #if 0 68 | #define BASE 0x700000 69 | #else 70 | #define BASE 0x70000000L 71 | #endif 72 | 73 | #if (__x86_64__||i386)&&!__TINYC__ 74 | Z_ I clzl(I n){R 60-__builtin_clzl(n);}Z_ V csr(){R;asm("movl $0x9fc0,-4(%rsp);ldmxcsr -4(%rsp);");}//V csr(){volatile I mxcsr=0x9fc0;asm("ldmxcsr %0":"=m"(mxcsr));} 75 | #else 76 | Z_ I clzl(I n){I i=0;W(n)n/=2,++i;R i-4;}Z_ V csr(){R;} //>n; 3 | //#define pw2(n) __(1)__(2)__(4)__(8)__(16) 4 | //ZI B[32]={0,9,1,10,13,21,2,29,11,14,16,18,22,25,3,30,8,12,20,28,15,17,24,7,19,27,23,6,26,5,4,31}; 5 | //static inline I clzl3(UI v){pw2(v);R-3+B[(UI)(v*0x07C4ACDDU)>>27];} 6 | ////static inline UI npow2(UI v){v--;pw2(v)R++v;} 7 | ////#define PW2(x) (x&&!(x&x-1)) //!< is integer n x power of 2 8 | //N(1024,O("clzl(%d+7=%d) = (%d %d %d)\n",i,i+7,clzl(i+7),clzl2(i+7),bkt(i+7))) 9 | 10 | //I main(){asm("movl $0x9fc0,-4(%rsp);ldmxcsr -4(%rsp);lea 8(%rsp),%rdi;jmp _km");} 11 | //V csr(){R;asm("movl $0x9fc0,-4(%rsp);ldmxcsr -4(%rsp);");} 12 | 13 | //K qi(I i){R qs((S[]){"nyi","rank","length","type","domain","value"}[i]);} //!< \fixme humans prefer this to segv 14 | 15 | //! \todo format c: 16 | //ZK1(rd1){QC(x)x=jc(x,0);I d=open(x,0);Qs(0>d,x)J b[16];fstat(d,b);R x=X0(511+ma(0,0,0,b[6]+4096)),xm=-1,xt=KC,ma(0,d,x,xn=b[6]),W+=xn,x;}(W-=xn,mu(x-511,xn+4096)) 17 | //ZK2(wr1){QC(x)x=jc(x,0);QC(y)unlink(x);I d=open(x,0102,0666);Qs(0>d,x)ftruncate(d,yn);R x=X0(ma(1,d,0,yn)),dsn(x,y,yn),mu(x,yn),Y0(NL);} 18 | //K1(rd0){R Ss(0,rd1(x));} //{-1_'(0,1+&x=y)_y} K2(wr0){R wr1(x,sS(0,y));} //{,/x,'y} 19 | //ZI rand(){ZJ j0=-314159;R j0=4294957665L*j0+(j0>>32);} 20 | 21 | //! b.c prototype code 22 | //asm("push %rbp;push %rbx");asm("pop %rbx;pop %rbp");MIN(y^(x^y)&x-y>>63)I low()__builtin_ctz(~i&-2);}V qq(I o,I r,I x,I y){oc(":+-*%? c"[o]),oc('0'+r),oc('0'+x),oi(y);} 23 | /* K1(ev){S s=xy;ZF M[16];ZJ A[999],*a=A+999,L[16],c,f;I b(){f&=7;R!f||(4>f?c==f-2:c!=f-6);} 24 | #define G(n,T,t) C(n,((t*)L[15&r])[l(*s++)]=T[r>>4])C(n+1,T[r>>4]=((t*)L[15&r])[l(*s++)]) 25 | J l(I c){R 16>c?L[c]:32>c?(I)xJ[2+c-16]:124>c?(J)G[c-'a']:c-128;} J j2(I i,J x,J y){R!i?y:1==i?x+y:2==i?x-y:3==i?x*y:4==i?x>>y:5==i?x<c?M[c]:32>c? xF[2+c-16]:*(F*)(G+c-'a');} F f2(I i,F x,F y){R!i?y:1==i?x+y:2==i?x-y:3==i?x*y:x/y;} 27 | W(*s){f=*s++;I r=*s++;$(1==f,$(25f,L[r]=b())$(24>f,s+=b()?(signed char)r:0)$(32>f,s+=3;s+=b()?*((I*)s-1):0)$(64>f, 28 | S(31&f,C(0,*--a=L[r])C(1,L[r]=*a++)C(2,c=L[r]?1:0)C(3,oi(L[r])) C(6,J j=l(*s++);c=L[r]j)G(12,L,I)G(14,L,J),L[r>>4]=j2(f-48,L[15&r],l(*s++)))) 29 | S(31&f,C(0,*--a=M[r])C(1,M[r]=*a++)C(2,c=M[r]?1:0)C(3,of(M[r])) C(4,M[r]=L[*s++])C(6,F f=m(*s++);c=M[r]f) ,M[r>>4]=f2(f-80,M[15&r],m(*s++)))} 30 | R x=xy,KS*s||4>c?2:15>*s?5:3;}I j(I t){R KF==t?32:0;}C B=2,RET=0,JJ[]={16,17,18,19,24,21,22,23}; 31 | K cc(I o,I r){R c2(8+o,r);}K Jj(K x,I n){R c5(8+x[xn],n-3);}K cll(I c){R c2(1,c);}K psh(I t,I r){R c2(32+j(t),r);}K pop(I t,I r){R c2(33+j(t),r);}K tst(I t,I r){R c2(34+j(t),r);} 32 | K sh(I t,I r){R c2(35+j(t),r);}K cv(I x,I y){R c3(36+32,x,y);}K cm(I t,I x,I y){R c3(38+j(t),x,y);}K o2(I t,I o,I r,I x,I y){R c3(48+o+j(t),16*r+x,y);}*/ 33 | 34 | //! original x64 spec 35 | // :+-*% ^&|<=> x64 JJ Jj o2 cc tst RET cll psh pop acdbsbsd89.. o[m[s|d]] c3 eb+1 e8+4 e9+4 [f2/66/4*][0f] 5* 7*+1 b*+4 0f8*+4 03 23 2b 3b (6b 83) 89 8b .. 36 | -------------------------------------------------------------------------------- /d/card.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/d/card.pdf -------------------------------------------------------------------------------- /d/cosmo.md: -------------------------------------------------------------------------------- 1 | cosmopolitan build 2 | 3 | ``` 4 | mkdir c && cd c 5 | wget https://justine.lol/cosmopolitan/cosmopolitan.zip && unzip cosmopolitan.zip && cd .. 6 | export COSMO_DIR=c 7 | make c 8 | ``` 9 | -------------------------------------------------------------------------------- /d/crypto.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/d/crypto.pdf -------------------------------------------------------------------------------- /d/ec25519-optimizations.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/d/ec25519-optimizations.pdf -------------------------------------------------------------------------------- /d/elf.md: -------------------------------------------------------------------------------- 1 | how to elf with style: 2 | 3 | ``` 4 | $ nasm -f bin -o x x.S && chmod +x x && ./x; echo $? 5 | 1 6 | $ ls -l x 7 | -rwxr-xr-x 1 root root 127 Oct 30 17:23 x 8 | ``` 9 | 10 | that is: 11 | 12 | ``` 13 | BITS 64 14 | org 0x10000 15 | e: ; Elf64_Ehdr 16 | db 0x7F, "ELF", 2, 1, 1, 0 ; e_ident 17 | times 8 db 0 18 | dw 2 ; e_type ET_EXEC = 2 19 | dw 62 ; e_machine EM_X86_64 = 62 20 | dd 1 ; e_version EV_CURRENT = 1 21 | dq a ; e_entry 22 | dq p-$$ ; e_phoff 23 | dq 0 ; e_shoff 24 | dd 0 ; e_flags 25 | dw en ; e_ehsize 26 | dw pn ; e_phentsize 27 | dw 1 ; e_phnum 28 | dw 0 ; e_shentsize 29 | dw 0 ; e_shnum 30 | dw 0 ; e_shstrndx 31 | en equ $-e 32 | p: ; Elf64_Phdr 33 | dd 1 ; p_type 34 | dd 5 ; p_flags 35 | dq 0 ; p_offset 36 | dq $$ ; p_vaddr 37 | dq $$ ; p_paddr 38 | dq n ; p_filesz 39 | dq n ; p_memsz 40 | dq 0 ; p_align 41 | pn equ $-p 42 | a: 43 | mov dil, 1 44 | mov al, 60 45 | syscall 46 | n equ $-$$ 47 | ``` 48 | 49 | remarkable. -------------------------------------------------------------------------------- /d/howto.md: -------------------------------------------------------------------------------- 1 | ``` 2 | 1. kparc day starts with a pull followed by a hello 3 | 2. we commit often but we are reasonable 4 | 3. commit msgs are lowercase and usually begin with a verb in imperative mood 5 | 4. `blah` is not a verb except `[~]` meaning `zap that typo` 6 | 5. consider `git config pull.rebase true` 7 | 6. tabs and `\r\n` are evil, dangling space is not cool, indent is `0x20` 8 | 7. enjoy responsibly when you push to master 9 | 8. consider `make test` pre-commit hook 10 | 9. code comments are essential, kparc uses doxygen 11 | 10. kparc code is 99% reflection 1% keyboard 12 | 13 | reflogs are like so: 14 | 15 | [-] remove excess code 16 | [+] add quality code 17 | [~] fix an imperfection 18 | [!] request a peer review 19 | [=] land something cool 20 | [===] land something epic 21 | ``` 22 | -------------------------------------------------------------------------------- /d/jucs05.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/d/jucs05.pdf -------------------------------------------------------------------------------- /d/mxcsr.md: -------------------------------------------------------------------------------- 1 | ``` 2 | mxcsr 0x9fc0 3 | 4 | fz b 15 flush to zero 5 | rn b 13/14 down round to nearest 6 | pm b 12 precision mask 7 | um b 11 underflow mask 8 | om b 10 overflow mask 9 | zm b 9 divide by zero mask 10 | dm b 8 denormal mask 11 | im b 7 invalid operation mask 12 | daz b 6 denormals are zero 13 | ``` -------------------------------------------------------------------------------- /d/rv-calling-convention.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/d/rv-calling-convention.pdf -------------------------------------------------------------------------------- /d/rvgreen-patterson.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/d/rvgreen-patterson.pdf -------------------------------------------------------------------------------- /ec/.gitignore: -------------------------------------------------------------------------------- 1 | e 2 | e32 3 | e64 4 | t32 5 | t64 6 | *.so 7 | *.wasm 8 | e.html 9 | w.html 10 | w.js 11 | e.js 12 | -------------------------------------------------------------------------------- /ec/e.c: -------------------------------------------------------------------------------- 1 | #include"e.h" 2 | 3 | #include 4 | #include 5 | 6 | ZG min(I x,I y){R x>=8)}ZZ prp(S r){*r&=0xf8,RFC,r[31]|=0x40;}Z_ sel(S r,S x,S y,G c){X(Rg=-c&(Yg^Xg)^Xg)} 18 | Z_ nrm(S r){fp y;H c=(r[31]>>7)*19;RFC;RDc;c=19;N(31,c+=Rg;Yg=c;c>>=8)c+=((H)r[31])-128;y[31]=c;sel(r,y,r,(c>>15)&1);} 19 | Z_ mul(S r,S x,S y){V c=0;X(c>>=8;Nj(i+1,c+=Vx(j)*Vy(i-j))Nj(31-i,c+=Vx(i+1+j)*Vy(31-j)*38)Rg=c)RDCC} 20 | Z_ mlc(S r,S x,V y){V c=0;X(c>>=8;c+=y*VX;Rg=c)RFC;c>>=7;c*=19;RDc} 21 | ZG eql(S x,S y){G s=0;X(s|=Xg^Yg)s|=s>>4;s|=s>>2;s|=s>>1;R(s^1)&1;} 22 | Z_ sub(S r,S y,S x){SUB(VY,Vy(31))}Z_ neg(S r,S x){SUB(0,0)} 23 | Z_ add(S r,S x,S y){H c=0;X(c>>=8;c+=HX+HY;Rg=c)RFC;RDC} 24 | Z_ inv(S r,S x){fp s;sq(s,x);RSX;N(248,sq(s,r),RSX)sq(s,r),sq(r,s),SRX,sq(r,s);N(2,sq(s,r),RSX)} 25 | Z_ exp(S r,S x,S s){ sq(r,x);SRX;N(248,sq(r,s),SRX)sq(r,s),sq(s,r),RSX;} 26 | Z_ sqt(S r,S a){fp v,i,x,y;mlc(x,a,2),exp(v,x,y),sq(y,v),mul(i,x,y),loa(y,1),sub(i,i,y),mul(x,v,a),mul(r,x,i);} 27 | 28 | // dbl-1987-m3: a=x2+z2, b=x2-z2, c=x3+z3, d=x3-z3, da=d a, cb=c b, x5=z1(da+cb)^2, z5=x1(da-cb)^2 29 | Z_ xadd(S x5,S z5,S x1,S z1,S x2,S z2,S x3,S z3){fp da,cb,a,b;add(a,x2,z2),sub(b,x3,z3),mul(da,a,b),sub(b,x2,z2),add(a,x3,z3),mul(cb,a,b),add(a,da,cb),sq(b,a),mul(x5,z1,b),sub(a,da,cb),sq(b,a),mul(z5,x1,b);} 30 | // dbl-1987-m: x3=(x1^2-z1^2)^2, z3=4 x1 z1 (x1^2+(a x1 z1)+z1^2) 31 | Z_ xdbl(S x3,S z3,S x1,S z1){fp x1sq,z1sq,x1z1,a;sq(x1sq,x1),sq(z1sq,z1),mul(x1z1,x1,z1),sub(a,x1sq,z1sq),sq(x3,a),mlc(a,x1z1,486662),add(a,x1sq,a),add(a,z1sq,a),mul(x1sq,x1z1,a),mlc(z3,x1sq,4);} 32 | // scalar mult 33 | ZZ xmul(S r,S q,S e){fp xm,xms,zms,zm={1},xm1={1},zm1={0};dsn(xm,q,32); //!< p(m),p(m-1) 34 | _N(254,BIT(e)xadd(xm1,zm1,q,ONE,xm,zm,xm1,zm1),xdbl(xm,zm,xm,zm),xadd(xms,zms,xm1,zm1,xm,zm,q,ONE); //!< p(2m),p(2m-1) 35 | sel(xm1,xm1,xm,bit),sel(zm1,zm1,zm,bit),sel(xm,xm,xms,bit),sel(zm,zm,zms,bit))//!< bit?(p(2m+1),p(2m)):(p(2m),p(2m-1)) 36 | inv(zm1,zm),mul(r,zm1,xm),nrm(r);}//!< freeze out projective coords 37 | 38 | //! x25519 ecdh 39 | _ xkeygen(fp sec,fp pub,fp rnd){dsn(sec,rnd,32),prp(sec),xmul(pub,BP,sec),rfc(pub);} 40 | _ xshared(fp shr,fp sec,fp pub){xmul(shr,pub,sec);}//_ xrandom(S x,V n){N(n,Xk=r8())} 41 | 42 | // generic finite fields 43 | Z_ shft(S x,I n){H c=0;X(c|=HX<>=8)}Z_ copy(S x,S a){dsn(x,a,32);}ZI pmsb(S x){G y;_N(32,if((y=Xg)){i<<=3;W(y){y>>=1;i++;}R--i;})R 0;} 44 | Z_ radd(S x,S y){H c=0;X(c+=HX+HY;Xg=c;c>>=8)}Z_ rsub(S x,S y){fp z;H c=0;X(c=HX-HY-c;Zg=c;c=(c>>8)&1)sel(x,z,x,c);}Z_ fadd(S r,S a,S m){radd(r,a),rsub(r,m);} 45 | Z_ pfrb(S r,S x,size_t len,S m){I t=min(pmsb(m)-1,len<<3),by=t>>3,bi=t&7,rbi=(len<<3)-t;memset(r,0,32);//O("len %d t %d by %d bi %d rbi %d\n",len,t,by,bi,rbi); 46 | N(by,Rg=x[len-by+i])if(bi){shft(r,bi);r[0]|=x[len-by-1]>>(8-bi);}_N(rbi,BIT(x);shft(r,1);*r|=bit;rsub(r,m))} 47 | Z_ fmul(S r,S a,S b,S m){memset(r,0,32);_N(pmsb(m),BIT(b);fp plusa;shft(r,1),rsub(r,m),copy(plusa,r),fadd(plusa,a,m),sel(r,r,plusa,bit))} 48 | 49 | #define SHA(s) struct sha_state s;sha_ini(&s); 50 | Z_ sha5(S out_fp,S init_block,V prfx,S msg,V len){SHA(s); 51 | if(len<128&&len+prfx<128){dsn(init_block+prfx,msg,len);sha_end(&s,init_block,len+prfx); 52 | }else{dsn(init_block+prfx,msg,128-prfx);sha_add(&s,init_block); 53 | size_t i;for(i=128-prfx;i+128<=len;i+=128)sha_add(&s,msg+i);sha_end(&s,msg+i,len+prfx);} 54 | sha_get(&s,init_block,0,64);pfrb(out_fp,init_block,64,EO);} 55 | 56 | //! projective prims: copy, project, unproject, pack, try to unpack 57 | Z_ ecpy(ep d,const ep s){dsn(d,s,SZ(EP));} 58 | Z_ proj(ep p,S x,S y){copy(Px,x),copy(Py,y);loa(Pz,1),mul(Pt,x,y);} 59 | Z_ uprj(S x,S y,ep p){fp z;inv(z,Pz),mul(x,Px,z),mul(y,Py,z),nrm(x),nrm(y);} 60 | Z_ pack(S c,S x,S y){fp t;G p;copy(t,x),nrm(t);copy(c,y),nrm(c);c[31]|=(t[0]&1)<<7;} 61 | ZG unpk(S x,S y,S comp){I p=comp[31]>>7;fp a,b,c;copy(y,comp);y[31]&=127; 62 | sq(c,y);mul(b,c,ED);add(a,b,ONE);inv(b,a);sub(a,c,ONE); 63 | mul(c,a,b),sqt(a,c),neg(b,a),sel(x,a,b,(a[0]^p)&1),sq(a,x),nrm(a),nrm(c);R eql(a,c);} 64 | 65 | // point addition (add-2008-hwcd-3) 66 | Z_ eadd(ep p,ep p1,ep p2){fp a,b,c,d,e,f,g,h;sub(c,P1y,P1x),sub(d,P2y,P2x),mul(a,c,d),add(c,P1y,P1x),add(d,P2y,P2x),mul(b,c,d),mul(d,P1t,P2t),mul(c,d,EK), 67 | mul(d,P1z,P2z),add(d,d,d),sub(e,b,a),sub(f,d,c),add(g,d,c),add(h,b,a);mul(Px,e,f),mul(Py,g,h),mul(Pt,e,h),mul(Pz,f,g);} 68 | 69 | // point doubling (dbl-2008-hwcd) 70 | Z_ edbl(ep p,ep p1){fp a,b,c,d,e,f,g,h;sq(a,P1x),sq(b,P1y),sq(c,P1z),add(c,c,c),add(f,P1x,P1y),sq(e,f),sub(e,e,a),sub(e,e,b),sub(g,b,a),sub(f,g,c),neg(h,b),sub(h,h,a); 71 | mul(Px,e,f),mul(Py,g,h),mul(Pt,e,h),mul(Pz,f,g);} 72 | 73 | // edwards scalar multiplication 74 | Z_ emul(ep out,ep p,S e){EP r,s;ecpy(&r,&EN);_N(256,BIT(e);edbl(&r,&r);eadd(&s,&r,p);SEL(x)SEL(y)SEL(z)SEL(t))ecpy(out,&r);} 75 | 76 | Z_ pck(S r,ep p){fp x,y;uprj(x,y,p);pack(r,x,y);} 77 | ZG upk(ep p,S pckd){fp x,y;G ok=unpk(x,y,pckd);R proj(p,x,y),ok;} 78 | Z_ epck(S r,S k){EP p;emul(&p,&EB,k);pck(r,&p);} 79 | Z_ xpnd(S r,S sec){SHA(s);sha_end(&s,sec,32),sha_get(&s,r,0,64),prp(r);} 80 | Z_ pubk(S pub,S sec){G e[64];xpnd(e,sec);epck(pub,e);} 81 | 82 | Z_ getk(S k,S key,S m,V n){G blk[128]={0};copy(blk,key);sha5(k,blk,32,m,n);} 83 | Z_ getm(S z,S r,S a,S m,V n){G blk[128]={0};copy(blk,r);copy(blk+32,a);sha5(z,blk,64,m,n);} 84 | 85 | //! ed25519 ecdsa 86 | _ edkeygen(G sec[64],fp pub,fp seed){pubk(pub,seed);copy(sec,seed);copy(sec+32,pub);}//FIXME wipe seed 87 | 88 | _ edsign(G sig[64],fp pub,G sec[64],S m,V n){ 89 | G expd[64];fp e,s,k,z;xpnd(expd,sec); 90 | getk(k,expd+32,m,n),epck(sig,k),getm(z,sig,pub,m,n), 91 | pfrb(e,expd,32,EO),fmul(s,z,e,EO),fadd(s,k,EO),copy(sig+32,s);} 92 | 93 | G edverify(G sig[64],fp pub,S m,V n){EP p,q;fp lhs,rhs,z;G ok=1; 94 | getm(z,sig,pub,m,n),epck(lhs,sig+32); 95 | ok&=upk(&p,pub);emul(&p,&p,z); 96 | ok&=upk(&q,sig);eadd(&p,&p,&q), 97 | pck(rhs,&p);R(ok&eql(lhs,rhs))!=0;} 98 | 99 | //:~ 100 | -------------------------------------------------------------------------------- /ec/e.h: -------------------------------------------------------------------------------- 1 | #include//mcpy 2 | #include//printf 3 | 4 | #define dsn memcpy 5 | #define mmv memmove 6 | #define mset memset 7 | 8 | #include"sha.h" 9 | 10 | typedef void _;typedef unsigned short H;typedef unsigned int V;typedef unsigned char*S,G;typedef int I;typedef unsigned long long UJ; 11 | typedef G fp[32]; typedef struct{fp x;fp y;fp t;fp z;}EP;typedef EP*ep; //!< montgomery / edwards 12 | 13 | extern _ xkeygen(fp sec,fp pub,fp rnd),xshared(fp shr,fp sec,fp pub); 14 | extern _ edsign(G sig[64],fp pub,G sec[64],S m,V n);extern G edverify(G sig[64],fp pub,S m,V n);_ edkeygen(G sec[64],fp pub,fp seed); 15 | 16 | #define ZEP(x) static const EP x 17 | 18 | #ifndef TST 19 | #define ZFP(x) static const fp x 20 | #define ZG static G 21 | #define ZI static I 22 | #define ZZ Z_ 23 | #else 24 | #define ZFP(x) fp x 25 | #define ZG G 26 | #define ZI I 27 | #define ZZ _ 28 | extern ZG eql(S x,S y);extern ZZ prp(S x),xmul(S r,S q,S e); 29 | #endif 30 | 31 | #define W(a...) while(({a;})) 32 | #define N(n,a...) {V _n=(n),i=-1;W(++i<_n){a;}} 33 | #define Nj(n,a...) {V _n=(n),j=-1;W(++j<_n){a;}} 34 | #define _N(n,a...) {V i=(n);W(i--){a;}} 35 | #define P(b,a...) if(b)R({a;}); 36 | 37 | #define R return 38 | #define SZ sizeof 39 | #define Z_ static _ 40 | #define rG ((G*)r) 41 | #define yG ((G*)y) 42 | #define xG ((G*)x) 43 | #define zG ((G*)z) 44 | #define Xg xG[i] 45 | #define Yg yG[i] 46 | #define Zg zG[i] 47 | #define Rg rG[i] 48 | #define Xk xK[i] 49 | #define X(x) N(32,x) 50 | #define RD(x) X(c+=x;x=c;c>>=8) 51 | #define RDc RD(Rg) 52 | #define RDC c=(c>>7)*19;RDc 53 | #define RDCC r[31]=c&127;RDC 54 | #define RSX mul(r,s,x) 55 | #define SRX mul(s,r,x) 56 | #define SRSX sq(s,r),RSX 57 | #define HX ((H)Xg) 58 | #define HY ((H)Yg) 59 | #define VX ((V)Xg) 60 | #define VY ((V)Yg) 61 | #define Vx(i) ((V)x[i]) 62 | #define Vy(i) ((V)y[i]) 63 | 64 | #define SUB(y,yy) V c=218;N(31,c+=y-VX+0xff00;Rg=c;c>>=8)c+=yy-Vx(31);RDCC 65 | #define BIT(x) G bit=(x[i>>3]>>(i&7))&1; 66 | #define SEL(f) sel(r.f,r.f,s.f,bit); 67 | #define rfc(x) x[31]&=0x7f 68 | #define RFC rfc(r) 69 | #define sq(r,x) mul(r,x,x) 70 | 71 | #define Px p->x 72 | #define Py p->y 73 | #define Pz p->z 74 | #define Pt p->t 75 | #define P1x p1->x 76 | #define P1y p1->y 77 | #define P1z p1->z 78 | #define P1t p1->t 79 | #define P2x p2->x 80 | #define P2y p2->y 81 | #define P2z p2->z 82 | #define P2t p2->t 83 | 84 | //! nolibc 85 | #if 0 86 | unsigned char*dsn(unsigned char*d,unsigned char*s,size_t n) {W(n--)*d++=*s++;R d;} 87 | unsigned char*mmv(unsigned char*d,unsigned char*s,size_t n) {P(s 2 | 3 | 4 | 5 | 6 | 7 | 8 | Theta | EC 9 | 10 | 11 | 12 | 13 | 14 | 15 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /ec/makefile: -------------------------------------------------------------------------------- 1 | M=64 2 | C=clang 3 | O=-Os -m$M -std=gnu11 -DTST -pedantic -minline-all-stringops -fno-asynchronous-unwind-tables -fno-stack-protector -Wno-gnu-statement-expression -Wno-variadic-macros -Wno-incompatible-pointer-types-discards-qualifiers 4 | SO=-shared -rdynamic -fPIC 5 | #-nostdlib 6 | EMOPT=${shell grep -v '@see' wop | xargs} 7 | EMOPT2=${shell grep -v '@see' wop2 | xargs} 8 | 9 | #C=$(shell env which gcc-9||env which gcc-8||echo gcc) 10 | ifeq ($(shell uname),Darwin) 11 | O+= -I$(shell xcrun --show-sdk-path)/usr/include 12 | endif 13 | 14 | e: so 15 | #@$C $O -UTST t.c -L. -le$M -o e$M 16 | @$C $O -DTST t.c e.c sha.c -o e$M 17 | @#strip -K _main e$M 18 | #LD_LIBRARY_PATH=. ./e$M 19 | ./e$M 20 | 21 | t: tso 22 | $C $O t.c -L. -le$Mt -o t$M 23 | LD_LIBRARY_PATH=. ./t$M 24 | 25 | so: 26 | @$C $O $(SO) -UTST e.c sha.c -o libe$M.so 27 | ls -lah libe$M.so 28 | 29 | tso: 30 | $C $O $(SO) e.c sha.c -o libe$Mt.so 31 | 32 | wso: 33 | emcc e.c -m32 -o e.wasm -Oz $(EMOPT) 34 | 35 | w: 36 | emcc -DTST e.c t.c -m32 -o w.html -Oz $(EMOPT2) 37 | 38 | 39 | goinstall: 40 | go install golang.org/x/crypto/curve25519 encoding/hex 41 | 42 | go: 43 | go build e.go 44 | ./e 45 | 46 | all: t 47 | 48 | .PHONY: all clean 49 | -------------------------------------------------------------------------------- /ec/sha.c: -------------------------------------------------------------------------------- 1 | /* SHA512 2 | * Daniel Beer , 22 Apr 2014 3 | * 4 | * This file is in the public domain. 5 | */ 6 | 7 | #include "sha.h" 8 | 9 | #if !defined(COMPACT_DISABLE_ED25519) || !defined(COMPACT_DISABLE_X25519_DERIVE) 10 | const struct sha_state sha_initial_state = { { 11 | 0x6a09e667f3bcc908LL, 0xbb67ae8584caa73bLL, 12 | 0x3c6ef372fe94f82bLL, 0xa54ff53a5f1d36f1LL, 13 | 0x510e527fade682d1LL, 0x9b05688c2b3e6c1fLL, 14 | 0x1f83d9abfb41bd6bLL, 0x5be0cd19137e2179LL, 15 | } }; 16 | 17 | static const uint64_t round_k[80] = { 18 | 0x428a2f98d728ae22LL, 0x7137449123ef65cdLL, 19 | 0xb5c0fbcfec4d3b2fLL, 0xe9b5dba58189dbbcLL, 20 | 0x3956c25bf348b538LL, 0x59f111f1b605d019LL, 21 | 0x923f82a4af194f9bLL, 0xab1c5ed5da6d8118LL, 22 | 0xd807aa98a3030242LL, 0x12835b0145706fbeLL, 23 | 0x243185be4ee4b28cLL, 0x550c7dc3d5ffb4e2LL, 24 | 0x72be5d74f27b896fLL, 0x80deb1fe3b1696b1LL, 25 | 0x9bdc06a725c71235LL, 0xc19bf174cf692694LL, 26 | 0xe49b69c19ef14ad2LL, 0xefbe4786384f25e3LL, 27 | 0x0fc19dc68b8cd5b5LL, 0x240ca1cc77ac9c65LL, 28 | 0x2de92c6f592b0275LL, 0x4a7484aa6ea6e483LL, 29 | 0x5cb0a9dcbd41fbd4LL, 0x76f988da831153b5LL, 30 | 0x983e5152ee66dfabLL, 0xa831c66d2db43210LL, 31 | 0xb00327c898fb213fLL, 0xbf597fc7beef0ee4LL, 32 | 0xc6e00bf33da88fc2LL, 0xd5a79147930aa725LL, 33 | 0x06ca6351e003826fLL, 0x142929670a0e6e70LL, 34 | 0x27b70a8546d22ffcLL, 0x2e1b21385c26c926LL, 35 | 0x4d2c6dfc5ac42aedLL, 0x53380d139d95b3dfLL, 36 | 0x650a73548baf63deLL, 0x766a0abb3c77b2a8LL, 37 | 0x81c2c92e47edaee6LL, 0x92722c851482353bLL, 38 | 0xa2bfe8a14cf10364LL, 0xa81a664bbc423001LL, 39 | 0xc24b8b70d0f89791LL, 0xc76c51a30654be30LL, 40 | 0xd192e819d6ef5218LL, 0xd69906245565a910LL, 41 | 0xf40e35855771202aLL, 0x106aa07032bbd1b8LL, 42 | 0x19a4c116b8d2d0c8LL, 0x1e376c085141ab53LL, 43 | 0x2748774cdf8eeb99LL, 0x34b0bcb5e19b48a8LL, 44 | 0x391c0cb3c5c95a63LL, 0x4ed8aa4ae3418acbLL, 45 | 0x5b9cca4f7763e373LL, 0x682e6ff3d6b2b8a3LL, 46 | 0x748f82ee5defb2fcLL, 0x78a5636f43172f60LL, 47 | 0x84c87814a1f0ab72LL, 0x8cc702081a6439ecLL, 48 | 0x90befffa23631e28LL, 0xa4506cebde82bde9LL, 49 | 0xbef9a3f7b2c67915LL, 0xc67178f2e372532bLL, 50 | 0xca273eceea26619cLL, 0xd186b8c721c0c207LL, 51 | 0xeada7dd6cde0eb1eLL, 0xf57d4f7fee6ed178LL, 52 | 0x06f067aa72176fbaLL, 0x0a637dc5a2c898a6LL, 53 | 0x113f9804bef90daeLL, 0x1b710b35131c471bLL, 54 | 0x28db77f523047d84LL, 0x32caab7b40c72493LL, 55 | 0x3c9ebe0a15c9bebcLL, 0x431d67c49c100d4cLL, 56 | 0x4cc5d4becb3e42b6LL, 0x597f299cfc657e2aLL, 57 | 0x5fcb6fab3ad6faecLL, 0x6c44198c4a475817LL, 58 | }; 59 | 60 | static inline uint64_t load64(const uint8_t *x) 61 | { 62 | uint64_t r; 63 | 64 | r = *(x++); 65 | r = (r << 8) | *(x++); 66 | r = (r << 8) | *(x++); 67 | r = (r << 8) | *(x++); 68 | r = (r << 8) | *(x++); 69 | r = (r << 8) | *(x++); 70 | r = (r << 8) | *(x++); 71 | r = (r << 8) | *(x++); 72 | 73 | return r; 74 | } 75 | 76 | static inline void store64(uint8_t *x, uint64_t v) 77 | { 78 | x += 7; 79 | *(x--) = v; 80 | v >>= 8; 81 | *(x--) = v; 82 | v >>= 8; 83 | *(x--) = v; 84 | v >>= 8; 85 | *(x--) = v; 86 | v >>= 8; 87 | *(x--) = v; 88 | v >>= 8; 89 | *(x--) = v; 90 | v >>= 8; 91 | *(x--) = v; 92 | v >>= 8; 93 | *(x--) = v; 94 | } 95 | 96 | static inline uint64_t rot64(uint64_t x, int bits) 97 | { 98 | return (x >> bits) | (x << (64 - bits)); 99 | } 100 | 101 | void sha_add(struct sha_state *s, const uint8_t *blk) 102 | { 103 | uint64_t w[16]; 104 | uint64_t a, b, c, d, e, f, g, h; 105 | int i; 106 | 107 | for (i = 0; i < 16; i++) { 108 | w[i] = load64(blk); 109 | blk += 8; 110 | } 111 | 112 | /* Load state */ 113 | a = s->h[0]; 114 | b = s->h[1]; 115 | c = s->h[2]; 116 | d = s->h[3]; 117 | e = s->h[4]; 118 | f = s->h[5]; 119 | g = s->h[6]; 120 | h = s->h[7]; 121 | 122 | for (i = 0; i < 80; i++) { 123 | /* Compute value of w[i + 16]. w[wrap(i)] is currently w[i] */ 124 | const uint64_t wi = w[i & 15]; 125 | const uint64_t wi15 = w[(i + 1) & 15]; 126 | const uint64_t wi2 = w[(i + 14) & 15]; 127 | const uint64_t wi7 = w[(i + 9) & 15]; 128 | const uint64_t s0 = 129 | rot64(wi15, 1) ^ rot64(wi15, 8) ^ (wi15 >> 7); 130 | const uint64_t s1 = 131 | rot64(wi2, 19) ^ rot64(wi2, 61) ^ (wi2 >> 6); 132 | 133 | /* Round calculations */ 134 | const uint64_t S0 = rot64(a, 28) ^ rot64(a, 34) ^ rot64(a, 39); 135 | const uint64_t S1 = rot64(e, 14) ^ rot64(e, 18) ^ rot64(e, 41); 136 | const uint64_t ch = (e & f) ^ ((~e) & g); 137 | const uint64_t temp1 = h + S1 + ch + round_k[i] + wi; 138 | const uint64_t maj = (a & b) ^ (a & c) ^ (b & c); 139 | const uint64_t temp2 = S0 + maj; 140 | 141 | /* Update round state */ 142 | h = g; 143 | g = f; 144 | f = e; 145 | e = d + temp1; 146 | d = c; 147 | c = b; 148 | b = a; 149 | a = temp1 + temp2; 150 | 151 | /* w[wrap(i)] becomes w[i + 16] */ 152 | w[i & 15] = wi + s0 + wi7 + s1; 153 | } 154 | 155 | /* Store state */ 156 | s->h[0] += a; 157 | s->h[1] += b; 158 | s->h[2] += c; 159 | s->h[3] += d; 160 | s->h[4] += e; 161 | s->h[5] += f; 162 | s->h[6] += g; 163 | s->h[7] += h; 164 | } 165 | 166 | void sha_end(struct sha_state *s, const uint8_t *blk, 167 | size_t total_size) 168 | { 169 | uint8_t temp[SHA512_BLOCK_SIZE] = {0}; 170 | const size_t last_size = total_size & (SHA512_BLOCK_SIZE - 1); 171 | 172 | if (last_size) 173 | dsn(temp, blk, last_size); 174 | temp[last_size] = 0x80; 175 | 176 | if (last_size > 111) { 177 | sha_add(s, temp); 178 | mset(temp, 0, sizeof(temp)); 179 | } 180 | 181 | /* Note: we assume total_size fits in 61 bits */ 182 | store64(temp + SHA512_BLOCK_SIZE - 8, total_size << 3); 183 | sha_add(s, temp); 184 | } 185 | 186 | void sha_get(const struct sha_state *s, uint8_t *hash, 187 | unsigned int offset, unsigned int len) 188 | { 189 | int i; 190 | 191 | if (offset > SHA512_BLOCK_SIZE) 192 | return; 193 | 194 | if (len > SHA512_BLOCK_SIZE - offset) 195 | len = SHA512_BLOCK_SIZE - offset; 196 | 197 | /* Skip whole words */ 198 | i = offset >> 3; 199 | offset &= 7; 200 | 201 | /* Skip/read out bytes */ 202 | if (offset) { 203 | uint8_t tmp[8]; 204 | unsigned int c = 8 - offset; 205 | 206 | if (c > len) 207 | c = len; 208 | 209 | store64(tmp, s->h[i++]); 210 | mmv(hash, tmp + offset, c); 211 | len -= c; 212 | hash += c; 213 | } 214 | 215 | /* Read out whole words */ 216 | while (len >= 8) { 217 | store64(hash, s->h[i++]); 218 | hash += 8; 219 | len -= 8; 220 | } 221 | 222 | /* Read out bytes */ 223 | if (len) { 224 | uint8_t tmp[8]; 225 | 226 | store64(tmp, s->h[i]); 227 | mmv(hash, tmp, len); 228 | } 229 | } 230 | #endif 231 | 232 | //:~ 233 | -------------------------------------------------------------------------------- /ec/sha.h: -------------------------------------------------------------------------------- 1 | /* SHA512 2 | * Daniel Beer , 22 Apr 2014 3 | * 4 | * This file is in the public domain. 5 | */ 6 | 7 | #ifndef SHA512_H_ 8 | #define SHA512_H_ 9 | 10 | #if !defined(COMPACT_DISABLE_ED25519) || !defined(COMPACT_DISABLE_X25519_DERIVE) 11 | #include 12 | #include 13 | #include 14 | 15 | #define dsn memcpy 16 | #define mset memset 17 | #define mmv memmove 18 | 19 | /* SHA512 state. State is updated as data is fed in, and then the final 20 | * hash can be read out in slices. 21 | * 22 | * Data is fed in as a sequence of full blocks terminated by a single 23 | * partial block. 24 | */ 25 | struct sha_state { 26 | uint64_t h[8]; 27 | }; 28 | 29 | /* Initial state */ 30 | extern const struct sha_state sha_initial_state; 31 | 32 | /* Set up a new context */ 33 | static inline void sha_ini(struct sha_state *s) 34 | { 35 | dsn(s, &sha_initial_state, sizeof(*s)); 36 | } 37 | 38 | /* Feed a full block in */ 39 | #define SHA512_BLOCK_SIZE 128 40 | 41 | void sha_add(struct sha_state *s, const uint8_t *blk); 42 | 43 | /* Feed the last partial block in. The total stream size must be 44 | * specified. The size of the block given is assumed to be (total_size % 45 | * SHA512_BLOCK_SIZE). This might be zero, but you still need to call 46 | * this function to terminate the stream. 47 | */ 48 | void sha_end(struct sha_state *s, const uint8_t *blk, 49 | size_t total_size); 50 | 51 | /* Fetch a slice of the hash result. */ 52 | #define SHA512_HASH_SIZE 64 53 | 54 | void sha_get(const struct sha_state *s, uint8_t *hash, 55 | unsigned int offset, unsigned int len); 56 | 57 | #endif 58 | #endif 59 | 60 | //:~ 61 | -------------------------------------------------------------------------------- /ec/t.c: -------------------------------------------------------------------------------- 1 | #include"t.h" 2 | 3 | #ifdef TST 4 | #define TEST(s,v) O("%s ",s);N(NVEC(v),tst(&v[i])); 5 | Z_ tst(tvec*v){ 6 | S p,_e,exp;fp e,r;p=hex(v->p);_e=hex(v->e);exp=hex(v->r); 7 | dsn(e,_e,32),prp(e),rfc(p),xmul(r,p,e);G t=eql(r, exp); 8 | if(!t){O(" ");dump(r);O(" != ");dump(exp);nl();} 9 | FR(p)FR(_e)FR(exp)assert(t);} 10 | #endif 11 | 12 | I main(I c,char**v){srand(time(0));pcg32 prng={rand(),rand()|1}; 13 | #ifdef TST 14 | TEST("rfc7748",rfc_vectors) 15 | // rfc7748 alice and bob 16 | fp ask,bsk,apub,bpub; 17 | S apri=hex(A_PRI),apub_exp=hex(A_PUB),bpri=hex(B_PRI),bpub_exp=hex(B_PUB),sha_exp=hex(AB_SK); 18 | prp(apri),prp(bpri),xmul(apub,BP,apri),xmul(bpub,BP,bpri),rfc(apub),rfc(bpub), 19 | xshared(ask,apri,bpub),xshared(bsk,bpri,apub); 20 | EQL(apub,apub_exp)EQL(bpub,bpub_exp)EQL(ask,bsk)EQL(ask,sha_exp) 21 | FR(apri)FR(apub_exp)FR(bpri)FR(bpub_exp)FR(sha_exp) 22 | O("prng "); 23 | #define LAPS 32 24 | #else 25 | #define LAPS 8 26 | #define EQL(x,y) if(memcmp(x,y,32)){O("mismatch\n");exit(1);}else{dump(x);nl();} 27 | #endif 28 | 29 | fp A,B,a,b,Ab,Ba,S1,S2; 30 | N(LAPS,seed(S1)seed(S2)xkeygen(A,a,S1),xkeygen(B,b,S2),xshared(Ab,A,b),xshared(Ba,B,a);EQL(Ab,Ba)) 31 | O("ok\n"); 32 | 33 | I MSG_SIZE = 128; 34 | uint8_t*msg = hex("4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e1617424a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e1617424a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e1617424a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742"); 35 | S SEED=hex("4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742"); 36 | 37 | fp seed,pub;G sec[64],sig[64];dsn(seed,SEED,32); 38 | edkeygen(sec,pub,seed);edsign(sig,pub,sec,msg,MSG_SIZE); 39 | P(!edverify(sig,pub,msg,MSG_SIZE),O("failed on good plaintext\n"),-1) 40 | msg[1]^=0x10;P(edverify(sig,pub,msg,MSG_SIZE),O("failed on bad plaintext\n"),-1) 41 | O("ed25519 smoke test ok\n");free(msg),free(SEED); 42 | 43 | //! rfc8072 test vectors 44 | #define RFC8032(test) O("rfc8032_%s_verify: %s\n",test,edverify(SIG,PUB,MSG,LEN)?"ok":"FAIL"); \ 45 | edsign(TESTSIG,PUB,PRI,MSG,LEN);O("rfc8032_%s_sign: %s\n",test,memcmp(TESTSIG,SIG,64)?"FAIL":"ok"); \ 46 | free(PRI),free(PUB),free(SIG),free(MSG); 47 | 48 | G TESTSIG[64]; 49 | 50 | S PRI = hex("f5e5767cf153319517630f226876b86c" 51 | "8160cc583bc013744c6bf255f5cc0ee5"); 52 | S PUB = hex("278117fc144c72340f67d0f2316e8386" 53 | "ceffbf2b2428c9c51fef7c597f1d426e"); 54 | S SIG = hex("0aab4c900501b3e24d7cdf4663326a3a" 55 | "87df5e4843b2cbdb67cbf6e460fec350" 56 | "aa5371b1508f9f4528ecea23c436d94b" 57 | "5e8fcd4f681e30a6ac00a9704a188a03"); 58 | V LEN = 1023; 59 | S MSG = hex("08b8b2b733424243760fe426a4b54908" 60 | "632110a66c2f6591eabd3345e3e4eb98" 61 | "fa6e264bf09efe12ee50f8f54e9f77b1" 62 | "e355f6c50544e23fb1433ddf73be84d8" 63 | "79de7c0046dc4996d9e773f4bc9efe57" 64 | "38829adb26c81b37c93a1b270b20329d" 65 | "658675fc6ea534e0810a4432826bf58c" 66 | "941efb65d57a338bbd2e26640f89ffbc" 67 | "1a858efcb8550ee3a5e1998bd177e93a" 68 | "7363c344fe6b199ee5d02e82d522c4fe" 69 | "ba15452f80288a821a579116ec6dad2b" 70 | "3b310da903401aa62100ab5d1a36553e" 71 | "06203b33890cc9b832f79ef80560ccb9" 72 | "a39ce767967ed628c6ad573cb116dbef" 73 | "efd75499da96bd68a8a97b928a8bbc10" 74 | "3b6621fcde2beca1231d206be6cd9ec7" 75 | "aff6f6c94fcd7204ed3455c68c83f4a4" 76 | "1da4af2b74ef5c53f1d8ac70bdcb7ed1" 77 | "85ce81bd84359d44254d95629e9855a9" 78 | "4a7c1958d1f8ada5d0532ed8a5aa3fb2" 79 | "d17ba70eb6248e594e1a2297acbbb39d" 80 | "502f1a8c6eb6f1ce22b3de1a1f40cc24" 81 | "554119a831a9aad6079cad88425de6bd" 82 | "e1a9187ebb6092cf67bf2b13fd65f270" 83 | "88d78b7e883c8759d2c4f5c65adb7553" 84 | "878ad575f9fad878e80a0c9ba63bcbcc" 85 | "2732e69485bbc9c90bfbd62481d9089b" 86 | "eccf80cfe2df16a2cf65bd92dd597b07" 87 | "07e0917af48bbb75fed413d238f5555a" 88 | "7a569d80c3414a8d0859dc65a46128ba" 89 | "b27af87a71314f318c782b23ebfe808b" 90 | "82b0ce26401d2e22f04d83d1255dc51a" 91 | "ddd3b75a2b1ae0784504df543af8969b" 92 | "e3ea7082ff7fc9888c144da2af58429e" 93 | "c96031dbcad3dad9af0dcbaaaf268cb8" 94 | "fcffead94f3c7ca495e056a9b47acdb7" 95 | "51fb73e666c6c655ade8297297d07ad1" 96 | "ba5e43f1bca32301651339e22904cc8c" 97 | "42f58c30c04aafdb038dda0847dd988d" 98 | "cda6f3bfd15c4b4c4525004aa06eeff8" 99 | "ca61783aacec57fb3d1f92b0fe2fd1a8" 100 | "5f6724517b65e614ad6808d6f6ee34df" 101 | "f7310fdc82aebfd904b01e1dc54b2927" 102 | "094b2db68d6f903b68401adebf5a7e08" 103 | "d78ff4ef5d63653a65040cf9bfd4aca7" 104 | "984a74d37145986780fc0b16ac451649" 105 | "de6188a7dbdf191f64b5fc5e2ab47b57" 106 | "f7f7276cd419c17a3ca8e1b939ae49e4" 107 | "88acba6b965610b5480109c8b17b80e1" 108 | "b7b750dfc7598d5d5011fd2dcc5600a3" 109 | "2ef5b52a1ecc820e308aa342721aac09" 110 | "43bf6686b64b2579376504ccc493d97e" 111 | "6aed3fb0f9cd71a43dd497f01f17c0e2" 112 | "cb3797aa2a2f256656168e6c496afc5f" 113 | "b93246f6b1116398a346f1a641f3b041" 114 | "e989f7914f90cc2c7fff357876e506b5" 115 | "0d334ba77c225bc307ba537152f3f161" 116 | "0e4eafe595f6d9d90d11faa933a15ef1" 117 | "369546868a7f3a45a96768d40fd9d034" 118 | "12c091c6315cf4fde7cb68606937380d" 119 | "b2eaaa707b4c4185c32eddcdd306705e" 120 | "4dc1ffc872eeee475a64dfac86aba41c" 121 | "0618983f8741c5ef68d3a101e8a3b8ca" 122 | "c60c905c15fc910840b94c00a0b9d0"); 123 | 124 | RFC8032("test1024") 125 | 126 | PRI = hex("833fe62409237b9d62ec77587520911e" 127 | "9a759cec1d19755b7da901b96dca3d42"); 128 | PUB = hex("ec172b93ad5e563bf4932c70e1245034" 129 | "c35467ef2efd4d64ebf819683467e2bf"); 130 | SIG = hex("dc2a4459e7369633a52b1bf277839a00" 131 | "201009a3efbf3ecb69bea2186c26b589" 132 | "09351fc9ac90b3ecfdfbc7c66431e030" 133 | "3dca179c138ac17ad9bef1177331a704"); 134 | LEN = 64; 135 | MSG = hex("ddaf35a193617abacc417349ae204131" 136 | "12e6fa4e89a97ea20a9eeee64b55d39a" 137 | "2192992a274fc1a836ba3c23a3feebbd" 138 | "454d4423643ce80e2a9ac94fa54ca49f"); 139 | 140 | RFC8032("testABC") 141 | 142 | PRI = hex("c5aa8df43f9f837bedb7442f31dcb7b1" 143 | "66d38535076f094b85ce3a2e0b4458f7"); 144 | PUB = hex("fc51cd8e6218a1a38da47ed00230f058" 145 | "0816ed13ba3303ac5deb911548908025"); 146 | SIG = hex("6291d657deec24024827e69c3abe01a3" 147 | "0ce548a284743a445e3680d7db5ac3ac" 148 | "18ff9b538d16f290ae67f760984dc659" 149 | "4a7c15e9716ed28dc027beceea1ec40a"); 150 | LEN = 2;MSG = hex("af82"); 151 | 152 | RFC8032("test3") 153 | 154 | PRI = hex("4ccd089b28ff96da9db6c346ec114e0f" 155 | "5b8a319f35aba624da8cf6ed4fb8a6fb"); 156 | PUB = hex("3d4017c3e843895a92b70aa74d1b7ebc" 157 | "9c982ccf2ec4968cc0cd55f12af4660c"); 158 | SIG = hex("92a009a9f0d4cab8720e820b5f642540" 159 | "a2b27b5416503f8fb3762223ebdb69da" 160 | "085ac1e43e15996e458f3613d0f11d8c" 161 | "387b2eaeb4302aeeb00d291612bb0c00"); 162 | LEN = 1;MSG = hex("72"); 163 | 164 | RFC8032("test2") 165 | 166 | PRI = hex("9d61b19deffd5a60ba844af492ec2cc4" 167 | "4449c5697b326919703bac031cae7f60"); 168 | PUB = hex("d75a980182b10ab7d54bfed3c964073a" 169 | "0ee172f3daa62325af021a68f707511a"); 170 | SIG = hex("e5564300c360ac729086e2cc806e828a" 171 | "84877f1eb8e5d974d873e06522490155" 172 | "5fb8821590a33bacc61e39701cf9b46b" 173 | "d25bf5f0595bbe24655141438e7a100b"); 174 | LEN = 0;MSG = hex(""); 175 | 176 | RFC8032("test1") 177 | 178 | R 0;} 179 | 180 | //:~ 181 | -------------------------------------------------------------------------------- /ec/t.h: -------------------------------------------------------------------------------- 1 | #include//malloc free srand rand 2 | #include//printf 3 | #include//assert 4 | #include//time 5 | #include"e.h" 6 | 7 | #define O printf 8 | #define nl() O("\n") 9 | #define dump(x) X(O("%02x",x[i])) 10 | #define seed(x) N(8,((V*)x)[i]=pcg(&prng)) 11 | typedef struct{UJ state;UJ inc;}pcg32; 12 | static V pcg(pcg32*r){ //state;r->state=old*6364136223846793005ULL+(r->inc|1);//!< advance 14 | V xorsh=((old>>18u)^old)>>27u,rot=old>>59u;//!< XSH RR, uses old state for max ILP 15 | R(xorsh>>rot)|(xorsh<<((-rot)&31));} 16 | 17 | #ifdef TST 18 | extern fp ONE,BP;//base point 19 | #define FR(x) free(x); 20 | #define EQL(x,y) assert(eql(x,y)); 21 | #define NVEC(x) (SZ(x)/SZ(x[0])) 22 | #define XI(p) (*(p) <= '9'? (*(p)- '0'): *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10)) 23 | #define xtoi(p) ((XI(p)*16)+XI((p)+1)) 24 | static S hex(char*x){char*s;S b=malloc(strlen((char*)x)/2+1);I l=0;for(s=x;*s;s+=2){((S)b)[l++]=xtoi(s);}R b;} 25 | 26 | #define BASE_POINT "0900000000000000000000000000000000000000000000000000000000000000" 27 | #define ZERO_POINT "0000000000000000000000000000000000000000000000000000000000000000" 28 | 29 | typedef struct{char*p;char*e;char*r;}tvec; 30 | static tvec 31 | rfc_vectors[] = {//rfc7748 32 | { BASE_POINT , BASE_POINT ,"422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079"}, 33 | { BASE_POINT ,"a8abababababababababababababababababababababababababababababab6b","e3712d851a0e5d79b831c5e34ab22b41a198171de209b8b8faca23a11c624859"}, 34 | { BASE_POINT ,"c8cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd4d","b5bea823d9c9ff576091c54b7c596c0ae296884f0e150290e88455d7fba6126f"}, 35 | {"e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c","a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4","c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552"}, 36 | {"e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493","4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d","95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957"}, 37 | {"e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a413","4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d","95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957"}, 38 | {"cdeb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b880","a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4","7ce548bc4919008436244d2da7a9906528fe3a6d278047654bd32d8acde9707b"}, 39 | {"4c9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f11d7","a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4","e17902e989a034acdf7248260e2c94cdaf2fe1e72aaac7024a128058b6189939"}, 40 | {"d9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4","ea6e6ddf0685c31e152d5818441ac9ac8db1a01f3d6cb5041b07443a901e7145"}, 41 | {"daffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4","845ddce7b3a9b3ee01a2f1fd4282ad293310f7a232cbc5459fb35d94bccc9d05"}, 42 | {"dbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4","6989e2cb1cea159acf121b0af6bf77493189c9bd32c2dac71669b540f9488247"}, 43 | { ZERO_POINT ,"a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", ZERO_POINT }, 44 | {"0100000000000000000000000000000000000000000000000000000000000000","a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", ZERO_POINT }, 45 | {"e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b800","a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", ZERO_POINT }, 46 | {"5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f1157","a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", ZERO_POINT }, 47 | {"ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f","a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", ZERO_POINT }, 48 | {"edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f","a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", ZERO_POINT }, 49 | {"eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f","a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", ZERO_POINT }}; 50 | 51 | // rfc7748 52 | char*A_PRI="77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a",//alice 53 | *A_PUB="8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a", 54 | *B_PRI="5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb",//bob 55 | *B_PUB="de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f", 56 | *AB_SK="4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742";//shared 57 | 58 | #endif 59 | 60 | //:~ 61 | 62 | /* 63 | typedef unsigned char*S;typedef int I; 64 | #define W(a...) while(({a;})) 65 | #define N(n,a...) {I _n=(n),i=-1;W(++i<_n){a;}} 66 | #define X(x) N(32,x) 67 | #define O printf 68 | #define nl() O("\n") 69 | #define dump(x) X(O("%02x",x[i])) 70 | 71 | #define XI(p) (*(p) <= '9'? (*(p)- '0'): *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10)) 72 | #define xtoi(p) ((XI(p)*16)+XI((p)+1)) 73 | static S hex(char*x){char*s;S b=malloc(strlen((char*)x)/2+1);I l=0;for(s=x;*s;s+=2){((S)b)[l++]=xtoi(s);}return b;} 74 | */ 75 | -------------------------------------------------------------------------------- /ec/wop: -------------------------------------------------------------------------------- 1 | -s MALLOC="emmalloc" 2 | -s ABORTING_MALLOC=1 3 | -s ALLOW_MEMORY_GROWTH=0 4 | -s SAFE_HEAP=0 5 | -s DETERMINISTIC=0 6 | -s STACK_OVERFLOW_CHECK=0 7 | 8 | -s PRECISE_I64_MATH=1 9 | 10 | -s WARN_UNALIGNED=0 11 | -s USE_CLOSURE_COMPILER=1 12 | -s BINARYEN_ASYNC_COMPILATION=1 13 | -s ALIASING_FUNCTION_POINTERS=1 14 | -s WASM=1 15 | -s BINARYEN=1 16 | -s ASSERTIONS=0 17 | -s ERROR_ON_UNDEFINED_SYMBOLS=1 18 | -s DISABLE_EXCEPTION_CATCHING=1 19 | -s EMULATE_FUNCTION_POINTER_CASTS=0 20 | -s DEMANGLE_SUPPORT=0 21 | 22 | -s GLOBAL_BASE=-1 23 | -s TOTAL_STACK=1KB 24 | -s INITIAL_MEMORY=64KB 25 | -s WASM_MEM_MAX=64KB 26 | 27 | -s SIDE_MODULE=1 28 | #-s EXIT_RUNTIME=0 29 | -s STANDALONE_WASM 30 | 31 | -s USE_PTHREADS=0 32 | 33 | #-s FORCE_FILESYSTEM=1 --embed-file fs@/ 34 | 35 | 36 | 37 | -s MODULARIZE=1 38 | -s EXPORT_NAME="libspqr" 39 | -s EXPORTED_FUNCTIONS='["_xkeygen","_xshared"]' 40 | -s EXPORTED_RUNTIME_METHODS='["xkeygen","xshared","ccall","cwrap", "xkeygen","xshared"]' 41 | -s EXTRA_EXPORTED_RUNTIME_METHODS='["xkeygen","xshared", "ccall", "cwrap","getTempRet0","UTF8ToString"]' 42 | -------------------------------------------------------------------------------- /ec/wop2: -------------------------------------------------------------------------------- 1 | -s MALLOC="emmalloc" 2 | -s ABORTING_MALLOC=1 3 | -s ALLOW_MEMORY_GROWTH=0 4 | -s SAFE_HEAP=0 5 | -s DETERMINISTIC=0 6 | -s STACK_OVERFLOW_CHECK=0 7 | 8 | -s PRECISE_I64_MATH=1 9 | 10 | -s WARN_UNALIGNED=1 11 | -s USE_CLOSURE_COMPILER=1 12 | -s BINARYEN_ASYNC_COMPILATION=1 13 | -s ALIASING_FUNCTION_POINTERS=1 14 | -s WASM=1 15 | -s BINARYEN=1 16 | -s ASSERTIONS=0 17 | -s ERROR_ON_UNDEFINED_SYMBOLS=1 18 | -s DISABLE_EXCEPTION_CATCHING=1 19 | -s EMULATE_FUNCTION_POINTER_CASTS=0 20 | -s DEMANGLE_SUPPORT=0 21 | 22 | -s GLOBAL_BASE=-1 23 | -s TOTAL_STACK=16KB 24 | -s INITIAL_MEMORY=64KB 25 | -s WASM_MEM_MAX=64KB 26 | 27 | #-s SIDE_MODULE=1 28 | #-s EXIT_RUNTIME=0 29 | 30 | -s USE_PTHREADS=0 31 | 32 | #-s FORCE_FILESYSTEM=1 --embed-file fs@/ 33 | 34 | -s MODULARIZE=1 35 | -s EXPORT_NAME="libspqr" 36 | -s EXPORTED_FUNCTIONS='["_xkeygen","_xshared"]' 37 | -s EXPORTED_RUNTIME_METHODS='["xkeygen","xshared","ccall","cwrap", "xkeygen","xshared"]' 38 | -s EXTRA_EXPORTED_RUNTIME_METHODS='["xkeygen","xshared", "ccall", "cwrap","getTempRet0","UTF8ToString"]' 39 | -------------------------------------------------------------------------------- /h.c: -------------------------------------------------------------------------------- 1 | //! \file h.c \brief simple hash table with separate chaining 2 | //! \see https://svn.process-one.net/ejabberd/tags/ejabberd-2.0.5/src/tls/tls_drv.c 3 | #pragma GCC diagnostic ignored "-Wunknown-warning-option" 4 | #pragma GCC diagnostic ignored "-Wunused-but-set-variable" //! hi=0|1 for dbg 5 | #include"a.h" 6 | #include"h.h" 7 | 8 | #include"m.h" 9 | #define bmalloc aw_malloc 10 | #define bcalloc aw_calloc 11 | #define brealloc aw_realloc 12 | #define bfree aw_free 13 | 14 | #define SZ sizeof 15 | #define rea brealloc 16 | #define F(p) bfree(p) 17 | #define hmap(h,rng) (h&((rng)-1)) //!< map hash value onto given range (h mod rng) 18 | #define tid t->tid 19 | #define spl t->spl 20 | #define lvl t->lvl 21 | #define rds t->rds 22 | #define mem t->mem 23 | #define cnt t->cnt 24 | #define bkt t->bkt 25 | 26 | //! djb2 \see www.burtleburtle.net/bob/hash/doobs.html groups.google.com/forum/#!topic/comp.lang.c/lSKWXiuNOAk 27 | HTYPE djb2(S s,SZT n){HTYPE h=5381;N(n,h=(h<<5)+h+*s++)R h;} 28 | //HTYPE djb2(S x,SZT n){HTYPE h=5381;N(n,h=33*(h^x[i]));R h;} 29 | HTYPE sdbm(S s,SZT n){HTYPE h=0;N(n)h=*s+++(h<<6)+(h<<16)-h;R h;}//id,id,n); 33 | ZV hbal(HT t); 34 | 35 | B hget(HT t,S s,SZT n){ //!< lookup or insert string s of length n 36 | K x;B b;HTYPE h=HFN(s,n), hi=0, //!< b bucket, h hash, hi use full range (dbg) 37 | idx=hmap(h,lvl); //!< first, try to map hash value to the 1st half of table 38 | $(idxn==n,x=b->k; //!< if length matches.. 42 | N(n,$(Xc!=s[i],goto L0);) //!< compare strings char by char 43 | b) //!< if they match, return the bucket 44 | L0:b=b->next;} //!< otherwise keep traversing the list. 45 | I m=SZ(pbkt)/*+n+1*/;b=(B)bmalloc(m);//!< allocate memory for a new bucket (header size //+ strlen + terminator) 46 | mem+=m;b->h=h;b->n=n;b->v=NL; //!< increment mem usage and initialize bucket header 47 | //hcpy(b->k,s,n); //!< copy string to the bucket and terminate it 48 | x=b->k=pn(s,n);xt=KS; //!< internalize the string 49 | b->next=bkt[idx];bkt[idx]=b; //!< push the new bucket to the head of the slot 50 | //O("hget() %llx %llx %llx %llx %llx\n",b,b->k,&b->k,b->v,(&b->k)[-1]);//exit(0); 51 | if(b->next)hbal(t); //!< if slot has a tail, try to split it 52 | R cnt++,b;} //!< increment bucket count and return new bucket 53 | 54 | ZV hbal(HT t){B*bp,mov; //!< balance hash table load 55 | N(rds, //!< perform rds balancing attempts: 56 | bp=&bkt[spl]; //!< retrieve the head bucket at spl 57 | SZT topidx=lvl+spl; //!< index of a slot in the upper part 58 | W(*bp){ //!< while the slot at spl is not empty 59 | $(hmap((*bp)->h,lvl<<1)==topidx, //!< if the bucket's hash maps to topidx 60 | mov=*bp;*bp=(*bp)->next; //!< remove it from the list at spl 61 | mov->next=bkt[topidx]; //!< link the head bucket at newidx to it 62 | bkt[topidx]=mov)//else //!< and make it the new head 63 | bp=&(*bp)->next;} //!< keep traversing the list. 64 | $(++spl==lvl, //!< if ++spl+lvl reaches the size of the table 65 | lvl<<=1;spl=0; //!< then double lvl and reset spl to zero 66 | bkt=(B*)rea((V*)bkt,SZ(B*)*2*lvl);//!< double the size of the table 67 | N(lvl,bkt[lvl+i]=0)); //!< zero out the upper part. 68 | )} 69 | 70 | #define S0(ks) {K x=ks;xt=KC;r0(x);}; //!< release symbol (downcast to KC) 71 | K hdel(HT t){B b,n; //!< destroy table 72 | N(lvl<<1,b=bkt[i]; 73 | W(b){n=b->next,cnt--;S0(b->k)F(b),b=n;}) 74 | K r=cnt?AB("cnt"):(K)(spl=lvl=rds=mem=0);S0(tid) 75 | R F(bkt),F(t),r;} 76 | 77 | #ifdef TST 78 | I hslot(HT t){I r=0;N(lvl<<1,r+=!!bkt[i])R r;}F hload(HT t){R(F)hslot(t)/cnt;}//k;$(1 ",xn,(S)x,(SZT)b->h));P(xn-b->n,AB("hlen"))n++,len+=b->n;csum+=b->h;b=b->next;} 82 | $(n,csum+=len+n+i);$(1 6 | #endif 7 | 8 | #include"c.h" 9 | 10 | //#define HFN sdbm 11 | #define HFN djb2 12 | 13 | #define hval(t,k) (hget(t,k,sl(k))->v) 14 | #define hset(t,k,v) (hval=(K)v) 15 | 16 | typedef size_t SZT;typedef UI HTYPE;//typedef HTYPE(*HFN)(S s,SZT n); //!< //!< hash value type, hshfn function interface 17 | typedef struct pbkt pbkt;typedef pbkt*B;typedef struct pbkt{HTYPE h;SZT n;B next;K v;K k;}pbkt;//!< keyhash,keylen,next,value,key 18 | 19 | typedef struct ht{ 20 | K tid; //< table id (KS) 21 | SZT spl; //< split position 22 | SZT lvl; //< capacity is 2*lvl 23 | short rds; //< split rounds 24 | SZT cnt; //< bucket count 25 | SZT mem; //< mem usage 26 | B* bkt; //< array of bucket pointers 27 | //V* hea; //< bucket heap pointer TODO packing 28 | } pHT;typedef pHT*HT; 29 | const static SZT SZHT=sizeof(pHT); //< hash table header size 30 | 31 | HT hnew(S id,I l,I r); //!< init \p id table identifier \p lvl initial size \p rds rounds of tail split attempts 32 | B hget(HT t,S s,SZT n); //!< insert|lookup \p s string \p n length 33 | K hdel(HT t); //!< destroy table 34 | 35 | #ifdef TST 36 | I hslot(HT t); // 2 | #include 3 | #include 4 | #include"b.h" 5 | #include"l.h" 6 | 7 | _ stdout_send(S s,I n){N(n,putchar(s[i]))} 8 | 9 | B2(MA);i2(p2);ZK r=0,lH[HSZ]={0};static rl_t RL;K rl(){R r;}ZK1(r00){P(x&&x!=c0,xr=0,r0(x))}K an(K f,I n,K*x);A2(a2); 10 | ZK _sp,_ct;ZK take(I x,K y){R r1(Y0(p2(14,ki(x),y)));}ZK drop(I x,K y){R r1(Y0(p2(15,ki(x),y)));} 11 | ZK splice(I i,I c,K x){R r1(X0(an(_sp,3,(K*)(K[]){ki(i),kc(c),x})));}ZK cutout(I i,K x){R r1(X0(a2(_ct,ki(i),x)));} 12 | _ rlinit(){_sp=_sp?_sp:p9(",/@[(0,2#x)^z;1;y]");_ct=_ct?_ct:p9(",/((0,x,x+1)^y)0 2");} 13 | 14 | ZI last_line_len,redraw_step_back,redraw_step_forward,redraw_from_cursor; 15 | 16 | _ rlprmt(S p){r=ss(""),RL.orig_line_len=POS=rn;RESC;RL.escape_seq_buf[0]=0;RL.hist_cur=-1;trc("rl_",r);RL.prompt=p;ltx(p);} 17 | Z_ rlback(I n){P(n<=4,txn("\b\b\b\b",n))G VT[6];n=snprintf(&VT[0],sizeof(VT),"\x1b[%u",n);P(n>0,VT[n]='D';txn(VT,n+1))} 18 | Z_ rlsave(K y){if(!yn||*lH&&MA(*lH,y)){if(y==c0)r0(c0);R;}r00(lH[HSZ-1]);I j;N(j=HSZ-1,lH[j-i]=lH[j-i-1])*lH=y;trc("save3",*lH);} 19 | Z_ rlkill(U n){(_)n;ltx("\x1b[K");}_ rl1(){memset(lH,0,HSZ*sizeof(K));}_ rl0(){"nyi";} 20 | 21 | ZI rldraw(){ 22 | if(RL.hist_cur>=0){lH[RL.hist_cur]=r;}//update pointer 23 | if(redraw_step_back>0){rlback(redraw_step_back);POS -= redraw_step_back;} 24 | Z(redraw_from_cursor, 25 | if(rn < last_line_len)rlkill(last_line_len - POS);//erase old chars 26 | txn(rG + POS, rn - POS);//draw new chars 27 | //move cursor forward if needed (already moved forward by length of line, so move it back) 28 | rlback(rn - (POS + redraw_step_forward));POS += redraw_step_forward) 29 | Z(redraw_step_forward>0,//draw over old chars to move cursor forwards 30 | txn(rG + POS, redraw_step_forward);POS += redraw_step_forward);R-1;} 31 | 32 | I rlchar(I c){BCK(0),FWD(0),RFC(0),last_line_len=rn;SW(RL.escape_seq, 33 | C(NOP, 34 | P(c=='\n',txn("\r\n",2),rlsave(r),0)//commit line 35 | P(c==CTL_C||cin(CTL_A,CTL_E)&&!rn,-1)//^c or ctrl char on empty line 36 | Z(c==CTL_W,r=drop(POS,r),BCK(POS-RL.orig_line_len),RFC(1))//^w kill from caret to line start 37 | Z(c==CTL_K,r=take(POS,r),RFC(1))//^k kill from caret to line end 38 | Z((c==8||c==127)&&POS>RL.orig_line_len,r=cutout(POS-1,r),BCK(1),RFC(1))//del|bksp 39 | Z(cin(32,126),r=splice(POS,c,r),FWD(1),RFC(1))//ascii 40 | Z(c==CTL_A,HOME)Z(c==CTL_E,END)Z(c==27,RL.escape_seq=ESC);)//esc seq start 41 | C(ESC,RL.escape_seq=c=='['?ESCBKT:c=='O'?ESCO:NOP) 42 | C(ESCO,SW(c,C('H',HOME)C('F',END),RESET)) 43 | C(ESCBKT, 44 | Z(cin('0','9'),RL.escape_seq=ESCBKT0,RL.escape_seq_buf[0]=c){RESC; 45 | Z(c=='A'&&RL.hist_cur+1=0,lH[RL.hist_cur]=r;if(RL.hist_cur-->=0)r=lH[RL.hist_cur],SETPOS;)//d 47 | Z(c=='C'&&POSRL.orig_line_len,BCK(1))//rl 48 | Z(c=='H',HOME)Z(c=='F',END);}) 49 | C(ESCBKT0, 50 | Z(c=='~', 51 | Z(qes('1')||qes('7'),home_key:BCK(POS-RL.orig_line_len)) 52 | Z(qes('4')||qes('8'),end_key:FWD(rn-POS)) 53 | Z(qes('3')&&POS 2 | #include 3 | #include 4 | #include"l.h" 5 | 6 | main()( 7 | struct termios old_tio,new_tio;tcgetattr(STDIN_FILENO,&old_tio); 8 | new_tio=old_tio;new_tio.c_lflag&=(~ICANON & ~ECHO); 9 | tcsetattr(STDIN_FILENO,TCSANOW,&new_tio);I chr;S p="> ";K x; 10 | 11 | //k_(S*),rl1(); 12 | 13 | rl2();rlprmt(p);do{if(rlchar(getchar())>=0){x=rl(); 14 | O("%.*s xr %d ws %d\n",xn,xG,xr,WS);rlprmt(p);}}W(1); 15 | 16 | rl0();tcsetattr(STDIN_FILENO,TCSANOW,&old_tio);} 17 | -------------------------------------------------------------------------------- /m.c: -------------------------------------------------------------------------------- 1 | //! \file memory manager 2 | #include"a.h" 3 | #include"m.h" 4 | //! malloc/free: mturnnnn list join (k[cifs] k[CIFS]) 5 | //! K is mturnnnn: membucket, type, flags, refcount, length 6 | #ifndef COSMO 7 | ZI clzl(I n); 8 | #endif 9 | 10 | ZK M[31];ZJ W=W0;//!< M memory buckets, W wssize (W0 initial offset for GT header and seed alloc c0() \see init() 11 | S ma(I d,size_t n){ZJ p=BASE;p+=d?0:n;V*r=mmap((V*)(d?0:p-n),n,PROT_READ|PROT_WRITE|PROT_EXEC,d?MAP_PRIVATE:(MAP_ANON|MAP_PRIVATE|MAP_FIXED),d-!d,0);P(r==MAP_FAILED,O("%s\n",strerror(errno)),(S)0)R r;} 12 | K mf(S s,J*n){struct stat b;I d=open((V*)s,O_RDONLY);Qs(0>d,(S)s)R(K)(fstat(d,&b),s=(*n=b.st_size)?ma(d,*n):s,close(d),s);} 13 | 14 | K m1(J n){K x,r; //!< allocate a memory block 15 | I i=clzl(n+7),j=i; //!< i is the bucket id, log2((I)n) 16 | P((x=M[i]),M[i]=xx,x); //!< if there is a free block on top of the list M[i], pop and return 17 | W(!(x=++j<31 //!< otherwise, scan for a free block of a larger size 18 | ?M[j]: //!< if one exists, use it, otherwise.. 19 | 8+(K)ma(0,16L<<(j=MX(18,i))))); //!< ..mmap additional ram, at least 4mb + 8 bytes for mturnnnn 20 | xm=i,M[j]=xx,r=x; //!< assign bucket id to the new block and push it on top of the list M[j] 21 | //! assign fill the smaller empty buckets as follows: 22 | W(i16L< 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #endif 11 | 12 | #include"c.h" 13 | #ifndef COSMO 14 | K m1(J n);V1(r0);V1(l0);K3(l1);K1(l2);K tn(I t,I n),r1(K),xiy(K x,I i,K y);K2(j2);J ws();K mf(S s,J*n);V csr(); 15 | #else 16 | K1(l2);K mf(S s,J*n); 17 | #endif 18 | 19 | #ifndef SYMS 20 | #define W0 -32 //32 is the size of seed alloc c0() \see init() 21 | #else 22 | #define W0 -128-64 //64 is the size of seed alloc c0() plus HT header \see init() 23 | #endif 24 | 25 | #ifdef USE_AW_MALLOC 26 | V aw_malloc_init(),*aw_malloc(size_t n),*aw_calloc(size_t n,size_t sz),*aw_realloc(V*p,size_t n),aw_free(V*p);//! posix wrappers for benchmarking 27 | #endif 28 | 29 | //:~ 30 | -------------------------------------------------------------------------------- /m/.gitignore: -------------------------------------------------------------------------------- 1 | m 2 | *.dSYM 3 | bench 4 | leak 5 | stress 6 | libtm* 7 | cfrac_* 8 | leak_* 9 | stress_* 10 | cf_* 11 | -------------------------------------------------------------------------------- /m/BENCH.md: -------------------------------------------------------------------------------- 1 | ## mimalloc-bench howto 2 | 3 | ``` 4 | git clone https://github.com/daanx/mimalloc-bench.git bench && cd bench 5 | ``` 6 | 7 | ### linux 8 | 9 | ``` 10 | ./build-bench-env.sh all 11 | ``` 12 | 13 | ### linux (w/o ninja) 14 | 15 | ``` 16 | ./build-bench-env.sh all no-hd no-je no-rp no-sn no-mesh no-bench 17 | ``` 18 | 19 | ### darwin (nyi) 20 | 21 | ``` 22 | #./build-bench-env.sh all no-tc no-hd no-rp no-sn no-sm no-mesh no-lean no-redis... 23 | ``` 24 | 25 | ### supported mallocs and tests 26 | 27 | ``` 28 | mkdir -p out/bench && cd out/bench 29 | ../../bench.sh --help 30 | ``` 31 | 32 | ### all mallocs on all benchmarks: 33 | 34 | ``` 35 | ../../bench.sh alla allt 36 | ``` 37 | 38 | ### mimalloc and tcmalloc on cfrac and larson with 16 threads 39 | 40 | ``` 41 | ../../bench.sh --procs=16 mi tc cfrac larson 42 | ``` 43 | 44 | `/:~` -------------------------------------------------------------------------------- /m/README.md: -------------------------------------------------------------------------------- 1 | # thi.ng/tinyalloc 2 | 3 | Tiny replacement for `malloc` / `free` in unmanaged, linear memory situations, e.g. [WASM](http://webassembly.org) and [embedded devices](https://github.com/thi-ng/ws-ldn-12). 4 | 5 | ## Features 6 | 7 | - written in standalone C11, no dependencies, C runtime or syscalls used 8 | - configurable address region (and max. block count) for heap space 9 | - configurable pointer alignment in heap space 10 | - optional compaction of consecutive free blocks 11 | - optional block splitting during alloc (if re-using larger free'd blocks) 12 | - tiny, the WASM binary is 1.5KB (1.1KB w/ compaction disabled) 13 | 14 | ## Details 15 | 16 | **tinyalloc** maintains 3 linked lists: fresh blocks, used blocks, free blocks. All lists are stored in the same fixed sized array so the memory overhead can be controlled at compile time via the [configuration vars](#configuration) listed below. During initialization all blocks are added to the list of fresh blocks. 17 | 18 | The difference between free & fresh blocks is the former already have an associated heap address and size from previous usage. OTOH fresh blocks are uninitialized and are only used if no existing free blocks satisfy an allocation request. 19 | 20 | The diagram illustrates the state of having 1 freed block (green), 2 used blocks (red) and the beginning of the fresh (unused) block list: 21 | 22 | ![memory layout](tinyalloc.png) 23 | 24 | ### Allocation 25 | 26 | When a new chunk of memory is requested, all previously freed blocks are checked for potential re-use. If a block is found, is larger than the requested size and the size difference is greater than the configured threshold (`TA_SPLIT_THRESH`), then the block is first split, the chunks added to the used & free lists respectively and the pointer to the first chunk returned to the user. If no blocks in the free list qualify, a new block is allocated at the current heap top address, moved from the "fresh" to the "used" block list and the pointer returned to the caller. 27 | 28 | Note: All returned pointers are aligned to `TA_ALIGN` word boundaries. Same goes for allocated block sizes. Also, allocation will fail when all blocks in the fixed size block array are used, even though there might still be ample space in the heap memory region... 29 | 30 | ### Freeing & compaction 31 | 32 | The list of freed blocks is sorted by block start address. When a block is being freed, **tinyalloc** uses insertion sort to add the block at the right list position and then runs a compaction procedure, merging blocks as long as they form consecutive chunks of memory (with no gaps in between them). The resulting obsolete blocks are re-added to the list of available blocks. 33 | 34 | ## API 35 | 36 | ### ta\_init(void \*base, void \*limit, size_t heap_blocks, size_t split_thresh, size_t alignment) 37 | 38 | Initializes the control datastructure. MUST be called prior to any other **tinyalloc** function. 39 | 40 | | Argument | Description | 41 | |----------|-------------| 42 | | `base` | Address of **tinyalloc** control structure, typically at the beginning of your heap | 43 | | `limit` | Heap space end address | 44 | | `heap_blocks` | Max. number of memory chunks (e.g. 256) | 45 | | `split_thresh` | Size threshold for splitting chunks (a good default is 16) | 46 | | `alignment` | Word size for pointer alignment (e.g. 8) | 47 | 48 | - `alignment` is assumed to be >= native word size 49 | - `base` must be an address in RAM (on embedded devices) 50 | 51 | ### void* ta\_alloc(size\_t num) 52 | 53 | Like standard `malloc`, returns aligned pointer to address in heap space, or `NULL` if allocation failed. 54 | 55 | ### void* ta\_calloc(size\_t num, size\_t t) 56 | 57 | Like standard `calloc`, returns aligned pointer to zeroed memory in heap space, or `NULL` if allocation failed. 58 | 59 | ### bool ta\_free(void \*ptr) 60 | 61 | Like `free`, but returns boolean result (true, if freeing succeeded). By default, any consecutive memory blocks are being merged during the freeing operation. 62 | 63 | ### bool ta\_check() 64 | 65 | Structural validation. Returns `true` if internal heap structure is ok. 66 | 67 | ## Building 68 | 69 | ### Configuration 70 | 71 | | Define | Default | Comment | 72 | |--------|---------|---------| 73 | | `TA_DEBUG` | undefined | Trace debug information | 74 | | `TA_DISABLE_COMPACT` | undefined | Disable free block compaction | 75 | | `TA_DISABLE_SPLIT` | undefined | Disable free block splitting during re-alloc | 76 | 77 | On a 32bit system, the default configuration causes an overhead of 3088 bytes in RAM, but can be reduced if fewer memory blocks are needed. 78 | 79 | **Notes:** 80 | 81 | If building in debug mode (if `TA_DEBUG` symbol is defined), two externally defined functions are required: 82 | 83 | - `print_s(char *)` - to print a single string 84 | - `print_i(size_t)` - to print a single unsigned int 85 | 86 | ### Building for WASM 87 | 88 | (Requires [emscripten](http://emscripten.org)) 89 | 90 | ```sh 91 | emcc -Oz -s WASM=1 -s SIDE_MODULE=1 -o tinyalloc.wasm tinyalloc.c 92 | ``` 93 | 94 | #### Disassemble to WAST 95 | 96 | (Requires [WABT](https://github.com/WebAssembly/wabt)) 97 | 98 | ```sh 99 | wasm2wast --generate-names tinyalloc.wasm > tinyalloc.wast 100 | ``` 101 | 102 | ## License 103 | 104 | © 2016 - 2017 Karsten Schmidt - Apache Software License 2.0 (see [LICENSE](./LICENSE)) 105 | -------------------------------------------------------------------------------- /m/RESULTS.md: -------------------------------------------------------------------------------- 1 | `$ make leak && make stress && make cfrac` 2 | 3 | ## leak 4 | 5 | ``` 6 | leak ta_malloc (split+compact) 7 | 8 | ta_test_init blk 256 heap 62g phys 251g 9 | using 1 thread with a 100% load-per-thread and 40000 iterations (ta_malloc) 10 | 0.18user 0.68system 0:00.78elapsed 1712maxresident 11 | 12 | leak ta_malloc (no split) 13 | 14 | ta_test_init blk 256 heap 62g phys 251g 15 | using 1 thread with a 100% load-per-thread and 40000 iterations (ta_malloc) 16 | 0.16user 0.68system 0:00.75elapsed 1600maxresident 17 | 18 | leak sys_malloc 19 | 20 | using 1 thread with a 100% load-per-thread and 40000 iterations (sys_malloc) 21 | 0.17user 0.67system 0:00.76elapsed 3496maxresident 22 | 23 | leak aw_malloc 24 | 25 | using 1 thread with a 100% load-per-thread and 40000 iterations (aw_malloc) 26 | 0.18user 0.65system 0:00.75elapsed 5768maxresident 27 | ``` 28 | 29 | ## stress 30 | 31 | ``` 32 | stress sys_realloc 33 | 34 | using 1 thread with a 100% load-per-thread and 32 iterations (sys_malloc) 35 | 9.19user 14.38system 0:23.66elapsed 1172932maxresident 36 | 37 | stress aw_realloc 38 | 39 | aw_malloc_init ok 40 | using 1 thread with a 100% load-per-thread and 32 iterations (aw_malloc) 41 | 11.51user 0.36system 0:11.95elapsed 1922696maxresident)k 42 | ``` 43 | 44 | ## cfrac 45 | 46 | ``` 47 | cfrac ta_malloc (split+compact) 48 | 49 | ta_test_init blk 2048 heap 62g phys 251g 50 | 175451865205073170563711388363 = 374456281610909315237213 * 468551 51 | 0.38user 0.00system 0:00.39elapsed 2440maxresident 52 | 53 | cfrac ta_malloc (no split) 54 | 55 | ta_test_init blk 2048 heap 62g phys 251g 56 | 175451865205073170563711388363 = 374456281610909315237213 * 468551 57 | 0.24user 0.00system 0:00.24elapsed 3716maxresident 58 | 59 | cfrac sys_malloc 60 | 61 | 175451865205073170563711388363 = 374456281610909315237213 * 468551 62 | 0.10user 0.00system 0:00.10elapsed 2204maxresident 63 | 64 | cfrac aw_malloc 65 | 66 | aw_malloc_init ok 67 | 175451865205073170563711388363 = 374456281610909315237213 * 468551 68 | 0.09user 0.00system 0:00.09elapsed 6324maxresident 69 | ``` 70 | 71 | ## env 72 | 73 | ``` 74 | $ uname -a 75 | Linux kei 5.7.10-1.el8.elrepo.x86_64 #1 SMP Wed Jul 22 08:30:51 EDT 2020 x86_64 x86_64 x86_64 GNU/Linux 76 | 77 | $ free -h 78 | total used free shared buff/cache available 79 | Mem: 251Gi 3.5Gi 230Gi 90Mi 17Gi 246Gi 80 | 81 | $ sysctl vm.* 82 | vm.overcommit_memory = 0 83 | vm.swappiness = 10 84 | vm.oom_kill_allocating_task = 0 85 | vm.swappiness = 10 86 | 87 | $ cat /proc/cpuinfo 88 | ... 89 | processor : 39 90 | cpu family : 6 91 | model : 79 92 | model name : Intel(R) Xeon(R) CPU E5-2630 v4 @ 2.20GHz 93 | stepping : 1 94 | microcode : 0xb000036 95 | cpu MHz : 2711.071 96 | cache size : 25600 KB 97 | ``` 98 | 99 | `/:~` 100 | -------------------------------------------------------------------------------- /m/cfrac/README.md: -------------------------------------------------------------------------------- 1 | pcfrac: Implementation of the continued fraction factoring algoritm 2 | 3 | Every two digits additional appears to double the factoring time 4 | 5 | Written by Dave Barrett (barrett%asgard@boulder.Colorado.EDU) 6 | -------------------------------------------------------------------------------- /m/cfrac/asm16bit.h: -------------------------------------------------------------------------------- 1 | /* 2 | * HP-UX C compiler conventions 3 | * 4 | * Args pushed right-to-left; caller pops args on return 5 | * Function result returned in d0 or d0(msb) d1(lsb) pair 6 | * Called function must preserve all registers except d0,d1,a0,a1 7 | * C Registers are allocated from top-to-bottem in text from d7-d2, a5-a2 8 | */ 9 | #ifdef __STDC__ 10 | extern digit memaddw(digitPtr, digitPtr, digitPtr, posit); 11 | extern digit memsubw(digitPtr, digitPtr, digitPtr, posit); 12 | 13 | extern digit memincw(digitPtr, accumulator); 14 | extern digit memdecw(digitPtr, accumulator); 15 | 16 | extern digit memmulw(digitPtr, digitPtr, posit, digitPtr, posit); 17 | 18 | extern digit memdivw(digitPtr, digitPtr, posit, digitPtr); 19 | extern digit memdivw1(digitPtr, digitPtr, posit, digit); 20 | extern digit memmulw1(digitPtr, digitPtr, posit, digit); 21 | extern digit memmodw1(digitPtr, posit, digit); 22 | 23 | extern void memlsrw(digitPtr, posit); 24 | #else 25 | extern digit memaddw(); 26 | extern digit memsubw(); 27 | 28 | extern digit memincw(); 29 | extern digit memdecw(); 30 | 31 | extern digit memmulw(); 32 | 33 | extern digit memdivw(); 34 | extern digit memdivw1(); 35 | extern digit memmulw1(); 36 | extern digit memmodw1(); 37 | 38 | extern void memlsrw(); 39 | #endif 40 | -------------------------------------------------------------------------------- /m/cfrac/atop.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "pdefs.h" 3 | #include "pcvt.h" 4 | #include "precision.h" 5 | 6 | /* 7 | * ascii to precision (modeled after atoi) 8 | * leading whitespace skipped 9 | * an optional leading '-' or '+' followed by digits '0'..'9' 10 | * leading 0's Ok 11 | * stops at first unrecognized character 12 | * 13 | * Returns: pUndef if an invalid argument (pUndef or nondigit as 1st digit) 14 | */ 15 | precision atop(chp) 16 | register char *chp; 17 | { 18 | precision res = pUndef; 19 | precision clump = pUndef; 20 | int sign = 0; 21 | register int ch; 22 | register accumulator temp; 23 | accumulator x; 24 | register int i; 25 | 26 | if (chp != (char *) 0) { 27 | while (isspace(*chp)) chp++; /* skip whitespace */ 28 | if (*chp == '-') { 29 | sign = 1; 30 | ++chp; 31 | } else if (*chp == '+') { 32 | ++chp; 33 | } 34 | if (isdigit(ch = * (unsigned char *) chp)) { 35 | pset(&res, pzero); 36 | pset(&clump, utop(aDigit)); 37 | do { 38 | i = aDigitLog-1; 39 | temp = ch - '0'; 40 | do { 41 | if (!isdigit(ch = * (unsigned char *) ++chp)) goto atoplast; 42 | temp = temp * aBase + (ch - '0'); 43 | } while (--i > 0); 44 | pset(&res, padd(pmul(res, clump), utop(temp))); 45 | } while (isdigit(ch = * (unsigned char *) ++chp)); 46 | goto atopdone; 47 | atoplast: 48 | x = aBase; 49 | while (i++ < aDigitLog-1) { 50 | x *= aBase; 51 | } 52 | pset(&res, padd(pmul(res, utop(x)), utop(temp))); 53 | atopdone: 54 | if (sign) { 55 | pset(&res, pneg(res)); 56 | } 57 | } 58 | } 59 | pdestroy(clump); 60 | return presult(res); 61 | } 62 | -------------------------------------------------------------------------------- /m/cfrac/atop.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/atop.o -------------------------------------------------------------------------------- /m/cfrac/cfrac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/cfrac -------------------------------------------------------------------------------- /m/cfrac/cfrac.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include /* for findk */ 4 | 5 | #if defined(_WIN32) 6 | #include 7 | #endif 8 | 9 | #include "pdefs.h" 10 | 11 | #ifdef __STDC__ 12 | #include 13 | #endif 14 | #include "precision.h" 15 | #include "pfactor.h" 16 | 17 | #ifdef __STDC__ 18 | extern unsigned *pfactorbase(precision n, unsigned k, 19 | unsigned *m, unsigned aborts); 20 | extern double pomeranceLpow(double n, double alpha); 21 | #else 22 | extern unsigned *pfactorbase(); 23 | extern double pomeranceLpow(); 24 | #endif 25 | 26 | int verbose = 0; 27 | int debug = 0; 28 | 29 | extern unsigned cfracNabort; 30 | extern unsigned cfracTsolns; 31 | extern unsigned cfracPsolns; 32 | extern unsigned cfracT2solns; 33 | extern unsigned cfracFsolns; 34 | 35 | 36 | extern unsigned short primes[]; 37 | extern unsigned primesize; 38 | 39 | /* 40 | * Return the value of "f(p,d)" from Knuth's exercise 28 41 | */ 42 | float pfKnuthEx28(p, d) 43 | unsigned p; 44 | precision d; 45 | { 46 | register float res; 47 | precision k = pUndef; 48 | 49 | (void) pparm(d); 50 | if (p == 2) { 51 | if (peven(d)) { 52 | pset(&k, phalf(d)); 53 | if (peven(k)) { 54 | res = 2.0/3.0 + pfKnuthEx28(2,k)/2.0; /* eliminate powers of 2 */ 55 | } else { /* until only one 2 left in d. */ 56 | res = 1.0/3.0; /* independent of (the now odd) k. Wow! */ 57 | } 58 | } else { /* d now odd */ 59 | pset(&k, phalf(d)); 60 | if (podd(k)) { 61 | res = 1.0/3.0; /* f(2,4k+3): d%8 == 3 or 7 */ 62 | } else { 63 | if (podd(phalf(k))) { 64 | res = 2.0/3.0; /* f(2,8k+5): d%8 == 5 */ 65 | } else { 66 | res = 4.0/3.0; /* f(2,8k+1): d%8 == 1 */ 67 | } 68 | } 69 | } 70 | } else { /* PART 3: p odd, d could still be even (OK) */ 71 | pset(&k, utop(p)); 72 | if peq(ppowmod(d, phalf(psub(k, pone)), k), pone) { 73 | res = (float) (p+p) / (((float) p)*p-1.0); /* beware int overflow! */ 74 | } else { 75 | res = 0.0; 76 | } 77 | } 78 | 79 | pdestroy(k); 80 | pdestroy(d); 81 | if (debug > 1) { 82 | fprintf(stdout, "f(%u,", p); 83 | fprintf(stdout, "d) = %9.7f\n", res); 84 | } 85 | return res; 86 | } 87 | 88 | float cfrac_logf(unsigned p, precision n, unsigned k) 89 | { 90 | register float res; 91 | 92 | (void) pparm(n); 93 | 94 | #if 0 /* old code for non-float machines; not worth the cost */ 95 | pset(&r, utop(k)); 96 | log2sqrtk = plogb(pipow(r, q >> 1), ptwo); 97 | fplog2p = (f(p,pmul(r,n),q) * plogb(pipow(utop(p),q),ptwo)+(q>>1))/q; 98 | #endif 99 | 100 | res = pfKnuthEx28(p, pmul(itop(k),n)) * log((double) p); 101 | /* res -= log((double) k) * 0.5; */ 102 | 103 | pdestroy(n); 104 | return res; 105 | } 106 | 107 | /* 108 | * Find the best value of k for the given n and m. 109 | * 110 | * Input/Output: 111 | * n - the number to factor 112 | * m - pointer to size of factorbase (0 = select "best" size) 113 | * aborts - the number of early aborts 114 | */ 115 | unsigned findk(n, m, aborts, maxk) 116 | precision n; 117 | register unsigned *m; 118 | unsigned aborts, maxk; 119 | { 120 | unsigned k, bestk = 0, count, bestcount = 0, maxpm; 121 | float sum, max = -1.0E+15; /* should be small enough */ 122 | unsigned *p; 123 | register unsigned i; 124 | register unsigned short *primePtr; 125 | 126 | (void) pparm(n); 127 | 128 | for (k = 1; k < maxk; k++) { /* maxk should best be m+m? */ 129 | if (debug) { 130 | fputs("kN = ", stdout); 131 | fputp(stdout, pmul(utop(k), n)); putc('\n', stdout); 132 | } 133 | count = *m; 134 | p = pfactorbase(n, k, &count, aborts); 135 | if (p == (unsigned *) 0) { 136 | fprintf(stderr, "couldn't compute factor base in findk\n"); 137 | exit(1); 138 | } 139 | 140 | maxpm = p[count-1]; 141 | 142 | sum = 0.0; 143 | primePtr = primes; 144 | while (*primePtr <= maxpm) { 145 | sum += cfrac_logf((unsigned) *primePtr++, n, k); 146 | } 147 | sum -= log((double) k) * 0.5; 148 | if (verbose > 2) fprintf(stdout, "%u: %5.2f", k, sum); 149 | if (debug) fprintf(stdout, " log(k)/2=%5.2f", log((double) k) * 0.5); 150 | if (verbose > 2) { 151 | fputs("\n", stdout); 152 | fflush(stdout); 153 | } 154 | if (sum > max) { 155 | max = sum; 156 | bestk = k; 157 | bestcount = count; 158 | } 159 | #ifndef IGNOREFREE 160 | free(p); 161 | #endif 162 | } 163 | 164 | *m = bestcount; 165 | pdestroy(n); 166 | return bestk; 167 | } 168 | 169 | extern char *optarg; 170 | extern int optind; 171 | 172 | char *progName; 173 | 174 | extern int getopt(); 175 | 176 | int main(argc, argv) 177 | int argc; 178 | char *argv[]; 179 | { 180 | 181 | #ifdef CUSTOM_MALLOC_INIT 182 | CUSTOM_MALLOC_INIT(); 183 | #endif 184 | 185 | unsigned m = 0, k = 0; 186 | unsigned maxCount = 1<<30, count, maxk = 0; 187 | int ch; 188 | precision n = pUndef, f = pUndef; 189 | unsigned aborts = 3; 190 | unsigned *p; 191 | double d; 192 | 193 | progName = *argv; 194 | 195 | while ((ch = getopt(argc, argv, "a:k:i:dv")) != EOF) switch (ch) { 196 | case 'a': 197 | aborts = atoi(optarg); 198 | break; 199 | case 'k': 200 | maxk = atoi(optarg); 201 | break; 202 | case 'i': 203 | maxCount = atoi(optarg); 204 | break; 205 | case 'd': 206 | debug++; 207 | break; 208 | case 'v': 209 | verbose++; 210 | break; 211 | default: 212 | usage: fprintf(stderr, 213 | "usage: %s [-dv] [-a aborts ] [-k maxk ] [-i maxCount ] n [[ m ] k ]\n", 214 | progName); 215 | return 1; 216 | } 217 | argc -= optind; 218 | argv += optind; 219 | 220 | if (argc == 0) { 221 | argc = 1; 222 | static char* argvx[2] = { "17545186520507317056371138836327483792736", NULL }; 223 | argv = argvx; 224 | } 225 | 226 | if (argc < 1 || argc > 3) goto usage; 227 | 228 | pset(&n, atop(*argv++)); --argc; 229 | if (argc) { m = atoi(*argv++); --argc; } 230 | if (argc) { k = atoi(*argv++); --argc; } 231 | 232 | if (k == 0) { 233 | if (maxk == 0) { 234 | maxk = m / 2 + 5; 235 | if (verbose) fprintf(stdout, "maxk = %u\n", maxk); 236 | } 237 | k = findk(n, &m, aborts, maxk); 238 | if (verbose) { 239 | fprintf(stdout, "k = %u\n", k); 240 | } 241 | } 242 | 243 | count = maxCount; 244 | 245 | pcfracInit(m, k, aborts); 246 | 247 | pset(&f, pcfrac(n, &count)); 248 | count = maxCount - count; 249 | if (verbose) { 250 | putc('\n', stdout); 251 | fprintf(stdout, "Iterations : %u\n", count); 252 | fprintf(stdout, "Early Aborts : %u\n", cfracNabort); 253 | fprintf(stdout, "Total Partials : %u\n", cfracTsolns); 254 | fprintf(stdout, "Used Partials : %u\n", cfracT2solns); 255 | fprintf(stdout, "Full Solutions : %u\n", cfracPsolns); 256 | fprintf(stdout, "Factor Attempts: %u\n", cfracFsolns); 257 | } 258 | 259 | if (f != pUndef) { 260 | fputp(stdout, n); 261 | fputs(" = ", stdout); 262 | fputp(stdout, f); 263 | fputs(" * ", stdout); 264 | pdivmod(n, f, &n, pNull); 265 | fputp(stdout, n); 266 | putc('\n', stdout); 267 | } 268 | 269 | pdestroy(f); 270 | pdestroy(n); 271 | 272 | return 0; 273 | } 274 | -------------------------------------------------------------------------------- /m/cfrac/cfrac.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/cfrac.o -------------------------------------------------------------------------------- /m/cfrac/errorp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "precision.h" 3 | 4 | /* 5 | * Fatal error (user substitutable) 6 | * 7 | * PNOMEM - out of memory (pcreate) 8 | * PREFCOUNT - refcount negative (pdestroy) 9 | * PUNDEFINED - undefined value referenced (all) 10 | * PDOMAIN - domain error 11 | * pdivmod: divide by zero 12 | * psqrt: negative argument 13 | * POVERFLOW - overflow 14 | * itop: too big 15 | */ 16 | precision errorp(errnum, routine, message) 17 | int errnum; 18 | char *routine; 19 | char *message; 20 | { 21 | fputs(routine, stderr); 22 | fputs(": ", stderr); 23 | fputs(message, stderr); 24 | fputs("\n", stderr); 25 | abort(); /* remove this line if you want */ 26 | return pUndef; 27 | } 28 | -------------------------------------------------------------------------------- /m/cfrac/errorp.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/errorp.o -------------------------------------------------------------------------------- /m/cfrac/getopt.h: -------------------------------------------------------------------------------- 1 | /* Declarations for getopt. 2 | Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc. 3 | 4 | This program is free software; you can redistribute it and/or modify it 5 | under the terms of the GNU General Public License as published by the 6 | Free Software Foundation; either version 2, or (at your option) any 7 | later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. */ 13 | 14 | #ifndef _GETOPT_H 15 | #define _GETOPT_H 1 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | /* For communication from `getopt' to the caller. 22 | When `getopt' finds an option that takes an argument, 23 | the argument value is returned here. 24 | Also, when `ordering' is RETURN_IN_ORDER, 25 | each non-option ARGV-element is returned here. */ 26 | 27 | extern char *optarg; 28 | 29 | /* Index in ARGV of the next element to be scanned. 30 | This is used for communication to and from the caller 31 | and for communication between successive calls to `getopt'. 32 | 33 | On entry to `getopt', zero means this is the first call; initialize. 34 | 35 | When `getopt' returns EOF, this is the index of the first of the 36 | non-option elements that the caller should itself scan. 37 | 38 | Otherwise, `optind' communicates from one call to the next 39 | how much of ARGV has been scanned so far. */ 40 | 41 | extern int optind; 42 | 43 | /* Callers store zero here to inhibit the error message `getopt' prints 44 | for unrecognized options. */ 45 | 46 | extern int opterr; 47 | 48 | /* Set to an option character which was unrecognized. */ 49 | 50 | extern int optopt; 51 | 52 | /* Describe the long-named options requested by the application. 53 | The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector 54 | of `struct option' terminated by an element containing a name which is 55 | zero. 56 | 57 | The field `has_arg' is: 58 | no_argument (or 0) if the option does not take an argument, 59 | required_argument (or 1) if the option requires an argument, 60 | optional_argument (or 2) if the option takes an optional argument. 61 | 62 | If the field `flag' is not NULL, it points to a variable that is set 63 | to the value given in the field `val' when the option is found, but 64 | left unchanged if the option is not found. 65 | 66 | To have a long-named option do something other than set an `int' to 67 | a compiled-in constant, such as set a value from `optarg', set the 68 | option's `flag' field to zero and its `val' field to a nonzero 69 | value (the equivalent single-letter option character, if there is 70 | one). For long options that have a zero `flag' field, `getopt' 71 | returns the contents of the `val' field. */ 72 | 73 | struct option 74 | { 75 | #if __STDC__ 76 | const char *name; 77 | #else 78 | char *name; 79 | #endif 80 | /* has_arg can't be an enum because some compilers complain about 81 | type mismatches in all the code that assumes it is an int. */ 82 | int has_arg; 83 | int *flag; 84 | int val; 85 | }; 86 | 87 | /* Names for the values of the `has_arg' field of `struct option'. */ 88 | 89 | #define no_argument 0 90 | #define required_argument 1 91 | #define optional_argument 2 92 | 93 | #if __STDC__ 94 | /* Many other libraries have conflicting prototypes for getopt, with 95 | differences in the consts, in stdlib.h. We used to try to prototype 96 | it if __GNU_LIBRARY__ but that wasn't problem free either (I'm not sure 97 | exactly why), and there is no particular need to prototype it. 98 | We really shouldn't be trampling on the system's namespace at all by 99 | declaring getopt() but that is a bigger issue. */ 100 | extern int getopt (); 101 | 102 | extern int getopt_long (int argc, char *const *argv, const char *shortopts, 103 | const struct option *longopts, int *longind); 104 | extern int getopt_long_only (int argc, char *const *argv, 105 | const char *shortopts, 106 | const struct option *longopts, int *longind); 107 | 108 | /* Internal only. Users should not call this directly. */ 109 | extern int _getopt_internal (int argc, char *const *argv, 110 | const char *shortopts, 111 | const struct option *longopts, int *longind, 112 | int long_only); 113 | #else /* not __STDC__ */ 114 | extern int getopt (); 115 | extern int getopt_long (); 116 | extern int getopt_long_only (); 117 | 118 | extern int _getopt_internal (); 119 | #endif /* not __STDC__ */ 120 | 121 | #ifdef __cplusplus 122 | } 123 | #endif 124 | 125 | #endif /* _GETOPT_H */ 126 | -------------------------------------------------------------------------------- /m/cfrac/getopt.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/getopt.o -------------------------------------------------------------------------------- /m/cfrac/itop.c: -------------------------------------------------------------------------------- 1 | #include "pdefs.h" 2 | #include "pcvt.h" 3 | #include "precision.h" 4 | 5 | /* 6 | * Integer to Precision 7 | */ 8 | precision itop(i) 9 | register int i; 10 | { 11 | register digitPtr uPtr; 12 | register precision u = palloc(INTSIZE); 13 | 14 | if (u == pUndef) return u; 15 | 16 | if (u->sign = (i < 0)) i = -i; 17 | uPtr = u->value; 18 | do { 19 | *uPtr++ = modBase(i); 20 | i = divBase(i); 21 | } while (i != 0); 22 | 23 | u->size = (uPtr - u->value); /* normalize */ 24 | return presult(u); 25 | } 26 | -------------------------------------------------------------------------------- /m/cfrac/itop.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/itop.o -------------------------------------------------------------------------------- /m/cfrac/ltop.c: -------------------------------------------------------------------------------- 1 | #include "pdefs.h" 2 | #include "pcvt.h" 3 | #include "precision.h" 4 | 5 | /* 6 | * Long to Precision 7 | */ 8 | precision ltop(l) 9 | register long l; 10 | { 11 | register digitPtr uPtr; 12 | register precision u = palloc(LONGSIZE); 13 | 14 | if (u == pUndef) return u; 15 | 16 | if (u->sign = (l < 0L)) l = -l; 17 | uPtr = u->value; 18 | do { 19 | *uPtr++ = modBase(l); 20 | l = divBase(l); 21 | } while (l != 0); 22 | 23 | u->size = (uPtr - u->value); /* normalize */ 24 | return presult(u); 25 | } 26 | -------------------------------------------------------------------------------- /m/cfrac/ltop.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/ltop.o -------------------------------------------------------------------------------- /m/cfrac/pabs.c: -------------------------------------------------------------------------------- 1 | #include "pdefs.h" /* private include file */ 2 | #include "precision.h" /* public include file for forward refs */ 3 | #include 4 | 5 | /* 6 | * absolute value 7 | */ 8 | precision pabs(u) 9 | register precision u; 10 | { 11 | register precision w; 12 | 13 | (void) pparm(u); 14 | w = palloc(u->size); 15 | if (w == pUndef) return w; 16 | 17 | w->sign = false; 18 | (void) memcpy(w->value, u->value, u->size * sizeof(digit)); 19 | 20 | pdestroy(u); 21 | return presult(w); 22 | } 23 | -------------------------------------------------------------------------------- /m/cfrac/pabs.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/pabs.o -------------------------------------------------------------------------------- /m/cfrac/padd.c: -------------------------------------------------------------------------------- 1 | #include "pdefs.h" 2 | #include "precision.h" 3 | #include 4 | 5 | #ifdef ASM_16BIT 6 | #include "asm16bit.h" 7 | #endif 8 | 9 | /* 10 | * Add 11 | * 12 | * This will work correctly if -0 is passed as input 13 | */ 14 | precision padd(u, v) 15 | register precision v; 16 | #ifndef ASM_16BIT 17 | precision u; 18 | { 19 | register digitPtr wPtr, uPtr, vPtr; 20 | #else 21 | register precision u; 22 | { 23 | register digitPtr wPtr; 24 | digitPtr uPtr; 25 | #endif 26 | precision w; /* function result */ 27 | register accumulator temp; /* 0 <= temp < 2*base */ 28 | register digit carry; /* 0 <= carry <= 1 */ 29 | #ifdef ASM_16BIT 30 | register int size; 31 | #endif 32 | 33 | (void) pparm(u); 34 | (void) pparm(v); 35 | if (u->sign != v->sign) { /* Are we are actually subtracting? */ 36 | w = pUndef; 37 | if (v->sign) { 38 | v->sign = !v->sign; /* can't generate -0 */ 39 | pset(&w, psub(u, v)); 40 | v->sign = !v->sign; 41 | } else { 42 | u->sign = !u->sign; /* can't generate -0 */ 43 | pset(&w, psub(v, u)); 44 | u->sign = !u->sign; 45 | } 46 | } else { 47 | if (u->size < v->size) { /* u is always biggest number */ 48 | w = u; u = v; v = w; 49 | } 50 | 51 | w = palloc(u->size+1); /* there is at most one added digit */ 52 | if (w == pUndef) return w; /* arguments not destroyed */ 53 | 54 | w->sign = u->sign; 55 | 56 | uPtr = u->value; 57 | wPtr = w->value; 58 | #ifndef ASM_16BIT 59 | vPtr = v->value; 60 | carry = 0; 61 | do { /* Add digits in both args */ 62 | temp = *uPtr++ + *vPtr++; /* 0 <= temp < 2*base-1 */ 63 | temp += carry; /* 0 <= temp < 2*base */ 64 | carry = divBase(temp); /* 0 <= carry <= 1 */ 65 | *wPtr++ = modBase(temp); /* mod has positive args */ 66 | } while (vPtr < v->value + v->size); 67 | 68 | while (uPtr < u->value + u->size) { /* propogate carry */ 69 | temp = *uPtr++ + carry; 70 | carry = divBase(temp); 71 | *wPtr++ = modBase(temp); 72 | } 73 | *wPtr = carry; 74 | #else 75 | size = v->size; 76 | temp = u->size - size; 77 | carry = memaddw(wPtr, uPtr, v->value, size); 78 | if (temp > 0) { 79 | memcpy(wPtr + size, uPtr + size, temp * sizeof(digit)); 80 | if (carry) { 81 | carry = memincw(wPtr + size, temp); 82 | } 83 | } 84 | wPtr[u->size] = carry; /* yes, I do mean u->size */ 85 | #endif 86 | if (carry == 0) { 87 | --(w->size); 88 | } 89 | } 90 | 91 | pdestroy(u); 92 | pdestroy(v); 93 | return presult(w); 94 | } 95 | -------------------------------------------------------------------------------- /m/cfrac/padd.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/padd.o -------------------------------------------------------------------------------- /m/cfrac/pcfrac.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/pcfrac.o -------------------------------------------------------------------------------- /m/cfrac/pcmp.c: -------------------------------------------------------------------------------- 1 | #include "pdefs.h" 2 | #include "precision.h" 3 | 4 | /* 5 | * Compare to zero (normalization not assumed) 6 | * 7 | * Returns same as pcmp(u, 0); 8 | */ 9 | int pcmpz(u) 10 | register precision u; 11 | { 12 | register digitPtr uPtr; 13 | register int i; 14 | 15 | (void) pparm(u); 16 | i = 0; 17 | uPtr = u->value; 18 | do { 19 | if (*uPtr++ != 0) { 20 | if (u->sign) i = -1; else i = 1; 21 | break; 22 | } 23 | } while (uPtr < u->value + u->size); 24 | 25 | pdestroy(u); 26 | return i; 27 | } 28 | 29 | /* 30 | * Compare u to v. 31 | * 32 | * Return: < 0 if u < v 33 | * = 0 if u = v 34 | * > 0 if u > v 35 | * 36 | * This routine is the one that assumes results are normalized! 37 | * - no leading 0's 38 | * - no negative 0 39 | */ 40 | int pcmp(u, v) 41 | precision u, v; 42 | { 43 | register digitPtr uPtr, vPtr; 44 | register int i; /* should be bigger than posit */ 45 | 46 | (void) pparm(u); 47 | (void) pparm(v); 48 | if (u->sign != v->sign) { 49 | if (u->sign) i = -1; else i = 1; 50 | } else { 51 | i = u->size - v->size; 52 | if (i == 0) { 53 | uPtr = u->value + u->size; 54 | vPtr = v->value + v->size; 55 | do { 56 | if (*--uPtr != *--vPtr) break; 57 | } while (vPtr > v->value); 58 | if (*uPtr > *vPtr) i = 1; 59 | else if (*uPtr < *vPtr) i = -1; 60 | } 61 | 62 | if (u->sign) i = -i; 63 | } 64 | 65 | pdestroy(u); 66 | pdestroy(v); 67 | return i; 68 | } 69 | -------------------------------------------------------------------------------- /m/cfrac/pcmp.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/pcmp.o -------------------------------------------------------------------------------- /m/cfrac/pconst.c: -------------------------------------------------------------------------------- 1 | #include "pdefs.h" 2 | 3 | static precisionType pzeroConst = { 4 | #ifndef BWGC 5 | (short) 1, /* refcount (read/write!) */ 6 | #endif 7 | (posit) 1, /* size */ 8 | (posit) 1, /* digitcount */ 9 | (boolean) 0, /* sign */ 10 | { (digit) 0 } /* value */ 11 | }; 12 | 13 | static precisionType poneConst = { 14 | #ifndef BWGC 15 | (short) 1, /* refcount (read/write!) */ 16 | #endif 17 | (posit) 1, /* size */ 18 | (posit) 1, /* digitcount */ 19 | (boolean) 0, /* sign */ 20 | { (digit) 1 } /* value */ 21 | }; 22 | 23 | static precisionType ptwoConst = { 24 | #ifndef BWGC 25 | (short) 1, /* refcount (read/write!) */ 26 | #endif 27 | (posit) 1, /* size */ 28 | (posit) 1, /* digitcount */ 29 | (boolean) 0, /* sign */ 30 | { (digit) 2 } /* value */ 31 | }; 32 | 33 | static precisionType p_oneConst = { 34 | #ifndef BWGC 35 | (short) 1, /* refcount (read/write!) */ 36 | #endif 37 | (posit) 1, /* size */ 38 | (posit) 1, /* digitcount */ 39 | (boolean) 1, /* sign */ 40 | { (digit) 1 } /* value */ 41 | }; 42 | 43 | precision pzero = &pzeroConst; /* zero */ 44 | precision pone = &poneConst; /* one */ 45 | precision ptwo = &ptwoConst; /* two */ 46 | precision p_one = &p_oneConst; /* negative one */ 47 | -------------------------------------------------------------------------------- /m/cfrac/pconst.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/pconst.o -------------------------------------------------------------------------------- /m/cfrac/pcvt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Machine dependent file used for conversion routines 3 | * (e.g. atop, ptoa, itop, ptoi, etc) 4 | */ 5 | 6 | /* 7 | * For pXtop: (X = {i,u,l,ul,d}) 8 | */ 9 | #define INTSIZE 2 /* floor(log[Base](2*(MAXINT+1))) */ 10 | #define LONGSIZE 2 /* floor(log[Base](2*(MAXLONG+1))) */ 11 | #define DOUBLESIZE 129 /* double precision size = log[base](HUGE) */ 12 | 13 | /* 14 | * For ptoX 15 | */ 16 | #define MAXINT (int) ((unsigned int) ~0 >> 1) 17 | #define MAXLONG (long) ((unsigned long) ~0 >> 1) 18 | #define MAXUNSIGNED (~ (unsigned int) 0) 19 | #define MAXUNSIGNEDLONG (~ (unsigned long) 0L) 20 | 21 | #define MAXACC (~ (accumulator) 0) 22 | 23 | /* 24 | * aBase - Ascii base (ptoa) 25 | * There are aDigits Ascii digits per precision digit, pDigits. 26 | * At least one of { aDigits, pDigits } <= (MAXINT / the maximum posit value). 27 | */ 28 | #define aDigits 525 /* aDigits/pDigits >~= log[aBase](Base) */ 29 | #define pDigits 109 /* 525/109=4.8165>log[10](65536)=4.816479931 */ 30 | #define aBase 10 /* string conversion base */ 31 | #define aDigit 1000000000 /* must be power of aBase < MAXINT */ 32 | #define aDigitLog 9 /* log[aBase] of aDigit */ 33 | -------------------------------------------------------------------------------- /m/cfrac/pdefs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * +------------------------------------------------------------------+ 3 | * | Private Math Library Definitions | 4 | * +------------------------------------------------------------------+ 5 | */ 6 | /* 7 | * Optional assembly language 8 | */ 9 | #ifdef ASM 10 | #include "machineop.h" /* 16-bit integer machine operations */ 11 | #define uModDiv(n, d, qp) umoddiv16(n, d, qp) /* slight help */ 12 | #else 13 | #define uModDiv(n, d, qp) (*(qp) = (n) / (d), (n) % (d)) 14 | #endif 15 | #define uMul(u, v) ((u) * (v)) /* fast enough */ 16 | 17 | /* 18 | * Optional alternate memory allocator 19 | */ 20 | 21 | #ifndef MYALLOC 22 | 23 | #include 24 | extern void*ta_malloc(size_t num),*ta_calloc(size_t num,size_t size);void ta_free(void*ptr); 25 | 26 | # if defined(BWGC) 27 | extern char *gc_malloc_atomic(); 28 | #define allocate(size) (char *) gc_malloc_atomic(size) 29 | # elif defined(CUSTOM_MALLOC) 30 | #define allocate(size) CUSTOM_MALLOC(size) 31 | # else 32 | /* extern char *malloc(); */ 33 | #define allocate(size) (char *) malloc(size) 34 | # endif 35 | 36 | #ifdef IGNOREFREE 37 | #define deallocate(p) {}; 38 | # elif defined(CUSTOM_FREE) 39 | #define deallocate(p) CUSTOM_FREE(p) 40 | #else 41 | /* 42 | extern int free(); 43 | */ 44 | #define deallocate(p) free(p) 45 | #endif 46 | 47 | #else 48 | extern char *allocate(); 49 | extern void deallocate(); 50 | #endif 51 | 52 | /* 53 | * These next four types are used only used in this include file 54 | */ 55 | #include 56 | typedef unsigned char u8; /* 8 bits */ 57 | typedef uint16_t u16; /* 16 bits */ 58 | typedef uint32_t u32; /* 32 bits */ 59 | typedef u8 boolean; /* 1 bit */ 60 | 61 | #define BASE 65536 /* Base * (Base-1) <= MAXINT */ 62 | 63 | /* 64 | * Operations on Base (unsigned math) 65 | */ 66 | #define modBase(u) ((u) & 0xffff) /* remainder on Base */ 67 | #define divBase(u) ((u) >> 16) /* divide by Base */ 68 | #define mulBase(u) ((u) << 16) /* multiply by Base */ 69 | 70 | /* 71 | * The type of a variable used to store intermediate results. 72 | * This should be the most efficient unsigned int on your machine. 73 | */ 74 | typedef u32 accumulator; /* 0..(Base * Base) - 1 */ 75 | 76 | /* 77 | * The type of a single digit 78 | */ 79 | typedef u16 digit; /* 0..Base-1 */ 80 | 81 | /* 82 | * The type of a digit index (the largest number of digits - 1) 83 | * Determines the maximum representable precision (not usually changed) 84 | */ 85 | typedef u16 posit; /* 0..size */ 86 | 87 | typedef unsigned short prefc; /* in precision.h also */ 88 | /* 89 | * End of area which needs to be modified 90 | */ 91 | 92 | #define false 0 93 | #define true 1 94 | 95 | typedef digit digitString[1]; /* dummy array type */ 96 | typedef digit *digitPtr; 97 | 98 | /* 99 | * A normalized integer has the following attributes: 100 | * -0 cannot occur 101 | * all digits >= size assumed to be 0. (no leading zero's) 102 | * size > 0 103 | */ 104 | typedef struct { 105 | #ifndef BWGC 106 | prefc refcount; /* reference count (must be 1st [for pref]) */ 107 | #endif 108 | posit alloc; /* allocated size */ 109 | posit size; /* number of digits */ 110 | boolean sign; /* sign: TRUE negative */ 111 | digitString value; 112 | } precisionType; 113 | 114 | typedef precisionType *precision; 115 | 116 | /* 117 | * Overlay for cache of precisions 118 | */ 119 | typedef struct { 120 | precision next; /* next item in list */ 121 | short count; /* number of items in this sublist */ 122 | } cacheType; 123 | 124 | typedef cacheType *cachePtr; 125 | /* 126 | * Maximum total memory consumed by cache = 127 | * LIMIT * (1 + SIZE * (PrecisionSize + sizeof(digit) * (SIZE-1) / 2)) 128 | */ 129 | #ifndef CACHESIZE 130 | #define CACHESIZE 32 /* size of allocation cache */ 131 | #endif 132 | #define CACHELIMIT 128 /* Determines max mem used by cache */ 133 | 134 | #define PrecisionSize (sizeof(precisionType) - sizeof(digitString)) 135 | 136 | /* 137 | * Function definitions are all in the global include file "mathdefs.h". 138 | */ 139 | extern precision palloc(); /* semi-private */ 140 | extern int pfree(); /* semi-private */ 141 | extern void pnorm(); /* semi-private */ 142 | -------------------------------------------------------------------------------- /m/cfrac/pdivmod.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/pdivmod.o -------------------------------------------------------------------------------- /m/cfrac/pfactor.c.bak: -------------------------------------------------------------------------------- 1 | #include 2 | #include "precision.h" 3 | #include "pfactor.h" 4 | 5 | void showfactors(); 6 | 7 | 8 | int main(argc, argv) 9 | int argc; 10 | char *argv[]; 11 | { 12 | precision n = pUndef; 13 | 14 | --argc; 15 | if (argc != 0) { 16 | do { 17 | pset(&n, atop(*++argv)); 18 | showfactors(n); 19 | } while (--argc > 0); 20 | } else { 21 | do { 22 | pset(&n, fgetp(stdin)); 23 | if (n == pUndef) break; 24 | showfactors(n); 25 | } while (1); 26 | } 27 | pdestroy(n); 28 | return 0; 29 | } 30 | 31 | void showfactors(n) 32 | precision n; 33 | { 34 | precision r = pUndef; 35 | FactorList factors = (FactorList) 0; 36 | 37 | (void) pparm(n); 38 | pset(&r, ptrial(n, (unsigned *) 0, &factors)); 39 | fputp(stdout, n); 40 | fputs(" = ", stdout); 41 | pputfactors(stdout, factors); 42 | if pne(r, pone) { 43 | if pne(r, n) putc('*', stdout); 44 | if (!pprime(r, 16)) { 45 | fputc('(', stdout); fputp(stdout, r); fputc(')', stdout); 46 | } else { 47 | fputp(stdout, r); 48 | } 49 | } 50 | putc('\n', stdout); 51 | 52 | pfreefactors(&factors); 53 | pdestroy(r); 54 | pdestroy(n); 55 | } 56 | -------------------------------------------------------------------------------- /m/cfrac/pfactor.h: -------------------------------------------------------------------------------- 1 | typedef struct Pfs { 2 | struct Pfs *next; 3 | precision factor; 4 | unsigned count; 5 | } Pfactor; 6 | 7 | typedef Pfactor *FactorPtr; 8 | typedef FactorPtr FactorList; 9 | typedef precision (*pfunc)(); /* pointer to func returning precision */ 10 | 11 | #ifndef __STDC__ 12 | 13 | extern int pprime(); /* test whether a number is prime */ 14 | extern precision pnextprime(); /* next prime >= it's argument */ 15 | 16 | extern precision pgcd(); /* greatest common divisor */ 17 | extern precision plcm(); /* least common multiple */ 18 | extern precision peuclid(); /* extended euclid's algorithm */ 19 | 20 | extern precision prho(); /* find factor using rho method */ 21 | extern precision pfermat(); /* find factor using Fermat's method */ 22 | extern precision pcfrac(); /* factor w/continued fractions */ 23 | 24 | extern int prhoInit(); /* alter parameters for rho method */ 25 | extern int pcfracInit(); /* alter paramteres for cfrac method */ 26 | 27 | extern precision ptrial(); /* find factors using trial division */ 28 | extern precision prfactor(); /* recursively factor a number */ 29 | 30 | extern void paddfactor(); /* add a factor to a factorlist */ 31 | extern void pputfactors(); /* print a factorlist */ 32 | extern void pfreefactors(); /* return a factorlist to memory */ 33 | 34 | #else 35 | 36 | extern int pprime(precision, unsigned trialCount); 37 | extern precision pnextprime(precision, unsigned trialCount); 38 | 39 | extern precision pgcd(precision, precision); 40 | extern precision plcm(precision, precision); 41 | extern precision peuclid(precision, precision, precision *, precision *); 42 | 43 | extern precision prho(precision n, unsigned *maxCount); 44 | extern precision pfermat(precision n, unsigned *maxCount); 45 | extern precision pcfrac(precision n, unsigned *maxCount); 46 | 47 | extern int prhoInit(precision c, unsigned batchSize); 48 | extern int pcfracInit(unsigned m, unsigned k, unsigned aborts); 49 | 50 | extern precision ptrial(precision n, unsigned *maxCount, FactorList *); 51 | extern precision prfactor(precision, unsigned *maxCount, pfunc, FactorList *); 52 | 53 | extern void paddfactor(FactorList *, precision); 54 | extern void pfreefactors(FactorList *); 55 | 56 | #ifndef BUFSIZE 57 | #include 58 | #endif 59 | 60 | extern void pputfactors(FILE *, FactorList); 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /m/cfrac/pfactor.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/pfactor.o -------------------------------------------------------------------------------- /m/cfrac/pfloat.c: -------------------------------------------------------------------------------- 1 | /* 2 | * High Precision Math Library Supplement for floating point routines 3 | */ 4 | #include 5 | #include 6 | #include "pdefs.h" 7 | #include "pcvt.h" 8 | #include "precision.h" 9 | 10 | extern precision palloc(); 11 | 12 | /* 13 | * double to precision 14 | */ 15 | precision dtop(f) 16 | register double f; 17 | { 18 | register digitPtr uPtr; 19 | register precision u; 20 | 21 | u = palloc(DOUBLESIZE); /* pretty big */ 22 | if (u == pUndef) return u; 23 | 24 | if (f < 0.0) { 25 | f = -f; 26 | u->sign = true; 27 | } else { 28 | u->sign = false; 29 | } 30 | uPtr = u->value; 31 | do { 32 | *uPtr++ = fmod(f, (double) BASE); 33 | f = floor(f / (double) BASE); 34 | } while (f != 0.0); 35 | 36 | u->size = (uPtr - u->value); 37 | 38 | return presult(u); 39 | } 40 | 41 | /* 42 | * precision to double (no overflow check) 43 | */ 44 | double ptod(u) 45 | precision u; 46 | { 47 | register digitPtr uPtr; 48 | register double f; 49 | 50 | (void) pparm(u); 51 | uPtr = u->value + u->size; 52 | f = 0.0; 53 | do { 54 | f = f * (double) BASE + (double) *--uPtr; 55 | } while (uPtr > u->value); 56 | 57 | if (u->sign) f = -f; 58 | 59 | pdestroy(u); 60 | return f; 61 | } 62 | -------------------------------------------------------------------------------- /m/cfrac/pfloat.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/pfloat.o -------------------------------------------------------------------------------- /m/cfrac/pgcd.c: -------------------------------------------------------------------------------- 1 | #include "precision.h" 2 | 3 | /* 4 | * Euclid's Algorithm 5 | * 6 | * Given u and v, calculated and return their greatest common divisor. 7 | */ 8 | precision pgcd(u, v) 9 | precision u, v; 10 | { 11 | precision u3 = pnew(pabs(pparm(u))), v3 = pnew(pabs(pparm(v))); 12 | precision q = pUndef, r = pUndef; 13 | 14 | while (pnez(v3)) { 15 | pdivmod(u3, v3, &q, &r); 16 | pset(&u3, v3); 17 | pset(&v3, r); 18 | } 19 | 20 | pdestroy(v3); 21 | pdestroy(q); pdestroy(r); 22 | pdestroy(u); pdestroy(v); 23 | return presult(u3); /* result always positive */ 24 | } 25 | -------------------------------------------------------------------------------- /m/cfrac/pgcd.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/pgcd.o -------------------------------------------------------------------------------- /m/cfrac/phalf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "pdefs.h" 3 | #include "precision.h" 4 | 5 | #ifdef ASM_16BIT 6 | #include "asm16bit.h" 7 | #endif 8 | 9 | /* 10 | * Divide a precision by 2 11 | */ 12 | precision phalf(u) 13 | register precision u; 14 | { 15 | #ifdef ASM_16BIT 16 | register precision w; 17 | register posit usize; 18 | 19 | pparm(u); 20 | usize = u->size; 21 | w = palloc(usize); 22 | if (w == pUndef) return w; 23 | 24 | w->sign = u->sign; 25 | (void) memcpy(w->value, u->value, usize * sizeof(digit)); 26 | 27 | memlsrw(w->value, usize); /* 68000 assembly language routine */ 28 | if (usize > 1 && w->value[usize-1] == (digit) 0) { /* normalize */ 29 | --(w->size); 30 | } 31 | pdestroy(u); 32 | return presult(w); 33 | #else 34 | return pdiv(u, ptwo); 35 | #endif 36 | } 37 | -------------------------------------------------------------------------------- /m/cfrac/phalf.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/phalf.o -------------------------------------------------------------------------------- /m/cfrac/picmp.c: -------------------------------------------------------------------------------- 1 | #include "pdefs.h" 2 | #include "precision.h" 3 | 4 | static char cmpError[] = "Second arg not single digit"; 5 | 6 | /* 7 | * Single-digit compare 8 | */ 9 | int picmp(u, v) 10 | register precision u; 11 | register int v; 12 | { 13 | register int i; 14 | 15 | (void) pparm(u); 16 | 17 | if (u->sign) { 18 | i = -1; 19 | if (v < 0) { 20 | if (-v >= BASE) { 21 | errorp(PDOMAIN, "picmp", cmpError); 22 | } 23 | if (u->size == 1) { 24 | i = - (int) *(u->value) - v; 25 | } 26 | } 27 | } else { 28 | i = 1; 29 | if (v >= 0) { 30 | if (v >= BASE) { 31 | errorp(PDOMAIN, "picmp", cmpError); 32 | } 33 | if (u->size == 1) { 34 | i = (int) *(u->value) - v; 35 | } 36 | } 37 | } 38 | 39 | pdestroy(u); 40 | return i; 41 | } 42 | -------------------------------------------------------------------------------- /m/cfrac/picmp.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/picmp.o -------------------------------------------------------------------------------- /m/cfrac/pidiv.c: -------------------------------------------------------------------------------- 1 | #include "pdefs.h" 2 | #include "precision.h" 3 | #ifdef ASM_16BIT 4 | #include "asm16bit.h" 5 | #endif 6 | 7 | /* 8 | * Single-digit divide 9 | */ 10 | precision pidiv(u, v) 11 | register precision u; 12 | int v; 13 | { 14 | #ifndef ASM_16BIT 15 | register digitPtr uPtr, qPtr; 16 | register accumulator temp; /* 0 <= temp < base^2 */ 17 | #endif 18 | register digit r, d; /* 0 <= r,d < base */ 19 | register posit m; 20 | register precision q; 21 | 22 | (void) pparm(u); 23 | 24 | if (v < 0) d = (digit) -v; else d = (digit) v; 25 | if (d >= BASE) { 26 | q = pnew(errorp(PDOMAIN, "pidiv", "divisor too big for single digit")); 27 | goto done; 28 | } 29 | if (d == 0) { 30 | q = pnew(errorp(PDOMAIN, "pidiv", "divide by zero")); 31 | goto done; 32 | } 33 | m = u->size; 34 | q = palloc(m); 35 | if (q == pUndef) goto done; 36 | 37 | #ifndef ASM_16BIT 38 | qPtr = q->value + m; 39 | uPtr = u->value + m; 40 | r = 0; /* r is current remainder */ 41 | do { 42 | temp = mulBase(r); /* 0 <= temp <= (base-1)^2 */ 43 | temp += *--uPtr; /* 0 <= temp <= base(base-1) */ 44 | r = uModDiv(temp, d, --qPtr); /* 0 <= r < base */ 45 | } while (uPtr > u->value); 46 | #else 47 | r = memdivw1(q->value, u->value, m, d); 48 | #endif 49 | /* 50 | * normalize q 51 | */ 52 | if (m > 1 && q->value[m-1] == 0) { 53 | --(q->size); 54 | } 55 | q->sign = (u->sign != (v < 0)); 56 | if (q->size == 1 && *(q->value) == 0) q->sign = false; 57 | done: 58 | pdestroy(u); 59 | return presult(q); 60 | } 61 | -------------------------------------------------------------------------------- /m/cfrac/pidiv.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/pidiv.o -------------------------------------------------------------------------------- /m/cfrac/pimod.c: -------------------------------------------------------------------------------- 1 | #include "pdefs.h" 2 | #include "precision.h" 3 | #ifdef ASM_16BIT 4 | #include "asm16bit.h" 5 | #endif 6 | 7 | /* 8 | * Single-digit remainder 9 | */ 10 | int pimod(u, v) 11 | register precision u; 12 | int v; 13 | { 14 | #ifndef ASM_16BIT 15 | register digitPtr uPtr; 16 | register accumulator temp; /* 0 <= temp < base^2 */ 17 | #endif 18 | register digit r = 0, d; /* 0 <= r,d < base */ 19 | register int res = 0; 20 | 21 | (void) pparm(u); 22 | if (v < 0) d = (digit) -v; else d = (digit) v; 23 | if (d >= BASE) { 24 | errorp(PDOMAIN, "pimod", "divisor too big for single digit"); 25 | goto done; 26 | } 27 | if (d == 0) { 28 | errorp(PDOMAIN, "pimod", "divide by zero"); 29 | goto done; 30 | } 31 | #ifndef ASM_16BIT 32 | uPtr = u->value + u->size; 33 | r = 0; /* r is current remainder */ 34 | do { 35 | temp = mulBase(r); /* 0 <= temp <= (base-1)^2 */ 36 | temp += *--uPtr; /* 0 <= temp <= base(base-1) */ 37 | r = temp % d; /* 0 <= r < base */ 38 | } while (uPtr > u->value); 39 | #else 40 | r = memmodw1(u->value, u->size, d); 41 | #endif 42 | 43 | res = (int) r; 44 | if (u->sign) res = -res; 45 | done: 46 | pdestroy(u); 47 | return res; 48 | } 49 | -------------------------------------------------------------------------------- /m/cfrac/pimod.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/pimod.o -------------------------------------------------------------------------------- /m/cfrac/pio.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "pdefs.h" 5 | #include "pcvt.h" 6 | #include "precision.h" 7 | 8 | /* 9 | * Output a string to a file. 10 | * 11 | * Returns: 12 | * the number of characters written 13 | * or EOF if error 14 | */ 15 | static int fouts(stream, chp) 16 | FILE *stream; 17 | register char *chp; 18 | { 19 | register int count = 0, res = 0; 20 | 21 | if (chp != (char *) 0 && *chp != '\0') do { 22 | count++; 23 | res = putc(*chp, stream); 24 | } while (*++chp != '\0' && res != EOF); 25 | 26 | if (res != EOF) res = count; 27 | return res; 28 | } 29 | 30 | /* 31 | * output the value of a precision to a file (no cr or whitespace) 32 | * 33 | * Returns: 34 | * The number of characters output or EOF if error 35 | */ 36 | int fputp(stream, p) 37 | FILE *stream; 38 | precision p; 39 | { 40 | int res; 41 | char *chp = ptoa(pparm(p)); 42 | 43 | res = fouts(stream, chp); 44 | deallocate(chp); 45 | pdestroy(p); 46 | return res; 47 | } 48 | 49 | /* 50 | * Output a precision to stdout with a newline (useful from debugger) 51 | */ 52 | int putp(p) 53 | precision p; 54 | { 55 | int res; 56 | char *chp = ptoa(pparm(p)); 57 | 58 | res = fouts(stdout, chp); 59 | res = putc('\n', stdout); 60 | deallocate(chp); 61 | pdestroy(p); 62 | return res; 63 | 64 | } 65 | 66 | /* 67 | * Output a justified precision 68 | * 69 | * Returns: The number of characters in the precision, or EOF if error 70 | */ 71 | int fprintp(stream, p, minWidth) 72 | FILE *stream; 73 | precision p; 74 | register int minWidth; 75 | { 76 | int res; 77 | char *chp = ptoa(pparm(p)); 78 | int len; 79 | 80 | len = strlen(chp); 81 | if (minWidth < 0) { /* left-justified */ 82 | res = fouts(stream, chp); 83 | while (minWidth++ < -len) { 84 | putc(' ', stream); 85 | } 86 | } else { 87 | while (minWidth-- > len) { /* right-justified */ 88 | putc(' ', stream); 89 | } 90 | res = fouts(stream, chp); 91 | } 92 | 93 | deallocate(chp); 94 | pdestroy(p); 95 | return res; 96 | } 97 | 98 | 99 | /* 100 | * Read in a precision type - same as atop but with io 101 | * 102 | * leading whitespace skipped 103 | * an optional leading '-' or '+' followed by digits '0'..'9' 104 | * leading 0's Ok 105 | * stops at first unrecognized character 106 | * 107 | * Returns: pUndef if EOF or invalid argument (NULL or nondigit as 1st digit) 108 | */ 109 | precision fgetp(stream) 110 | FILE *stream; 111 | { 112 | precision res = pUndef; 113 | precision clump = pUndef; 114 | int sign = 0; 115 | register int ch; 116 | register accumulator temp, x; 117 | register int j; 118 | 119 | ch = getc(stream); 120 | if (ch != EOF) { 121 | while (isspace(ch)) ch = getc(stream); /* skip whitespace */ 122 | if (ch == '-') { 123 | sign = 1; 124 | ch = getc(stream); 125 | } else if (ch == '+') { 126 | ch = getc(stream); 127 | } 128 | if (isdigit(ch)) { 129 | pset(&res, pzero); 130 | pset(&clump, utop(aDigit)); 131 | do { 132 | j = aDigitLog-1; 133 | temp = ch - '0'; 134 | do { 135 | if (!isdigit(ch = getc(stream))) goto atoplast; 136 | temp = temp * aBase + (ch - '0'); 137 | } while (--j > 0); 138 | pset(&res, padd(pmul(res, clump), utop(temp))); 139 | } while (isdigit(ch = getc(stream))); 140 | goto atopdone; 141 | atoplast: 142 | x = aBase; 143 | while (j++ < aDigitLog-1) { 144 | x *= aBase; 145 | } 146 | pset(&res, padd(pmul(res, utop(x)), utop(temp))); 147 | atopdone: 148 | if (ch != EOF) ungetc(ch, stream); 149 | if (sign) { 150 | pset(&res, pneg(res)); 151 | } 152 | } else { 153 | if (ch == EOF) { 154 | res = pUndef; 155 | } else { 156 | ungetc(ch, stream); 157 | } 158 | } 159 | } else { 160 | res = pUndef; 161 | } 162 | pdestroy(clump); 163 | if (res == pUndef) return res; 164 | return presult(res); 165 | } 166 | -------------------------------------------------------------------------------- /m/cfrac/pio.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/pio.o -------------------------------------------------------------------------------- /m/cfrac/pmul.c: -------------------------------------------------------------------------------- 1 | #include "pdefs.h" 2 | #include "precision.h" 3 | #include 4 | 5 | #ifdef ASM_16BIT 6 | #include "asm16bit.h" 7 | #endif 8 | 9 | /* 10 | * Multiply u by v (assumes normalized) 11 | */ 12 | precision pmul(u, v) 13 | register precision v; /* register a5 on 68000 */ 14 | #ifdef ASM_16BIT 15 | register precision u; /* register a4 */ 16 | { 17 | #else 18 | precision u; 19 | { 20 | digitPtr vPtr; 21 | register digitPtr uPtr, wPtr, HiDigit; 22 | register accumulator temp; /* 0 <= temp < base * base */ /* d7 */ 23 | register digit vdigit; /* d6 */ 24 | #endif 25 | register digit hi; /* 0 <= hi < base */ /* d5 */ 26 | precision w; 27 | 28 | (void) pparm(u); 29 | (void) pparm(v); 30 | /* 31 | * Check for multiply by zero. Helps prevent wasted storage and -0 32 | */ 33 | if (peqz(u) || peqz(v)) { 34 | w = palloc(1); 35 | if (w == pUndef) return w; 36 | 37 | w->sign = false; 38 | w->value[0] = 0; 39 | } else { 40 | if (u->size < v->size) { /* u is biggest number (for inner loop speed) */ 41 | w = u; u = v; v = w; 42 | } 43 | 44 | w = palloc(u->size + v->size); 45 | if (w == pUndef) return w; 46 | 47 | w->sign = (u->sign != v->sign); 48 | 49 | #ifndef ASM_16BIT 50 | uPtr = u->value; 51 | vPtr = v->value; 52 | wPtr = w->value + u->size; /* this is correct! */ 53 | do { 54 | *--wPtr = 0; 55 | } while (wPtr > w->value); 56 | 57 | vPtr = v->value; 58 | HiDigit = u->value + u->size; 59 | do { 60 | uPtr = u->value; 61 | wPtr = w->value + (vPtr - v->value); 62 | hi = 0; 63 | vdigit = *vPtr; 64 | do { 65 | temp = uMul(vdigit, *uPtr++); /* 0 <= temp <= (base-1)^2 */ 66 | temp += *wPtr; /* 0 <= temp <= base(base-1) */ 67 | temp += hi; /* 0 <= temp < base * base */ 68 | hi = divBase(temp); /* 0 <= hi < base */ 69 | *wPtr++ = modBase(temp); 70 | } while (uPtr < HiDigit); 71 | *wPtr++ = hi; 72 | } while (++vPtr < v->value + v->size); 73 | #else 74 | hi = memmulw(w->value, u->value, u->size, v->value, v->size); 75 | #endif 76 | if (hi == 0) { 77 | --(w->size); /* normalize */ 78 | } 79 | } 80 | 81 | pdestroy(u); 82 | pdestroy(v); 83 | return presult(w); 84 | } 85 | -------------------------------------------------------------------------------- /m/cfrac/pmul.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/pmul.o -------------------------------------------------------------------------------- /m/cfrac/pneg.c: -------------------------------------------------------------------------------- 1 | #include "pdefs.h" /* private include file */ 2 | #include "precision.h" /* public include file for forward refs */ 3 | #include 4 | 5 | /* 6 | * negation 7 | */ 8 | precision pneg(u) 9 | register precision u; 10 | { 11 | precision w; 12 | 13 | (void) pparm(u); 14 | w = palloc(u->size); 15 | if (w == pUndef) return w; 16 | 17 | w->sign = u->sign; 18 | if (pnez(u)) { /* don't create a negative 0 */ 19 | w->sign = !w->sign; 20 | } 21 | (void) memcpy(w->value, u->value, u->size * sizeof(digit)); 22 | 23 | pdestroy(u); 24 | return presult(w); 25 | } 26 | -------------------------------------------------------------------------------- /m/cfrac/pneg.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/pneg.o -------------------------------------------------------------------------------- /m/cfrac/podd.c: -------------------------------------------------------------------------------- 1 | #include "pdefs.h" 2 | #include "precision.h" 3 | 4 | /* 5 | * Returns non-zero if u is odd 6 | */ 7 | int podd(u) 8 | precision u; 9 | { 10 | register int res; 11 | 12 | (void) pparm(u); 13 | res = (*(u->value) & 1); 14 | pdestroy(u); 15 | return res; 16 | } 17 | -------------------------------------------------------------------------------- /m/cfrac/podd.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/podd.o -------------------------------------------------------------------------------- /m/cfrac/pops.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/pops.o -------------------------------------------------------------------------------- /m/cfrac/ppowmod.c: -------------------------------------------------------------------------------- 1 | #include "precision.h" 2 | 3 | /* 4 | * Raise to precision power mod m 5 | */ 6 | precision ppowmod(u, v, m) 7 | precision u, v, m; 8 | { 9 | precision j = pUndef, i = pUndef, n = pUndef; 10 | 11 | (void) pparm(m); 12 | pset(&i, pparm(u)); 13 | pset(&n, pparm(v)); 14 | pset(&j, pone); 15 | 16 | do { 17 | if (podd(n)) { 18 | pset(&j, pmod(pmul(i, j), m)); 19 | } 20 | pset(&n, phalf(n)); 21 | if (peqz(n)) break; 22 | pset(&i, pmod(pmul(i, i), m)); 23 | } while (1); 24 | 25 | pdestroy(i); pdestroy(n); 26 | pdestroy(u); pdestroy(v); pdestroy(m); 27 | return presult(j); 28 | } 29 | -------------------------------------------------------------------------------- /m/cfrac/ppowmod.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/ppowmod.o -------------------------------------------------------------------------------- /m/cfrac/primes.h: -------------------------------------------------------------------------------- 1 | extern unsigned int primesize; 2 | extern unsigned short primes[]; 3 | -------------------------------------------------------------------------------- /m/cfrac/primes.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/primes.o -------------------------------------------------------------------------------- /m/cfrac/psqrt.c: -------------------------------------------------------------------------------- 1 | #include "precision.h" 2 | 3 | /* 4 | * Square root 5 | */ 6 | precision psqrt(y) 7 | precision y; 8 | { 9 | int i; 10 | precision x = pUndef, lastx = pUndef; 11 | 12 | i = pcmpz(pparm(y)); 13 | if (i == 0) { /* if y == 0 */ 14 | pset(&lastx, pzero); 15 | } else if (i < 0) { /* if y negative */ 16 | pset(&x, errorp(PDOMAIN, "psqrt", "negative argument")); 17 | } else { 18 | pset(&x, y); 19 | do { 20 | pset(&lastx, x); 21 | pset(&x, phalf(padd(x, pdiv(y, x)))); 22 | } while (plt(x, lastx)); 23 | } 24 | 25 | pdestroy(x); 26 | 27 | pdestroy(y); 28 | return presult(lastx); 29 | } 30 | -------------------------------------------------------------------------------- /m/cfrac/psqrt.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/psqrt.o -------------------------------------------------------------------------------- /m/cfrac/psub.c: -------------------------------------------------------------------------------- 1 | #include "pdefs.h" 2 | #include "precision.h" 3 | #include 4 | 5 | #ifdef ASM_16BIT 6 | #include "asm16bit.h" 7 | #endif 8 | 9 | /* 10 | * Subtract u from v (assumes normalized) 11 | */ 12 | precision psub(u, v) 13 | #ifndef ASM_16BIT 14 | precision u, v; 15 | { 16 | register digitPtr HiDigit, wPtr, uPtr; 17 | register digitPtr vPtr; 18 | #else 19 | register precision u, v; 20 | { 21 | register digitPtr wPtr, uPtr; 22 | #endif 23 | precision w; 24 | register accumulator temp; 25 | #ifndef ASM_16BIT 26 | register digit noborrow; 27 | #endif 28 | register int i; 29 | 30 | (void) pparm(u); 31 | (void) pparm(v); 32 | if (u->sign != v->sign) { /* Are we actually adding? */ 33 | w = pUndef; 34 | v->sign = !v->sign; /* may generate -0 */ 35 | pset(&w, padd(u, v)); 36 | v->sign = !v->sign; 37 | } else { 38 | i = pcmp(u, v); 39 | if (u->sign) i = -i; /* compare magnitudes only */ 40 | 41 | if (i < 0) { 42 | w = u; u = v; v = w; /* make u the largest */ 43 | } 44 | 45 | w = palloc(u->size); /* may produce much wasted storage */ 46 | if (w == pUndef) return w; 47 | 48 | if (i < 0) w->sign = !u->sign; else w->sign = u->sign; 49 | 50 | uPtr = u->value; 51 | wPtr = w->value; 52 | #ifndef ASM_16BIT 53 | vPtr = v->value; 54 | noborrow = 1; 55 | 56 | HiDigit = v->value + v->size; /* digits in both args */ 57 | do { 58 | temp = (BASE-1) - *vPtr++; /* 0 <= temp < base */ 59 | temp += *uPtr++; /* 0 <= temp < 2*base-1 */ 60 | temp += noborrow; /* 0 <= temp < 2*base */ 61 | noborrow = divBase(temp); /* 0 <= noborrow <= 1 */ 62 | *wPtr++ = modBase(temp); 63 | } while (vPtr < HiDigit); 64 | 65 | HiDigit = u->value + u->size; /* propagate borrow */ 66 | while (uPtr < HiDigit) { 67 | temp = (BASE-1) + *uPtr++; 68 | temp += noborrow; /* 0 <= temp < 2 * base */ 69 | noborrow = divBase(temp); /* 0 <= noborrow <= 1 */ 70 | *wPtr++ = modBase(temp); 71 | } /* noborrow = 1 */ 72 | #else 73 | i = v->size; 74 | temp = u->size - i; 75 | if (temp > 0) { 76 | memcpy(wPtr + i, uPtr + i, temp * sizeof(digit)); 77 | } 78 | if (memsubw(wPtr, uPtr, v->value, i)) { /* trashes uPtr */ 79 | memdecw(wPtr + i, temp); 80 | } 81 | wPtr += w->size; 82 | #endif 83 | do { /* normalize */ 84 | if (*--wPtr != 0) break; 85 | } while (wPtr > w->value); 86 | w->size = (wPtr - w->value) + 1; 87 | } 88 | 89 | pdestroy(u); 90 | pdestroy(v); 91 | return presult(w); 92 | } 93 | -------------------------------------------------------------------------------- /m/cfrac/psub.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/psub.o -------------------------------------------------------------------------------- /m/cfrac/ptoa.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "pdefs.h" 3 | #include "pcvt.h" 4 | #include "precision.h" 5 | 6 | /* 7 | * Return the character string decimal value of a Precision 8 | */ 9 | #if (BASE > 10) 10 | #define CONDIGIT(d) ((d) < 10 ? (d) + '0' : (d) + 'a'-10) 11 | #else 12 | #define CONDIGIT(d) ((d) + '0') 13 | #endif 14 | 15 | char *ptoa(u) 16 | precision u; 17 | { 18 | register accumulator temp; 19 | register char *dPtr; 20 | char *d; 21 | int i = 0; 22 | unsigned int consize; 23 | precision r, v, pbase; 24 | register int j; 25 | 26 | (void) pparm(u); 27 | r = pUndef; 28 | v = pUndef; 29 | pbase = pUndef; 30 | 31 | consize = (unsigned int) u->size; 32 | if (consize > MAXINT / aDigits) { 33 | consize = (consize / pDigits) * aDigits; 34 | } else { 35 | consize = (consize * aDigits) / pDigits; 36 | } 37 | 38 | consize += aDigitLog + 2; /* leading 0's, sign, & '\0' */ 39 | d = (char *) allocate((unsigned int) consize); 40 | if (d == (char *) 0) return d; 41 | 42 | pset(&v, pabs(u)); 43 | pset(&pbase, utop(aDigit)); 44 | 45 | dPtr = d + consize; 46 | *--dPtr = '\0'; /* null terminate string */ 47 | i = u->sign; /* save sign */ 48 | do { 49 | pdivmod(v, pbase, &v, &r); 50 | temp = ptou(r); /* Assumes unsigned and accumulator same! */ 51 | j = aDigitLog; 52 | do { 53 | *--dPtr = CONDIGIT(temp % aBase); /* remainder */ 54 | temp = temp / aBase; 55 | } while (--j > 0); 56 | } while (pnez(v)); 57 | 58 | while (*dPtr == '0') dPtr++; /* toss leading zero's */ 59 | if (*dPtr == '\0') --dPtr; /* but don't waste zero! */ 60 | if (i) *--dPtr = '-'; 61 | if (dPtr > d) { /* ASSUME copied from lower to higher! */ 62 | (void) memcpy(d, dPtr, consize - (dPtr - d)); 63 | } 64 | 65 | pdestroy(pbase); 66 | pdestroy(v); 67 | pdestroy(r); 68 | 69 | pdestroy(u); 70 | return d; 71 | } 72 | -------------------------------------------------------------------------------- /m/cfrac/ptoa.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/ptoa.o -------------------------------------------------------------------------------- /m/cfrac/ptob.c: -------------------------------------------------------------------------------- 1 | #include "pdefs.h" 2 | #include "precision.h" 3 | 4 | /* 5 | * Convert a precision to a given base (the sign is ignored) 6 | * 7 | * Input: 8 | * u - the number to convert 9 | * dest - Where to put the ASCII representation radix 10 | * WARNING! Not '\0' terminated, this is an exact image 11 | * size - the number of digits of dest. 12 | * (alphabet[0] padded on left) 13 | * if size is too small, truncation occurs on left 14 | * alphabet - A mapping from each radix digit to it's character digit 15 | * (note: '\0' is perfectly OK as a digit) 16 | * radix - The size of the alphabet, and the conversion radix 17 | * 2 <= radix < 256. 18 | * 19 | * Returns: 20 | * -1 if invalid radix 21 | * 0 if successful 22 | * >0 the number didn't fit 23 | */ 24 | int ptob(u, dest, size, alphabet, radix) 25 | precision u; /* the number to convert */ 26 | char *dest; /* where to place the converted ascii */ 27 | unsigned int size; /* the size of the result in characters */ 28 | char *alphabet; /* the character set forming the radix */ 29 | register unsigned int radix; /* the size of the character set */ 30 | { 31 | register accumulator temp; 32 | register unsigned int i; 33 | register char *chp; 34 | unsigned int lgclump; 35 | int res = 0; 36 | 37 | precision r = pUndef, v = pUndef, pbase = pUndef; 38 | 39 | if (radix > 256 || radix < 2) return -1; 40 | if (size == 0) return 1; 41 | 42 | (void) pparm(u); 43 | temp = radix; 44 | i = 1; 45 | while (temp * radix > temp) { 46 | temp *= radix; 47 | i++; 48 | } 49 | lgclump = i; 50 | 51 | pset(&v, pabs(u)); 52 | pset(&pbase, utop(temp)); /* assumes accumulator and int are the same! */ 53 | 54 | chp = dest + size; 55 | do { 56 | pdivmod(v, pbase, &v, &r); 57 | temp = ptou(r); /* assumes accumulator and int are the same! */ 58 | i = lgclump; 59 | do { 60 | *--chp = alphabet[temp % radix]; /* remainder */ 61 | temp = temp / radix; 62 | if (chp == dest) goto bail; 63 | } while (--i > 0); 64 | } while pnez(v); 65 | 66 | if (chp > dest) do { 67 | *--chp = *alphabet; 68 | } while (chp > dest); 69 | 70 | bail: 71 | if (pnez(v) || temp != 0) { /* check for overflow */ 72 | res = 1; 73 | } 74 | 75 | pdestroy(pbase); 76 | pdestroy(v); 77 | pdestroy(r); 78 | 79 | pdestroy(u); 80 | return res; 81 | } 82 | -------------------------------------------------------------------------------- /m/cfrac/ptob.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/ptob.o -------------------------------------------------------------------------------- /m/cfrac/ptou.c: -------------------------------------------------------------------------------- 1 | #include "pdefs.h" 2 | #include "pcvt.h" 3 | #include "precision.h" 4 | 5 | /* 6 | * Precision to unsigned 7 | */ 8 | unsigned int ptou(u) 9 | precision u; 10 | { 11 | register digitPtr uPtr; 12 | register accumulator temp; 13 | 14 | (void) pparm(u); 15 | if (u->sign) { 16 | temp = (unsigned long) errorp(PDOMAIN, "ptou", "negative argument"); 17 | } else { 18 | uPtr = u->value + u->size; 19 | temp = 0; 20 | do { 21 | if (temp > divBase(MAXUNSIGNED - *--uPtr)) { 22 | temp = (unsigned long) errorp(POVERFLOW, "ptou", "overflow"); 23 | break; 24 | } 25 | temp = mulBase(temp); 26 | temp += *uPtr; 27 | } while (uPtr > u->value); 28 | } 29 | pdestroy(u); 30 | return (unsigned int) temp; 31 | } 32 | -------------------------------------------------------------------------------- /m/cfrac/ptou.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/ptou.o -------------------------------------------------------------------------------- /m/cfrac/seive.h: -------------------------------------------------------------------------------- 1 | extern unsigned long seivesize; 2 | 3 | extern unsigned char seive[]; 4 | -------------------------------------------------------------------------------- /m/cfrac/utop.c: -------------------------------------------------------------------------------- 1 | #include "pdefs.h" 2 | #include "pcvt.h" 3 | #include "precision.h" 4 | 5 | /* 6 | * Unsigned to Precision 7 | */ 8 | precision utop(i) 9 | register unsigned int i; 10 | { 11 | register digitPtr uPtr; 12 | register precision u = palloc(INTSIZE); 13 | 14 | if (u == pUndef) return pUndef; 15 | 16 | u->sign = false; 17 | uPtr = u->value; 18 | do { 19 | *uPtr++ = modBase(i); 20 | i = divBase(i); 21 | } while (i != 0); 22 | 23 | u->size = (uPtr - u->value); 24 | return presult(u); 25 | } 26 | -------------------------------------------------------------------------------- /m/cfrac/utop.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kparc/bcc/7955654bcb80d7e850066b19dc53a1110fd70281/m/cfrac/utop.o -------------------------------------------------------------------------------- /m/m.c: -------------------------------------------------------------------------------- 1 | #include"m.h" 2 | 3 | typedef struct pB pB;typedef pB*B; //!< forward decl for recursion 4 | typedef struct pB{V*a;B n;SZ s;}pB; //!< memblock: addr,next,size 5 | typedef struct {B f;B u;B frsh;SZ top;}pHP;typedef pHP*HP;//!< heap: first free block,first used,first available blank,top free addr 6 | static HP hp;ZS HMAX;static SZ heap_split_thresh,heap_alignment,heap_max_blocks; 7 | 8 | #include"t.c" 9 | 10 | V ta_init(V*base,V*max,SZ hpb,SZ splt,SZ algn) { 11 | hp=(HP)base; 12 | HMAX = max, 13 | heap_max_blocks = hpb, 14 | heap_split_thresh = splt, 15 | heap_alignment = algn; 16 | 17 | hp->f=hp->u=0; 18 | hp->frsh=(B)(hp+1); 19 | hp->top=(SZ)(hp->frsh+hpb); 20 | 21 | B b=hp->frsh; 22 | SZ i=heap_max_blocks-1; 23 | W(i--)b->n=b+1,++b; 24 | b->n=0;} 25 | 26 | ZV insert_block(B b){ 27 | DBG("insert_block %p\n",b); 28 | #ifndef TA_NO_COMPACT 29 | B p=hp->f,prev=0;//< if compaction is enabled, insert block into free list, sorted by addr 30 | W(p){$((SZ)b->a<=(SZ)p->a,DBG("insert %p\n",p);break);prev=p,p=p->n;} 31 | $(prev,prev->n=b){hp->f=b;} 32 | b->n=p;} 33 | #else 34 | b->n=hp->f,hp->f=b;}//n,sc->n=hp->frsh,hp->frsh=sc,sc->a=(V*)0,sc->s=0,sc=nxt;} 39 | ZV compact(){ 40 | DBG("compact()\n"); 41 | B ptr=hp->f,prev,scan; 42 | W(ptr){ 43 | prev=ptr;scan=ptr->n; 44 | W(scan&&(SZ)prev->a+prev->s==(SZ)scan->a){DBG("compact() merge=%p\n",scan);prev=scan,scan=scan->n;}//merge 45 | if(prev!=ptr){ 46 | SZ new_size = (SZ)prev->a-(SZ)ptr->a + prev->s; 47 | DBG("compact() new_size=%zu\n",new_size); 48 | ptr->s = new_size; 49 | B next = prev->n; 50 | release_blocks(ptr->n,prev->n); 51 | ptr->n=next;//relink 52 | } 53 | ptr = ptr->n;}} 54 | #endif 55 | 56 | V ta_free(V*p){ 57 | DBG("ta_free %p:\n",p); 58 | B b=hp->u,prev=0; 59 | W(b){//DBG("...ta_free b=%p -> ",b); 60 | if(p==b->a){ 61 | if(prev){ 62 | prev->n=b->n; 63 | }else{ 64 | hp->u=b->n; 65 | } 66 | INSERT(b) 67 | DBG("1\n");CHK("ta_free1"); 68 | } 69 | prev=b;b=b->n; 70 | } 71 | DBG("0\n");CHK("ta_free0");} 72 | 73 | static B alloc_block(SZ n){DBG("alloc_block(%zu):\n",n);ALGN(n) 74 | B ptr=hp->f,prev=0;SZ tp=hp->top; 75 | W(ptr){ 76 | const C is_top=((SZ)ptr->a+ptr->s>=tp)&&((SZ)ptr->a+n<=(SZ)HMAX); 77 | if(is_top||ptr->s>=n){ 78 | $(prev,prev->n=ptr->n)hp->f=ptr->n; 79 | ptr->n=hp->u,hp->u=ptr; 80 | if(is_top){//resize top block 81 | ptr->s=n,hp->top=(SZ)ptr->a+n; 82 | #ifndef TA_NO_SPLIT 83 | }else if(hp->frsh){ 84 | SZ excess = ptr->s-n; 85 | $(excess >= heap_split_thresh, 86 | ptr->s = n; 87 | B split = hp->frsh; 88 | hp->frsh = split->n; 89 | split->a = (V*)((SZ)ptr->a+n); 90 | DBG("split %p\n",split->a); 91 | split->s = excess; 92 | INSERT(split) 93 | );//else; 94 | #endif 95 | } 96 | R ptr;} 97 | prev = ptr, 98 | ptr = ptr->n;} 99 | 100 | // no matching free blocks, see if any other blocks available 101 | SZ new_top=tp+n; 102 | R hp->frsh&&new_top<=(SZ)HMAX? 103 | ptr = hp->frsh, 104 | hp->frsh = ptr->n, 105 | ptr->a = (V*)tp, 106 | ptr->n = hp->u, 107 | ptr->s = n, 108 | hp->u = ptr, 109 | hp->top = new_top, 110 | ptr:0;} 111 | 112 | V*ta_malloc(SZ n){DBG("ta_alloc %zu...\n",n);B b=alloc_block(n);V*r=b?b->a:0;DBG("ta_alloc %p\n",r);CHK("ta_alloc")R r;} 113 | ZV*ta_memclear(V*p,SZ n){SZ*ptrw=(SZ*)p,numw=(n&-SZT)/SZT;W(numw--)*ptrw++=0;n&=SZT-1;S ptrb=(S)ptrw;W(n--)*ptrb++=0;R p;} 114 | V*ta_calloc(SZ n,SZ sz){DBG("ta_calloc(%zu,%zu)\n",n,sz);B b=alloc_block(n*=sz);V*r=b?ta_memclear(b->a,n):(V*)0;DBG("ta_calloc -> %p\n",r);CHK("ta_calloc");R r;} 115 | 116 | #ifdef TA_TEST 117 | static SZ ta_count(B b){SZ c=0;W(b)b=b->n,c++;R c;} 118 | CNT(ta_avail,f)CNT(ta_used,u)CNT(ta_fresh,frsh) 119 | C ta_check(){R heap_max_blocks==ta_avail()+ta_used()+ta_fresh();} 120 | #endif 121 | 122 | //:~ 123 | -------------------------------------------------------------------------------- /m/m.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | //#include 3 | //#include 4 | #include"../c.h" 5 | 6 | #define EXP __attribute__ ((visibility("default"))) 7 | 8 | #define SZ size_t 9 | #define SZT sizeof(size_t) 10 | #define ALGN(x) x=(x+heap_alignment-1)&-heap_alignment; 11 | 12 | #ifndef TA_NO_COMPACT 13 | #define INSERT(b) insert_block(b);compact(); 14 | #else 15 | #define INSERT(b) insert_block(b); 16 | #endif 17 | 18 | V ta_init(V*base,V*max,SZ heap_blocks,SZ split_thresh,SZ alignment), 19 | *ta_malloc(SZ num), 20 | *ta_calloc(SZ num,SZ size), 21 | ta_free(V*ptr); 22 | 23 | #ifdef TA_MAIN 24 | #define TA_TEST 25 | #endif 26 | 27 | #ifdef TA_TEST 28 | SZ phy();V*ma(SZ n); 29 | #define CNT(f,x) SZ f(){R ta_count(hp->x);} 30 | SZ ta_avail(),ta_used(),ta_fresh(); 31 | C ta_check();V EXP ta_test_init(); 32 | #endif 33 | 34 | //:~ 35 | -------------------------------------------------------------------------------- /m/makefile: -------------------------------------------------------------------------------- 1 | C=clang -std=gnu11 2 | 3 | #-fvisibility=hidden 4 | CF=-Wall -Wextra -pedantic -fno-asynchronous-unwind-tables -fno-stack-protector -fno-common -fvisibility=default 5 | GNU=-Wno-variadic-macros -Wno-dollar-in-identifier-extension -Wno-gnu-statement-expression -Wno-unused-parameter -Wno-format-pedantic 6 | SRC_TA=m.c 7 | SRC_AW=-I.. ../m.c 8 | OREL=-O0 9 | ODBG=-O0 -g 10 | 11 | #TINYOPTS=-DTA_NO_COMPACT -DTA_NO_SPLIT 12 | TINYOPTS=-DTA_TEST 13 | 14 | OSO=-shared -lpthread -fPIC 15 | TSO=libtm.so 16 | TIME=/usr/bin/time 17 | 18 | ifeq ($(shell uname),Darwin) 19 | OSO=-dynamiclib -undefined dynamic_lookup 20 | TSO=libtm.dylib 21 | PGFIX=-pagezero_size 1000 22 | CF+=$(PGFIX) 23 | TIME=time -l 24 | endif 25 | 26 | m: 27 | @$C $(ODBG) $(SRC_TA) -DTA_MAIN -o m $(CF) $(GNU) 28 | 29 | so: 30 | $C $(OREL) $(SRC_TA) -o $(TSO) $(OSO) $(CF) $(GNU) $(TINYOPTS) 31 | @ls -la $(TSO) 32 | 33 | t: 34 | @./m 35 | 36 | ################ 37 | # memstress test 38 | ################ 39 | 40 | NBLK=128 41 | 42 | OSTRESS=-O2 -g -DTA_TEST -DNDEBUG -DNO_MI_STATS -lpthread $(PGFIX) 43 | OMI=-Ibench/extern/mimalloc/include -Lbench/extern/mimalloc/out/release -lmimalloc -Wno-int-conversion -Wno-extra-semi 44 | TM=TA_NBLK=$(NBLK) LD_LIBRARY_PATH=bench/extern/mimalloc/out/release $(TIME) 45 | 46 | STRESSCFG=1 100 32 47 | stress: clean 48 | @$C $(OSTRESS) -DUSE_AW_MALLOC -DSTRESS $(SRC_AW) stress.c -o stress_aw $(CF) $(GNU) -Wno-language-extension-token -Wno-pointer-sign 49 | @$C $(OSTRESS) -DUSE_STD_MALLOC -DSTRESS $(SRC_TA) stress.c -o stress_sys $(CF) $(GNU) 50 | 51 | @#$C $(OSTRESS) -DUSE_MI_MALLOC -DSTRESS $(SRC_TA) stress.c -o stress_mi $(CF) $(GNU) $(OMI) 52 | @#$C $(OSTRESS) -DUSE_TA_MALLOC -DSTRESS $(SRC_TA) stress.c -o stress_ta $(CF) $(GNU) 53 | 54 | @echo;echo "stress sys_realloc";echo 55 | @$(TIME) ./stress_sys $(STRESSCFG) 56 | 57 | @echo;echo "stress aw_realloc";echo 58 | @$(TIME) ./stress_aw $(STRESSCFG) 59 | 60 | @#echo;echo "stress mi_realloc";echo 61 | @#$(MI) ./stress_mi $(STRESSCFG) 62 | 63 | @#echo;echo "stress ta_realloc (nyi)";echo 64 | @#$(TM) ./stress_ta $(STRESSCFG) 65 | 66 | ############## 67 | # memleak test 68 | ############## 69 | 70 | LEAKCFG=1 100 40000 71 | leak: clean 72 | @$C $(OSTRESS) -DUSE_AW_MALLOC $(SRC_AW) stress.c -o leak_aw $(CF) $(GNU) -Wno-language-extension-token -Wno-pointer-sign 73 | @$C $(OSTRESS) -DUSE_TA_MALLOC $(SRC_TA) stress.c -o leak_ta $(CF) $(GNU) 74 | @$C $(OSTRESS) -DUSE_TA_MALLOC $(SRC_TA) stress.c -o leak_ta_chk $(CF) $(GNU) -DTA_CHECK 75 | @$C $(OSTRESS) -DUSE_TA_MALLOC $(SRC_TA) stress.c -o leak_ta_ns $(CF) $(GNU) -DTA_NO_SPLIT 76 | @$C $(OSTRESS) -DUSE_STD_MALLOC $(SRC_TA) stress.c -o leak_sys $(CF) $(GNU) 77 | @#$C $(OSTRESS) -DUSE_MI_MALLOC $(SRC_TA) stress.c -o leak_mi $(CF) $(GNU) $(OMI) 78 | 79 | @echo;echo "leak ta_malloc (split+compact)";echo 80 | @$(TIME) ./leak_ta $(LEAKCFG) 81 | 82 | @echo;echo "leak ta_malloc (no split)";echo 83 | @$(TIME) ./leak_ta_ns $(LEAKCFG) 84 | 85 | @#echo;echo "leak ta_malloc (w/check)";echo 86 | @#$(TIME) ./leak_ta_chk $(LEAKCFG) 87 | 88 | @echo;echo "leak sys_malloc";echo 89 | @$(TIME) ./leak_sys $(LEAKCFG) 90 | 91 | @echo;echo "leak aw_malloc";echo 92 | @$(TIME) ./leak_aw $(LEAKCFG) 93 | 94 | @#echo;echo "leak mi_malloc";echo 95 | @#$(TM) ./leak_mi $(LEAKCFG) 96 | 97 | ############ 98 | # cfrac test 99 | ############ 100 | 101 | OCFRAC=-w -O3 -DNDEBUG -std=gnu89 -DNOMEMOPT cfrac/*.c -lm 102 | OCFRAC_AW=-DCUSTOM_FREE=aw_free -DCUSTOM_MALLOC=aw_malloc -DCUSTOM_MALLOC_INIT=aw_malloc_init -DTA_TEST $(SRC_AW) 103 | OCFRAC_TA=-DCUSTOM_FREE=ta_free -DCUSTOM_MALLOC=ta_malloc -DCUSTOM_MALLOC_INIT=ta_test_init -DTA_TEST $(SRC_TA) 104 | OCFRAC_IN=175451865205073170563711388363 105 | 106 | cfrac: clean 107 | @clang $(OCFRAC) -o cfrac_sys 108 | @clang $(OCFRAC) $(OCFRAC_AW) -o cfrac_aw -DUSE_AW_MALLOC -pagezero_size 1000 109 | @clang $(OCFRAC) $(OCFRAC_TA) -o cfrac_ta 110 | @clang $(OCFRAC) $(OCFRAC_TA) -o cfrac_ta 111 | @clang $(OCFRAC) $(OCFRAC_TA) -o cfrac_ta_nc -DTA_NO_COMPACT 112 | @clang $(OCFRAC) $(OCFRAC_TA) -o cfrac_ta_ns -DTA_NO_SPLIT 113 | @clang $(OCFRAC) $(OCFRAC_TA) -o cfrac_ta_ncs -DTA_NO_COMPACT -DTA_NO_SPLIT 114 | 115 | @echo;echo "cfrac ta_malloc (split+compact)";echo 116 | @TA_NBLK=2048 $(TIME) ./cfrac_ta $(OCFRAC_IN) 117 | 118 | @echo;echo "cfrac ta_malloc (no split)";echo 119 | @TA_NBLK=2048 $(TIME) ./cfrac_ta_ns $(OCFRAC_IN) 120 | 121 | @echo;echo "cfrac sys_malloc";echo 122 | @ $(TIME) ./cfrac_sys $(OCFRAC_IN) 123 | 124 | @echo;echo "cfrac aw_malloc";echo 125 | @ $(TIME) ./cfrac_aw $(OCFRAC_IN) 126 | 127 | @#echo;echo "cfrac ta_malloc (no compact)";echo 128 | @#TA_NBLK=4096 $(TIME) ./cfrac_ta_nc $(OCFRAC_IN) 129 | 130 | @#echo;echo "cfrac ta_malloc (no split/compact)";echo 131 | @#TA_NBLK=4096 $(TIME) ./cfrac_ta_ncs $(OCFRAC_IN) 132 | 133 | all: clean m t so 134 | 135 | clean: 136 | @rm -rf *.dSYM 137 | @rm -f m libtm.so libtm.dylib cfrac_* leak_* stress_* 138 | 139 | .PHONY: clean all cfrac 140 | -------------------------------------------------------------------------------- /m/mk: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | make leak 4 | make cfrac 5 | -------------------------------------------------------------------------------- /m/t.c: -------------------------------------------------------------------------------- 1 | #ifdef TA_TEST 2 | //#define DBG(a...) O(a) 3 | #define DBG(a...) 4 | 5 | #ifndef TA_CHECK 6 | #define CHK(fn) 7 | #else 8 | #define CHK(fn) if(!ta_check())O("ta_check() fail %s\n",fn),exit(1); 9 | #endif 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #define GB(n) (n>>30) 19 | 20 | SZ phy(){SZ m=0; 21 | #if defined(__EMSCRIPTEN__) 22 | m=__builtin_wasm_memory_size(0)*64*1024; 23 | #elif defined(__linux__) || defined(__OpenBSD__) 24 | #include 25 | m=sysconf(_SC_PHYS_PAGES)*sysconf(_SC_PAGE_SIZE); 26 | #elif defined(__APPLE__) 27 | SZ ln=sizeof(m);sysctlbyname("hw.memsize",&m,&ln, NULL, 0); 28 | #endif 29 | R m;} 30 | 31 | static C ge(char*name,char*result,SZ sz){// cannot call getenv() when still initializing the C runtime. 32 | char*s=getenv(name); 33 | if(!s){ 34 | C buf[64+1];// we check the upper case name too. 35 | SZ len=strlen(name); 36 | if(len>=sizeof(buf))len=sizeof(buf)-1; 37 | N(len,buf[i]=toupper(name[i]))buf[len]=0; 38 | s=getenv((char*)buf);} 39 | P(s&&strlen(s)>2, 50 | nblk=n?n:256, 51 | splt=16, 52 | algn=sizeof(S); 53 | base=ma(heap); 54 | 55 | ta_init(base,(S)base+heap,nblk,splt,algn); 56 | O("ta_test_init blk %zu heap %zug phys %zug\n",nblk,GB(heap),GB(phys));} 57 | 58 | #else 59 | #define DBG(a...) 60 | #define CHK(fn) 61 | #endif 62 | 63 | #ifdef TA_MAIN 64 | 65 | I main(I c,char**v){R ta_test_init(),0;} 66 | #endif 67 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | CF=-fno-asynchronous-unwind-tables -fno-stack-protector -Wall -Wno-pragmas -Wno-unused-value -Wno-misleading-indentation 2 | #-Wno-unused-command-line-argument -Wno-unknown-warning-option -Wno-parentheses -Wno-pointer-sign -minline-all-stringops 3 | LF=-rdynamic 4 | #LF=+-nostdlib -c a.S 5 | SRC=[abmphu].c 6 | 7 | BSRC=$(shell ls -1 $(SRC) | sed s/.c/.o/ | xargs) 8 | BOBJ=$(patsubst %,t/obj/%,$(BSRC)) 9 | TSRC=$(shell basename t/t.*.c | sed s/.c// | xargs) 10 | TOBJ=$(patsubst %,t/obj/%,$(TSRC),%.o%) 11 | TBIN=$(patsubst %,b/%,$(TSRC)) 12 | USRC=t/lib/unity.c 13 | UOBJ=t/obj/unity.o 14 | 15 | Q=@ 16 | # -DSYMS 17 | O=-O0 -g -std=gnu11 -DUSE_AW_MALLOC -DQUIET 18 | LVM=clang 19 | GCC=$(shell env env which gcc-11||which gcc-10||env which gcc-9||env which gcc-8||echo gcc) 20 | COSD=${COSMO_DIR} 21 | TCC=tcc 22 | TESTC=$(LVM) $O 23 | 24 | #FIXME=-Wno-int-conversion -Wno-pointer-to-int-cast -Wno-unused-value -Wno-misleading-indentation -Wno-pragmas 25 | FIXME=-Wno-format -Wno-pointer-sign 26 | TOPTS=-UISOMRPH -DTST -DSYMS $(FIXME) 27 | T=tiso.b 28 | 29 | ifeq ($(shell uname),Darwin) 30 | LF+= -pagezero_size 1000 31 | CF+= -I$(shell xcrun --show-sdk-path)/usr/include -L$(shell xcrun --show-sdk-path)/usr/lib 32 | endif 33 | 34 | # llvm 35 | l: uprep 36 | $(LVM) $O $(LF) $(SRC) -o b/bl $(CF) 37 | @b/bl $T 38 | @#@echo 39 | @#@objdump -b binary -m i386 -M intel,x86-64 -D lnk.bin | tail -n+8 40 | @#@echo 41 | 42 | 43 | # llvm syms 44 | s: uprep 45 | $(Q)$(LVM) $O $(LF) $(SRC) -o b/wip $(CF) -DSYMS 46 | @b/wip 47 | 48 | # gcc 49 | g: uprep 50 | $(Q)$(GCC) $O $(LF) $(SRC) -o b/bg $(CF) $(FIXME) 51 | b/bg $T 52 | 53 | # cosmopolitan gcc 54 | # -fuse-ld=bfd -mnop-mcount -minline-all-stringops -mno-red-zone 55 | c: uprep 56 | $(Q)$(GCC) -g -Os -std=gnu11 -DCOSMO -DUSE_AW_MALLOC -Wall -static -fno-stack-protector -Wno-format -Wno-pointer-sign -Wno-pragmas -Wno-unused-value -fno-pie -no-pie -nostdlib -nostdinc -fno-omit-frame-pointer -pg -o b/b.com.dbg $(SRC) -Wl,--gc-sections -Wl,-T,$(COSD)/ape.lds -include $(COSD)/cosmopolitan.h $(COSD)/crt.o $(COSD)/ape.o $(COSD)/cosmopolitan.a 57 | @objcopy -S -O binary b/b.com.dbg b/b.com 58 | @b/b.com $T 59 | # tcc 60 | t: uprep 61 | $(Q)$(TCC) $O $(SRC) -o b/bt 62 | b/bt $T 63 | 64 | # ref 65 | r: 66 | $(Q)$(TESTC) -Os -g r.c -o b/r && b/r 67 | @#objdump -d b/r 68 | 69 | ## 70 | ## wip unit 71 | ## 72 | wip: cleanwip 73 | @#-fprofile-instr-generate -fcoverage-mapping -fdebug-macro -fmacro-backtrace-limit=0 74 | $(Q)$(TESTC) $O $(TOPTS) t/t.c t/lib/unity.c $(SRC) -o w $(LF) $(CF) $(FIXME) -fmacro-backtrace-limit=0 75 | @echo 76 | 77 | w: wip 78 | @./w 79 | 80 | wl: wip 81 | lldb --source-on-crash t/dat/t.lldb -b -o run ./w 82 | @echo 83 | @objdump -b binary -m i386 -M intel,x86-64 -D raw.bin | tail -n+8 84 | @echo 85 | @echo 86 | @objdump -b binary -m i386 -M intel,x86-64 -D lnk.bin | tail -n+8 87 | @echo 88 | 89 | ## 90 | ## incremental test build 91 | ## 92 | u: uprep udep urun 93 | 94 | ucl: 95 | @rm -rf b t/obj 96 | 97 | uprep: 98 | @mkdir -p b t/obj 99 | 100 | udep: $(BOBJ) $(UOBJ) 101 | 102 | urun: $(TBIN) 103 | 104 | #@#-fprofile-instr-generate -fcoverage-mapping -fdebug-macro -fmacro-backtrace-limit=0 105 | t/obj/%.o: %.c 106 | $(Q)$(TESTC) $O $(CF) $(TOPTS) $< -o $@ -c # build b source 107 | 108 | t/obj/t.%.o: t/t.%.c 109 | $(Q)$(TESTC) $O $(CF) $(TOPTS) $< -o $@ -c # build test units 110 | 111 | $(UOBJ): $(USRC) 112 | $(Q)$(TESTC) $O $(CF) $(TOPTS) $< -o $@ -c # build unity 113 | 114 | b/t.%: t/obj/t.%.o 115 | $(Q)$(TESTC) $(BOBJ) $(UOBJ) $< -o $@ $(LF) # link 116 | @#ls -la $@ 117 | @#$@ 118 | 119 | ## 120 | ## phony 121 | ## 122 | all: l g t 123 | 124 | cleanwip: 125 | @rm -f w 126 | 127 | clean: 128 | @rm -f test b/bl b/bg b/bt b/r 129 | 130 | .PHONY: clean all cleanwip syms ucl uprep urun u b l g t r w 131 | -------------------------------------------------------------------------------- /mk: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | make clean all 4 | 5 | #:~ 6 | -------------------------------------------------------------------------------- /p.c: -------------------------------------------------------------------------------- 1 | #pragma GCC diagnostic ignored "-Wempty-body" 2 | #include"b.h" 3 | #include"h.h" 4 | 5 | K XXX(K*k,K y){R r0(*k),*k=y,NL;} //!< release an existing K object under pointer x and replace it with y 6 | C ID(CP p){R!!sc((S)"aNW_",cl(p));} //!< valid identifier chars 7 | ZS qt(){R sc(";})]",*Ss);} //!< valid expression terminators 8 | 9 | #ifdef SYMS //!< global namespace api 10 | K gget(B b){R(&b->k)[-1];}ZC gpos(B x){AB("nyi gpos");}K*GLO(K x){B y=hget(GT,xC,xn);R&y->v;} 11 | CP nxt(ST st){S s=Ss;Ss=cp(Ss,&Pt);R Pn=Ss-s,Pt;}//!< return next cp on tape and paste its length into Pn 12 | B tok(ST st){S r=Ss;W(nxt(st)&&ID(Pt)){};Ss-=Pn;R hget(GT,r,Ss-r);} 13 | #endif 14 | 15 | ZK Na(){S r=Ss;W(10u>*++Ss-'0'||'.'==*Ss){};I f=0;N(Ss-r,f|='.'==r[i])R f?kf(fp(r,Ss-r)):ki(ip(r,Ss-r));}//!< parse numbers, int|fp (floats as 1e6 must contain a dot) 16 | 17 | // encode integers up to 127 as bytes with the highest bit set 18 | // other numbers are appended at the end of z and return index 19 | // (indices <16 correspond to registers, zn-3 is the index in 20 | // the z is of K vals: z[0] is the source and z[1] is opcodes) 21 | ZK n(K x){R kc(KI==Ax&&129u>1+xi?128+xi:(z=jk(z,x),16+zn-3));} 22 | 23 | #define f(x,b) pF(x,b,st) 24 | #define E(a,c) pE(a,c,st) 25 | 26 | ZK pF(K x,I b,ST st){ //!< promote rettype to float if needed 27 | O("pF x %llx b %d Ax %d b %d t(x) %d\n",x,b,Ax,b,t(x)); 28 | R KF-b||KF==t(x) 29 | ?x 30 | #ifndef SYMS 31 | :Ax&&126?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 46 | I cl(CP c){P(!c,0)R 128>c?" \"+$++ ()++ + +0000000000+;+++ aaaaaaaaaaaaaNaaaaaaaaWaaa[+]+_`aaaaaaaaaaaaaaaaaaaaaaaaaa{+} "[c-32]:0;} //!< ascii 47 | #else 48 | //! class !""#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 49 | I cl(CP c){P(!c,0)R 128>c?" \"+$++ ()++ + +0000000000+;+++ aaaaaaaaaaaaaNaaaaaaaaWaaa[+]+_`aaaaaaaaaaaaaaaaaaaaaaaaaa{+} "[c-32]:"\0aga++"[UC(c)];} //!< ascii + unicode classes 50 | #endif 51 | 52 | //! parse next codepoint on tape 53 | K _p(ST st){K x,y;CP a;I b; //!< a operator, x/y operands, b return type 54 | C qn='0'-cl('-'==(a=*Ss++)?Ss['.'==*Ss]:'.'==a?*Ss:a); //!< special case: if expr starts with a minus, dot or a minus-dot, it may be a number 55 | C cls=qn?cl(a):'0'; 56 | 57 | #ifdef SYMS 58 | cls=LP(cls)&&'('-Ss[1]?'a':cls; //!< special case: if N|W is not followed by (, force class to identifier 59 | #endif 60 | 61 | switch(cls){ //!< current char class: 62 | case'N':T[sN++]=KI; //!< 'for' loop, declare a loop variable and fallthrough to W 63 | C('W',R //!< W|N(cnd){body} 64 | ++Ss,x=p(),++Ss, //!< parse cnd expr into x 65 | x=k3(kc(a),x,p()), //!< x is (W|N,cnd,body) 66 | sN-='N'==a,x) //!< undeclare loop var for N 67 | case'$':++Ss; //!< $[ctf], fallthrough 68 | C('{',R E(0,a)) //!< inner scope, parse enclosed expressions 69 | C('+',R x=p(), //!< operator: parse right operand and store rettype in xu: 70 | u('#'==a?KI: //!< count #x is int 71 | '%'==a?KF: //!< division x%y is float 72 | t(x)-8*('*'==a), //!< dereference *x is list type 73 | k2c(a,x))) //!< other ops inherit type of right operand 74 | C('[',R E(X2,a)) //!< parse a dyadic expression inside square brackets 75 | C('(',x=p(),++Ss) //!< parse fenced expression 76 | C('0', //!< number: 77 | P('2'==a&&'*'==*Ss, //!< translate 2*x into bitwise left shift (\x) 78 | ++Ss,x=p(), //!< skip 2* and parse the right operand 79 | u(t(x),k2c('\\',x)) //!< inherit type of x and return monadic tuple 80 | )--Ss;x=n(Na())) //!< parse a number 81 | case'a': //!< identifier: 82 | #ifdef SYMS 83 | {--Ss;B t=tk();K y=gget(t); //!< tk() scans an identifier and stores it in the hash table 84 | #endif 85 | x='['==*Ss?++Ss,E( //!< a) if followed by [expr], it is an array indexing or a function call: 86 | #ifndef SYMS 87 | T[b=a-'a']?T[b]-8: //!< if varname has no type, it is a func call; for arrays, unset high bit 88 | (x=GGG[b],x=xy, //!< xx is the string, xy is the code 89 | #else 90 | T[b=gpos(t)]?T[b]-8: //!< if varname has no type, it is a func call; for arrays, unset high bit 91 | (x=y,x=xy, //!< xx is the string, xy is the code 92 | #endif 93 | D0=MX(D0,xC[xn-2]), //!< D[0] and D[1] are stored after RET 94 | D1=MX(D1,xC[xn-1]),xu), 95 | #ifdef SYMS 96 | y //!< op is the array|function name. 97 | ):ks(t->k);};break; //!< b) it is a variable reference. 98 | #else 99 | a //!< op is the array|function name. 100 | ):ks(a);break; //!< b) it is a variable reference. 101 | #endif 102 | default:R AB(Ss-1);} //!< bail on unmapped class or whitespace 103 | 104 | P(qt(),x) //!< if reached expr end, return the parse tree 105 | P('+'-cl(a=*Ss++),AB(Ss-1)) //!< otherwise next char should be an operator, bail if not 106 | if(':'==*Ss)++Ss,a+=128; //!< for assignment, set high bit of op char byte 107 | y=p();b=t(y); //!< parse right operand into y and get its type into b 108 | #ifndef SYMS 109 | $(':'==a&&Ax,T[xi-'a']=b) //!< for assignment, set result type to the type of the right operand 110 | #else 111 | $(':'==a&&Ax,T[(*(I*)x)-'a']=b) //!< for assignment, set result type to the type of the right operand 112 | #endif 113 | b='%'-a?MX(b,t(x)):KF; //!< for div, force it to float, for the rest, use the widest one (KF>KJ>KI>KC) 114 | O("END p() b %d\n",b); 115 | 116 | R u(U('<')<=U(a)?KI:b, //!< if operator is a comparison (<=>), force return type to int 117 | k3(kc(a),f(x,b),f(y,b)));} //!< return (op,left,right) 118 | 119 | //S('0'-c('-'==(a=*s++)?s['.'==*s]:'.'==a?*s:a)?c(a):'0',case'N':T[sN++]=KI; 120 | // C('W',R++s,x=p(st),++s,x=k3(kc(a),x,p(st)),sN-='N'==a,x)case'$':++s;C('{',R Ee(0,a,st)) 121 | // C('+',R x=p(st),u('#'==a?KI:'%'==a?KF:t(x)-8*('*'==a),k2(kc(a),x)))C('[',R Ee(12,a,st))C('(',x=p(st),++s)C('0',P('2'==a&&'*'==*s,++s,x=p(st),u(t(x),k2(kc('\\'),x)))--s;x=n(Na())) 122 | // C('a',x='['==*s?++s,Ee(T[b=a-'a']?T[b]-8:(x=G[b],x=xy,D0=MX(D0,x[xn-2]),D1=MX(D1,x[xn-1]),xu),a,st):kc(a)),AB(s-1)) 123 | 124 | //:~ 125 | -------------------------------------------------------------------------------- /r.c: -------------------------------------------------------------------------------- 1 | //!\file reference impls 2 | #include//printf 3 | typedef int I;typedef unsigned int UI;typedef long long J;typedef void V; 4 | #define ZJ static J 5 | #define ZI static I 6 | #define R return 7 | #define O printf 8 | #define P(x,y) {if(x)R(y);} 9 | #define W(a...) while((a)) 10 | #define N(n,a...) {I _n=(n),i=0;W(i<_n){a;++i;}} 11 | #define rI ((I*)r) 12 | #define xI ((I*)x) 13 | 14 | I xor(I x,I y){R x^y;}V ox(I x,I y){O("%d^%d %d\n",x,y,xor(x,y));} 15 | 16 | //c[i]{n:0;W(x>1){x:$[x&1;(\x)+x+1;/x];n+:1};n} 17 | I c(I n){I c=0;W(n!=1){n=n&1?(n<<1)+n+1:n>>1;c++;}R c;}//!< all numbers lead to one 18 | 19 | inline ZI cmp(I*x,I i,I*y,I j){R x[i]y[j];}//!< comparator 20 | ZI mrg(I*b,I*x,I l,I h,I d){ 21 | I t,u,m=(UI)(l+h+1)/2; 22 | P(h==m,(b[l]=-1,l)) 23 | u=cmp(x,h=mrg(b,x,m,h,d),x,l=mrg(b,x,l,m,d)); 24 | if(u?d^(u<0):h1 16 | 1<2 17 | 1=2 18 | 2=2 19 | 20 | c[i]{n:0;W(x>1){x:$[x&1;(\x)+x+1;/x];n+:1};n} 21 | c[9] 22 | l[i]{r:0;N(x){r+:2};r} 23 | a[ii]$[x;a[-x;$[y;a[x;-y];1]];+y] 24 | b[Ii]{h:#x;l:0;W(h>l)$[y>x[i:/l+h];l:i+1;h:i];l} 25 | f[iII]{m:0;$[k:-x;W(x){x-:1;j:*y;N(k)y[i]:y[+i];y[k]:j;j:f[k;y;z];$[m(t:p*p)+u:q*q){m-:1;q:s+2*p*q;p:r+t-u};k+:0=m}};k} 29 | 30 | \w 31 | 32 | /test 33 | l[10] 34 | a[3;4] 35 | 36 | /fixme segv on ubuntu boxes 37 | x:!9 38 | b[x;7] 39 | y:!8 40 | z:!8 41 | f[#y;y;z] 42 | w:t[0;2] 43 | c[w] 44 | m[10] 45 | 46 | \w 47 | 48 | /time 49 | \t:2000 a[3;4] 50 | 51 | /fixme segv on ubuntu boxes 52 | x:!1000 53 | \t N(1000000)b[x;1023&i] 54 | y:!8 55 | z:!8 56 | \t:20 f[#y;y;z] 57 | \t:100 t[0;13] 58 | w:t[0;13] 59 | \t:100 c[w] 60 | 61 | \t:30 m[100] 62 | \v 63 | \f 64 | 65 | /fixme segv on ubuntu boxes 66 | \-x 67 | \-y 68 | \-z 69 | \-w 70 | 71 | \-a 72 | \-b 73 | \-c 74 | \-f 75 | \-m 76 | \-t 77 | \-l 78 | 79 | \v 80 | \f 81 | 82 | \w 83 | 84 | \\ 85 | -------------------------------------------------------------------------------- /t.c: -------------------------------------------------------------------------------- 1 | #include // (-O 40/1500 + 60/1500) 2 | #include 3 | #include"c.h" 4 | #define O printf 5 | 6 | //ackermann 7 | I a(I x,I y){R x?a(x-1,y?a(x,y-1):1):y+1;} 8 | 9 | //bsearch 10 | I b(I*x,I y){I h=x[-1],i,l=0;W(h>l)y>x[i=l+h>>1]?l=i+1:(h=i);R l;} 11 | 12 | //fannkuch 13 | I f(I x,I*y,I*z){I j,k,m=0;$(--x,N(x+1,j=*y;N(x,y[i]=y[i+1])y[x]=j;m=MX(m,f(x,y,z)))){N(y[-1],z[i]=y[i])W(j=*z){I i=0;++m;W(i(t=p*p)+(u=q*q)))--m,q=s+2*p*q,p=r+t-u;k+=!m))R k;} 22 | 23 | //timer 24 | F ms(){J a,d;asm volatile("rdtsc":"=a"(a),"=d"(d));R((d<<32)+a)*.58e-6;} 25 | 26 | //enm 27 | V*malloc(),free();I*enm(I n){I*r=malloc(4+4*n);N(*r++=n,r[i]=i)R r;} 28 | #define MS(n,e) {F _t=ms();I s=0;N(n,s+=e)O("%d %d\n",(I)(ms()-_t),s);} 29 | I main(){J*p;I*x=enm(1000),*y=enm(8),*z=enm(8); 30 | MS(2000,a(3,4)) 31 | MS(1000000,b(x,1023&i)) 32 | MS(20,f(8,y,z)) 33 | MS(100,(p=t(0,13),c(p),u(p),1)) 34 | MS(30,m(100)) 35 | R 0;} 36 | 37 | //tree 38 | //I t(I n){I d=4;J*p=a(n+1,0),*q;c(p),b(p),q=a(n,0);for(;d<=n;d+=2){I j=0,m=1;N(n-d+4,m*=2)N(m,j+=c(p=a(d,i+1)),b(p),j+=c(p=a(d,-i-1)),b(p))}R d=c(q),b(q),d;}//O("%d %d\n",2*m,j); 39 | 40 | -------------------------------------------------------------------------------- /t/dat/t.fio.b: -------------------------------------------------------------------------------- 1 | x:!100 -------------------------------------------------------------------------------- /t/dat/t.lldb: -------------------------------------------------------------------------------- 1 | bt 2 | quit 3 | -------------------------------------------------------------------------------- /t/dat/t.utf.b: -------------------------------------------------------------------------------- 1 | Ξεσκεπάζω τὴν ψυχοφθόρα βδελυγμία -------------------------------------------------------------------------------- /t/t.c: -------------------------------------------------------------------------------- 1 | #include"t.h" 2 | #include"../b.h" 3 | 4 | extern S Ss;extern K z;//!< \Ss tape \z zx source zy 0xrtype:opcodes:stack 5 | //K gset(B b,K v){K x=b->k;P(xr,XXX(&b->v,v))O("gset val %llx\n",b->v);R b->v=v,r1(x);} //!< only used in tests 6 | //#define GSET(k,v) ({ST0(k);B b=tk();K x=gset(b,v);/*K y=nm(x);O("GSET dbg %.*s %d pos=%d=%d %p b=%p xx=%p\n",yn,yC,yn,yu-26,gpos((B)xx),(I*)x,b,(B)xx),*/x;}); 7 | 8 | UNIT(wip, 9 | #ifdef SYMS 10 | 11 | O("----------- WIP ----------\n"); 12 | 13 | _("1|0", 1, "or truth table #1") 14 | _("0|1", 1, "or truth table #2") 15 | _("1|1", 1, "or truth table #3") 16 | _("0|0", 0, "or truth table #4") 17 | 18 | O("-----------------------------------------------------\n"); 19 | 20 | _("1&0", 0, "and truth table #1") 21 | _("0&1", 0, "and truth table #2") 22 | _("1&1", 1, "and truth table #3") 23 | _("0&0", 0, "and truth table #4") 24 | 25 | O("-----------------------------------------------------\n"); 26 | 27 | _("1^0", 1, "xor truth table #1") 28 | _("0^1", 1, "xor truth table #2") 29 | _("1^1", 0, "xor truth table #3") 30 | _("0^0", 0, "xor truth table #4") 31 | 32 | //___ 33 | 34 | //GSET("ƒ[]", ki(4)) 35 | //GSET("λ",ki(42)) 36 | //GSET("∀",ki(42)) 37 | 38 | //PT("l(i){r:0;N(x){r+:2};r}", "('{';(':';r;0x80);('N';x;('{';(0xab;r;0x82)));r)", "loop function decl ptree") 39 | //PT("f[i]{k:42;k+x}", "('{';(':';k;0xaa);('+';k;x))", "basic function declaration with unicode identifier") 40 | 41 | //_("f[i]{k:42;k+x}", NONE, "basic function declaration with unicode identifier") 42 | //_("f[2]", 42, "basic function declaration with unicode identifier") 43 | 44 | O("----------- WIP ----------\n"); 45 | 46 | _("k:42", NONE, "basic function declaration with unicode identifier") 47 | //_("k+:1", "FIXME", "basic function declaration with unicode identifier") 48 | //_("z-:2", 41, "basic function declaration with unicode identifier") 49 | //_("z%:2", 20, "basic function declaration with unicode identifier") 50 | 51 | //___ 52 | 53 | _("k", 42, "basic function declaration with unicode identifier") 54 | //_("k:k+1", NONE, "basic function declaration with unicode identifier") 55 | //_("k", 43, "basic function declaration with unicode identifier") 56 | 57 | //_("f[5]", NONE, "basic function declaration with unicode identifier") 58 | //_("f[i]{$[x=(128*1);2;1]}",NONE, "basic function declaration with unicode identifier") 59 | 60 | O("--------------------------\n"); 61 | 62 | //PT("f[]{2}", "('{';0x82)", "ptree of a simple function #1") 63 | //PT("f[i]{x}", "('{';x)", "ptree of a simple function #2") 64 | //PT("λ[i]{λ[i]}", "FIXME", "ptree of a basic recursive fn with utf identifier") 65 | 66 | _("-42", -42, "int negation") 67 | _("-42.5", -42.5, "float negation") 68 | _("/42", 21, "shift") 69 | _("//42", 10, "double shift") 70 | _("%42", 42.0, "cast to float") 71 | 72 | O("--------------------------\n"); 73 | 74 | //_("v:!13", NONE, "enlist") 75 | //_("*v", "FIXME", "first (float)") 76 | //_("#v", 13, "count (float)") 77 | //ERR("&v", "nyi sh", "count (float)") 78 | 79 | 80 | //PT("f[i]{$[10>x;f[x+1];x]}", "asdf", "basic function declaration with unicode identifier") 81 | //PT("ƒ[i]{x}", "('{';x)", "basic function declaration with unicode identifier") 82 | //_("f[i]{$[10>x;f[x+1];x]}", NONE, "basic function declaration with unicode identifier") 83 | 84 | //_("f[2]", 4, "basic function call") 85 | //_("f", 123, "disasm") 86 | 87 | 88 | //FIXME PT("TEST+NONE","('+';TEST;NONE)", "addition of non-existent globals hould produce correct parse tree") 89 | //FIXME ERR("123+NONE", "NONE", "sum holds the correct scalar value") 90 | 91 | PT("128+2", "('+';0x10;0x82)", "parse tree of a simple repl expr should match expected") 92 | _("128+2", 130, "simple repl expr should be sane") 93 | 94 | O("-------------------------\n"); 95 | 96 | _("(2+2)%4", 1.0, "precedence sanity #1") 97 | _("2+2%2", 3.0, "precedence sanity #2") 98 | _("2+(2%4)", 2.5, "precedence sanity #3") 99 | _("(2+2)%0", 0, "precedence sanity #4") 100 | 101 | O("-------------------------\n"); 102 | 103 | ERR("TEST", "TEST", "non-existent global variable should be a name error") 104 | ERR("TEST", "TEST", "non-existent global variable should be a name error (repeat)") 105 | _("TEST:42", NONE, "declaration of a global var shouldn't echo #1") 106 | _("BLAH:10", NONE, "declaration of a global var shouldn't echo #2") 107 | EQ_SYM("TEST", "42", "internal check of assigned global value should pass") 108 | _("TEST", 42, "global identifier should echo correct value") 109 | 110 | PT("TEST+BLAH", "('+';TEST;BLAH)", "addition of two declared globals should produce correct parse tree") 111 | 112 | _("TEST+BLAH", 52, "addition of two globals should echo correct value") 113 | 114 | 115 | O("-------------------------\n"); 116 | 117 | _("RIGHT:4", NONE, "multiple expressions on a line") 118 | _("LEFT:3", NONE, "multiple expressions on a line") 119 | 120 | _("RIGHT+LEFT", 7, "sum of two globals should echo correct value") 121 | _("RIGHT*LEFT", 12, "product of two globals should echo correct value") 122 | _("RIGHT-LEFT", 1, "subtraction of two globals should echo correct value") 123 | _("LEFT%RIGHT", 0.75, "division of two globals should echo correct value") 124 | _("RIGHT%2", 2.0, "division of a global by a constant should echo correct value") 125 | 126 | 127 | O("-------------------------\n"); 128 | 129 | _("LFT:42", NONE, "(tmp global var #1)") 130 | _("RGT:58", NONE, "(tmp global var #2)") 131 | 132 | EQ_SYM("LFT", "42", "(tmp global var check #1)") 133 | EQ_SYM("RGT", "58", "(tmp global var check #2)") 134 | 135 | 136 | O("-------------------------\n"); 137 | 138 | _("SUM:2*LFT+RGT", NONE, "global assignment (compound expression)") 139 | _("SUM", 200, "global assignment target should hold a correct value") 140 | 141 | O("-------------------------\n"); 142 | 143 | _("кен:42", NONE, "unicode identifier #1") 144 | _("артур:2", NONE, "unicode identifier #2") 145 | _("кен%артур", 21.0, "an simple expression with unicode identifiers") 146 | 147 | O("-------------------------\n"); 148 | 149 | Wstart=ws(); 150 | 151 | #else 152 | 153 | GGG['l'-'a']=ki(3); 154 | GGG['r'-'a']=ki(4); 155 | 156 | //PT("a:42", "0xaa", "parse tree of a scalar assignment is its literal value") 157 | //PT("s:2+1", "('+';0x82;0x81)", "parse tree of a simple expression #1") 158 | //PT("s+s", "('+';s;s)", "parse tree of a simple expression #2") 159 | //PT("p:s*s", "('*';s;s)", "parse tree of a simple expression #3") 160 | 161 | //_("l*r", 12, "evaluate an expression with global references #1") 162 | _("l:42", 12, "evaluate an expression with global references #1") 163 | 164 | //_("s:2+2", 0, "scalar expr assignment") 165 | //_("p:s*s", 0, "evaluate an expression with global references #1") 166 | //_("l*r", 12, "evaluate an expression with global references #2") 167 | //_("p", 16, "p should have expected value") 168 | 169 | #endif 170 | 171 | #if 0 172 | PT("pr:s*s", "('*';`s;`s)", "parse tree of a simple expression #2") 173 | _("p:s*s", 0, "parse tree of a simple expression #2") 174 | _("p", 9, "p should have expected value") 175 | #endif 176 | 177 | 178 | // PT("pr:s*s", "('*';`s;`s)", "parse tree of a simple expression #2") 179 | // _("p:s*s", 0, "parse tree of a simple expression #2") 180 | // _("p", 9, "p should have expected value") 181 | 182 | //PT("prd:sum*sum", "('*';`sum;`sum)", "assignment referencing globals should produce correct parse tree") 183 | //EQ_SYM("prd", "9", "prd holds the correct vector value in the slot FIXME") 184 | 185 | ) 186 | 187 | //:~ 188 | -------------------------------------------------------------------------------- /t/t.env.c: -------------------------------------------------------------------------------- 1 | #include"t.h" 2 | 3 | UNIT(env, //0 20 | ) 21 | 22 | //:~ 23 | -------------------------------------------------------------------------------- /t/t.err.c: -------------------------------------------------------------------------------- 1 | #include"t.h" 2 | 3 | #ifndef SYMS 4 | UNIT(err, 5 | ERR("\\-f", "f", "releasing a non-existent global should name-error") 6 | ERR("\\-A", "A", "releasing an invalid identifier should name-error") 7 | ERR("x", "x", "referencing an non-existent global should name-error") 8 | 9 | _("x:2", NONE, "declare a test scalar") 10 | ERR("\\-x", "nyi", "releasing a scalar should nyi") 11 | ) 12 | #else 13 | UNIT(err, 14 | ERR("\\-f", "f", "releasing a non-existent global should name-error (lcase)") 15 | ERR("\\-A", "A", "releasing a non-existent global should name-error (ucase)") 16 | ERR("\\-кен", "кен", "releasing a non-existent global should name-error (utf)") 17 | ERR("\\-123", "123", "releasing an invalid global should name-error") 18 | 19 | ERR("x", "x", "referencing an non-existent global should name-error") 20 | ___ 21 | _("x:2", NONE, "declare a test scalar") 22 | ERR("\\-x", "nyi", "releasing a scalar should nyi") 23 | ) 24 | #endif 25 | //:~ -------------------------------------------------------------------------------- /t/t.fio.c: -------------------------------------------------------------------------------- 1 | #include"t.h" 2 | 3 | UNIT(fio, 4 | 5 | ERR("\\l t/dat/blah.b", "t/dat/blah.b", "missing file should report an error") 6 | _("\\l t/dat/t.fio.b", NONE, "successful file compilation shouldn't report") 7 | _("#x", 100, "loaded and compiled source should produce result") 8 | _("\\-x", NONE, "releasing the result of compilation should empty the ws") 9 | ) 10 | 11 | //:~ 12 | -------------------------------------------------------------------------------- /t/t.h: -------------------------------------------------------------------------------- 1 | #pragma GCC diagnostic ignored "-Wunused-function" 2 | #define UNITY_INCLUDE_DOUBLE 3 | #include"lib/unity.h" 4 | #include"../a.h" 5 | 6 | #define NONE 0 7 | #define ES(x) ((S)(-1UL>>16&(J)x)) 8 | 9 | ZJ Wstart,Wprev;//!< wssize 10 | 11 | extern V init();S1(es);K pcle(S tp,I dbg);K se(K x,K pt);/*;K1(pr);K sS(I c,K x);*/K Li(K x,I i),bb(S x);//!< NB never forget signatures 12 | ZC xQ(K x){R QQ==A(x);}ZK str(S x){R es((S)x);}ZK ptree(S s){K x=pcle(s,1);/*os("PTREE"),o(x);*/R X0(jc(se(x,1),0));} 13 | //ZK out(S x){R pr(es(x));} 14 | 15 | #define TYPE(expr) (_Generic((expr), \ 16 | char: 'C', short: 'H', int: 'I', long: 'L', \ 17 | long long: 'J', unsigned long long: 'K', \ 18 | float: 'E', double: 'F', \ 19 | void*: '_', char*: 'S', default: '?')) 20 | 21 | #define EQ_I(act,exp,msg) TEST_ASSERT_EQUAL_INT_MESSAGE(exp,act,msg); 22 | #define EQ_K(act,exp,msg) TEST_ASSERT_EQUAL_UINT64_MESSAGE(exp,act,msg); 23 | #define EQ_E(act,exp,msg) TEST_ASSERT_EQUAL_FLOAT_MESSAGE(exp,act,msg); 24 | #define EQ_F(act,exp,msg) TEST_ASSERT_EQUAL_DOUBLE_MESSAGE(exp,act,msg); 25 | #define EQ_S(act,exp,msg) TEST_ASSERT_EQUAL_STRING_MESSAGE(exp,(S)str((S)act),msg); 26 | //#define STR(act,exp,msg) TEST_ASSERT_EQUAL_STRING_MESSAGE(exp,act,msg); 27 | 28 | #define SYMVAL(s) (S)se(hget(GT,s,sl((S)s))->v,0) 29 | #define EQ_SYM(act,exp,msg) {O("SYMVAL %llx\n",hget(GT,act,sl((S)act))->v);S x=SYMVAL((S)act);O("EQ_SYM %llx %\n",x);\ 30 | TEST_ASSERT_MESSAGE(!memcmp(x,exp,MN(strlen(exp),xn)), "variable value should match expected");} 31 | 32 | #define FAIL(msg) TEST_ASSERT_MESSAGE(0,msg) 33 | #define TRUE(cnd,msg) TEST_ASSERT_MESSAGE((cnd),msg); 34 | #define MEM(act,exp,n) TEST_ASSERT_EQUAL_MEMORY(act,exp,n); 35 | 36 | //#define EQ_NL(act,msg) TEST_ASSERT_MESSAGE(out(act)==NL,msg); 37 | 38 | //C('F',EQ_F(*(F*)&act,*(F*)&exp,msg)) 39 | //C('F',EQ_F(act,exp,msg)) 40 | #define ASSERT(act,exp,msg) S(TYPE(exp),\ 41 | C('S',EQ_S(act,(K)exp,msg)) \ 42 | C('I',EQ_I(I(act),exp,msg)) \ 43 | C('F',K y=act;F flt=*(F*)&y;EQ_E(flt,exp,msg)) \ 44 | C('K',EQ_K(act,exp,msg)) \ 45 | ,TEST_ASSERT_MESSAGE(0,"unknown type")) 46 | 47 | //O("___ %llx\n",x); 48 | #define _(act,exp,msg,cleanup...) Wprev=ws();if(TYPE(act)=='S'){K x=str((S)(J)(act));\ 49 | if(xQ(x)){TEST_ASSERT_EQUAL_STRING_MESSAGE("ok",ES(x),"unexpected error");r0(x);}\ 50 | else{ASSERT(X0(x),exp,msg)}}/*else{ASSERT(act,exp,msg)}*/;cleanup; 51 | 52 | #define ERR(act,exp,msg,cleanup...) Wprev=ws();{K x=str((S)(J)(act));\ 53 | if(!xQ(x)){TEST_ASSERT_EQUAL_STRING_MESSAGE(exp,"ok","expected an error");r0(x);}\ 54 | else{TEST_ASSERT_EQUAL_STRING_MESSAGE(exp,ES(x),msg);r0(0);}cleanup;} 55 | 56 | 57 | #define PT(act,exp,msg) {Wprev=ws();K x=ptree((S)act);TEST_ASSERT_EQUAL_STRING_MESSAGE(exp,(S)x,msg);r0(x);} 58 | #define WS0(msg) {TEST_ASSERT_EQUAL_INT_MESSAGE(0,ws(),msg);} 59 | #define WSSAME(msg) {TEST_ASSERT_EQUAL_INT_MESSAGE(0,ws()-Wprev,msg);} 60 | #define WS(exp,msg) {TEST_ASSERT_EQUAL_INT_MESSAGE(exp,ws(),msg);} 61 | 62 | #define ___ TEST_ASSERT_MESSAGE(0,"HALT"); 63 | 64 | #define TESTS(units...) ZV hsegv();I main(I a,char**c){hsegv(),init();UNITY_BEGIN();units;R UNITY_END();}V setUp(V){}V tearDown(V){}//!< before/after each test 65 | 66 | #define _run(name) extern V unit##_##name(V);RUN_TEST(unit##_##name); 67 | #define _skip(name) extern V skip##_##name(V);RUN_TEST(skip##_##name); 68 | 69 | #define UNIT(name,tests...) V skip##_##name(V){TEST_IGNORE();};V unit##_##name(V){Wstart=Wprev=ws();tests;\ 70 | /*WS(Wstart,"test unit shouldn't leak memory")*/};TESTS(_run(name)) 71 | 72 | #define TN(label,laps,task...) {F _avg,_ttl,_ms=ms();N(laps,({task;}));_ttl=ms()-_ms;_avg=_ttl/laps;O("\nclk %s: laps %d elapsed %d avg %.3f\n",label,laps,(I)_ttl,_avg);} 73 | 74 | #ifdef SIGHANDLER 75 | 76 | #define _GNU_SOURCE 1 //! 79 | #include 80 | #include 81 | #include 82 | #ifdef __APPLE__ 83 | #define osg(s) psignal(si->si_signo,s) 84 | #define RIP ((ucontext_t*)c)->uc_mcontext->__ss.__rip 85 | #else 86 | #define osg(s) psiginfo(si,s) 87 | //#define RIP ((ucontext_t *)c)->uc_mcontext->__ss.__rip 88 | #define RIP 0x0 89 | #endif 90 | V stack(I d,I o){V*arr[d];I sz=backtrace(arr, d);char**frames=backtrace_symbols(arr,sz);N(sz-o,os(frames[i+o]));nl();free(frames);}//!< depth+offset 91 | V handler(I sig,siginfo_t*si,V*c){nl();if(si->si_signo-SIGABRT){nl(),O("rip 0x%zu",(size_t)RIP),osg(""),nl();}osg("");stack(10,0),exit(1);} 92 | ZV hsegv(){struct sigaction a;memset(&a,0,sizeof(struct sigaction));a.sa_flags=SA_SIGINFO;a.sa_sigaction=handler;sigaction(SIGSEGV,&a,0);sigaction(SIGABRT,&a,0);} 93 | 94 | #else 95 | ZV hsegv(){} 96 | #endif//SIGHANDLER 97 | 98 | //!attic 99 | 100 | //V __llvm_profile_enable_continuous_mode(V);I __llvm_profile_is_continuous_mode_enabled(V),__llvm_profile_write_file(V); 101 | // 0 1 2 3 4 5 6 7 8 9 10 11 102 | //enum kerr{ERR_ZERO,ERR_CARET,ERR_PARSE,ERR_RANK,ERR_VALUE,ERR_NYI,ERR_CLASS,ERR_LENGTH,ERR_TYPE,ERR_DOMAIN,ERR_STACK,ERR_LIMIT}; 103 | //char* err[]={"zero", "caret", "parse", "rank", "value", "nyi", "class", "length", "type", "domain", "stack", "limit"}; 104 | //unsigned long: "unsigned long",unsigned int: "unsigned int",signed char: "signed char",long: "long",long double: "long double" 105 | //I k_init(I n,char**a);K1 e0,w_,ev;ZS str(K x){R(S)vc(wv(0,x),0);}long xT(K x){R(I)xt;}J xA(K x){R Ax;} 106 | //ZI WS(){I r=_i(w_(0));R 0>r?0:r;}ZS se(I e){R(S)err[e];}ZK out(S s){K x;U(x=p9(s));R X0(e0(x));} 107 | //#define $(act,msg) _(act,act,msg) 108 | //printf("cont mode enabled: %d\n", __llvm_profile_is_continuous_mode_enabled()); 109 | //__llvm_profile_enable_continuous_mode(); 110 | //ZC arg[32]={0};init(0,(char**)(S[]){(S)"b"}); 111 | //if(a==2){strncpy(arg,c[1],31);arg[31]='\0';memset(c[1],0,32);c=0;} 112 | 113 | //:~ 114 | -------------------------------------------------------------------------------- /t/t.hsh.c: -------------------------------------------------------------------------------- 1 | #include"t.h" 2 | #include"../h.h" 3 | 4 | #define TEST_HT_STRESS 5 | 6 | #include//rand 7 | enum charsets { CHARSET_ALNUM, CHARSET_AZaz, CHARSET_AZ, CHARSET_az}; 8 | char*csets[]={ 9 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 10 | "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", 11 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 12 | "abcdefghijklmnopqrstuvwxyz" 13 | };ZS rnd_str(S,SZT,C); 14 | 15 | UJ csums[]={1435,13992,5376450523,107282683043};//sdbm|djb2 16 | UJ CSM(I i){R csums[2*(HFN((S)"",0)==5381)+i];} 17 | 18 | //#define expmem(n) ((n)*(sizeof(pbkt)+1)+total) 19 | #define expmem(n) ((n)*(sizeof(pbkt))) 20 | UNIT(hsh, 21 | 22 | HT t=hnew((S)"tst",2,10); //k; 31 | MEM(xC, keys[i], xn)) 32 | 33 | EQ_I(t->cnt, n, "htable should contain 6 elements") 34 | EQ_I(hdbg(t,0,1), t->cnt, "htable counter should match internal check") 35 | EQ_I(t->mem, expmem(n), "htable mem usage should match expected") 36 | EQ_K(hdbg(t,0,0), CSM(0), "htable checksum must match expected") 37 | 38 | N(n,if(bkts[i]!=hget(t,(S)keys[i],sl(keys[i])))FAIL("hash table must be stable")) 39 | EQ_I(t->cnt, n, "htable counter should stay the same") 40 | EQ_I(hdbg(t,0,1), t->cnt, "htable counter should match internal check") 41 | EQ_I(t->mem, expmem(n), "htable mem usage should match expected") 42 | EQ_K(hdbg(t,0,0), CSM(0), "htable checksum must match expected") 43 | //hdbg(t,0,0); 44 | TRUE(hload(t) >0.85, "htable load factor should be above 0.85") 45 | 46 | I c;N(c=sl(charset),total+=i+1;hget(t,(S)charset+i,c-i));//uppercase only - cannot be any of keys[] 47 | EQ_I(t->mem, expmem(n+sl(charset)), "htable mem usage should match expected") 48 | EQ_I(hdbg(t,0,1), t->cnt, "htable counter should match internal check") 49 | EQ_K(hdbg(t,0,0), CSM(1), "htable checksum must match expected") 50 | //hdbg(t,1,0); 51 | TRUE(hload(t) >0.85, "htable load factor should be above 0.85") 52 | 53 | #ifdef TEST_HT_STRESS 54 | //! load factor under stress 55 | N(10000,I rlen=rand()%100;S s=(S)calloc(1,rlen+1);total+=rlen;rnd_str(s,rlen,CHARSET_ALNUM);hget(t,s,rlen);free(s))//!< rand load 56 | //hdbg(t,1,0); 57 | TRUE(hload(t) >0.8, "htable load factor should be above 0.8") 58 | #endif 59 | 60 | hdel(t); //!< release memory 61 | ) 62 | 63 | #ifdef TEST_HT_STRESS 64 | ZS rnd_str(S dest,size_t size,C cs){ 65 | P(41 16 | 1<2 17 | 1=2 18 | 2=2 19 | 20 | c[i]{n:0;W(x>1){x:$[x&1;(\x)+x+1;/x];n+:1};n} 21 | c[9] 22 | l[i]{r:0;N(x){r+:2};r} 23 | a[ii]$[x;a[-x;$[y;a[x;-y];1]];+y] 24 | b[Ii]{h:#x;l:0;W(h>l)$[y>x[i:/l+h];l:i+1;h:i];l} 25 | f[iII]{m:0;$[k:-x;W(x){x-:1;j:*y;N(k)y[i]:y[+i];y[k]:j;j:f[k;y;z];$[m(t:p*p)+u:q*q){m-:1;q:s+2*p*q;p:r+t-u};k+:0=m}};k} 29 | 30 | \w 31 | 32 | /test 33 | l[10] 34 | a[3;4] 35 | x:!9 36 | b[x;7] 37 | y:!8 38 | z:!8 39 | f[#y;y;z] 40 | w:t[0;2] 41 | c[w] 42 | /m[9] FIXME 43 | 44 | \w 45 | 46 | /time 47 | \t:2000 a[3;4] 48 | x:!1000 49 | \t N(1000000)b[x;1023&i] 50 | y:!8 51 | z:!8 52 | \t:20 f[#y;y;z] 53 | \t:100 t[0;13] 54 | w:t[0;13] 55 | \t:100 c[w] 56 | /\t:30 m[100] FIXME 57 | \v 58 | \f 59 | 60 | \-w 61 | \-x 62 | \-y 63 | \-z 64 | \-a 65 | \-b 66 | \-c 67 | \-f 68 | \-m 69 | \-t 70 | \-l 71 | \v 72 | \f 73 | 74 | \w 75 | \\ 76 | -------------------------------------------------------------------------------- /u.c: -------------------------------------------------------------------------------- 1 | #pragma GCC diagnostic ignored "-Wunsequenced" 2 | #pragma GCC diagnostic ignored "-Wsequence-point" 3 | 4 | #include"a.h" 5 | //extern I clz(I n); 6 | Z_ UI clz(UI x){R __builtin_clz(x);} 7 | 8 | #define ff (0x3f&*s++) 9 | #define M(m) (!((CP)m&c)) 10 | #define uf(b,s) *d=b|(C)(c>>s); 11 | #define um(i,s) d[i]=0x80|(C)(c>>s); 12 | #define ux(i,x) d[i]=0x80|(C)((x)&0x3f) 13 | #define ut(i) ux(i,c) 14 | #define ue(b,s) case b:ux(w-(b-1),c>>s); 15 | #define U4(c) 0xf0==(0xf8&c) 16 | #define U3(c) 0xe0==(0xf0&c) 17 | #define U2(c) 0xc0==(0xe0&c) 18 | 19 | //! set cp to the first codepoint in s and return the address of the next cp 20 | S cp(S s,CP*cp){R*cp=U4(*s)?(0x07&*s++)<<18|ff<<12|ff<<6|ff:U3(*s)?(0x0f&*s++)<<12|ff<<6|ff:U2(*s)?(0x1f&*s++)<<6|ff:*s++,s;} 21 | S us(S h,S n){CP t;S m,s;P(!*n,h)W(*h){m=h;s=n;W(*h==*s&&(*h&&*s))h++,s++;P(!*s,m)h=cp(m,&t);}R 0;}//!< position of utf needle in utf haystack 22 | S uc(S s,CP c){C d[5]={0,0,0,0,0};P(!c,W(*s)s++;s)$(M(0xffffff80),*d=(C)c)//!< find first match of codepoint c in the utf string s 23 | $(M(0xfffff800),uf(0xc0,6)ut(1))$(M(0xffff0000),uf(0xe0,12)um(1,6)ut(2))$(M(0xffff0000),uf(0xf0,18)um(1,12)um(2,6)ut(3));R us(s,d);} 24 | UI ul(S s){UI n=0;W(*s){$(U4(*s),s+=4)$(U3(*s),s+=3)$(U2(*s),s+=2)s++;n++;}R n;}//!< count codepoints in utf string s excluding terminal 25 | CP at(S s,UI i){CP r=0;UI n=0;W(i-n++&&*s){$(U4(*s),s+=4)$(U3(*s),s+=3)$(U2(*s),s+=2)s++;}R cp(s,&r),r;}//!< return codepoint at index i in s 26 | C cw(CP c){P(!c,1)static const C l[32]={1,1,1,1,1,1,1,2,2,2,2,3,3,3,3,3,4,4,4,4,4,5,5,5,5,5,6,6,6,6,6,7};R l[31-clz(c)];}//!< codepoint width in bytes 27 | //V uen(CP c,S d){C w;S(w=cw(c),ue(7,30)ue(6,24)ue(5,18)ue(4,12)ue(3,6)ue(2,0)*d=(0xFF00uL>>w)|(c>>(6*w-6));break;C(1,*d=(C)c));R w;}//!< encode cp into buffer d (<=7 bytes) 28 | 29 | //:~ 30 | --------------------------------------------------------------------------------