diff options
author | aiju <devnull@localhost> | 2017-04-02 14:47:23 +0000 |
---|---|---|
committer | aiju <devnull@localhost> | 2017-04-02 14:47:23 +0000 |
commit | e09adf59442cd36888eaea1d76e66ff3259d16b8 (patch) | |
tree | 53fa8e7631019a787afd920b522eb98bcd587ba7 /sys | |
parent | e0087b2a78d7229d8d2b148b8def688be6639797 (diff) |
pc(1): fix memory leak and add clog() function
Diffstat (limited to 'sys')
-rw-r--r-- | sys/man/1/pc | 3 | ||||
-rw-r--r-- | sys/src/cmd/pc.y | 51 |
2 files changed, 52 insertions, 2 deletions
diff --git a/sys/man/1/pc b/sys/man/1/pc index 9c86eba9a..a3926f19c 100644 --- a/sys/man/1/pc +++ b/sys/man/1/pc @@ -105,6 +105,9 @@ Truncate each of the \fIa\d\s7i\s0\u\fR arguments to \fIn\d\s7i\s0\u\fR bits and .I gcd(n,m) The greatest common divisor of \fIn\fR and \fIm\fR. .TP +.I clog(a,b) +The ceiling of the logarithm of \fIa\fR with respect to base \fIb\fR. \fIb\fR can be omitted, in which case it defaults to 2. +.TP .I minv(n,m) The inverse of \fIn\fR mod \fIm\fR. .TP diff --git a/sys/src/cmd/pc.y b/sys/src/cmd/pc.y index 73eb30110..f656ee292 100644 --- a/sys/src/cmd/pc.y +++ b/sys/src/cmd/pc.y @@ -310,15 +310,28 @@ numprint(Num *n) free(t); } +void +numdecrefs(int n, Num **x) +{ + int i; + + for(i = 0; i < n; i++) + numdecref(x[i]); +} + Num * fncall(Symbol *s, int n, Num **x) { int i; - if(s->t != SYMFUNC) + if(s->t != SYMFUNC){ + numdecrefs(n, x); return error("%s: not a function", s->name); - else if(s->nargs >= 0 && s->nargs != n) + } + else if(s->nargs >= 0 && s->nargs != n){ + numdecrefs(n, x); return error("%s: wrong number of arguments", s->name); + } for(i = 0; i < n; i++) if(x[i] == nil) return nil; @@ -820,6 +833,39 @@ fnxtend(int, Num **a) } Num * +fnclog(int n, Num **a) +{ + int r; + + if(n != 1 && n != 2){ + numdecrefs(n, a); + return error("clog: wrong number of arguments"); + } + if(mpcmp(a[0], mpzero) <= 0 || n == 2 && mpcmp(a[1], mpone) <= 0){ + numdecref(a[0]); + return error("invalid argument"); + } + if(n == 1 || mpcmp(a[1], mptwo) == 0){ + a[0] = nummod(a[0]); + mpsub(a[0], mpone, a[0]); + itomp(mpsignif(a[0]), a[0]); + a[0]->b = 0; + if(n == 2) numdecref(a[1]); + return a[0]; + } + a[0] = nummod(a[0]); + for(r = 0; mpcmp(a[0], mpone) > 0; r++){ + mpadd(a[0], a[1], a[0]); + mpsub(a[0], mpone, a[0]); + mpdiv(a[0], a[1], a[0], nil); + } + itomp(r, a[0]); + a[0]->b = 0; + numdecref(a[1]); + return a[0]; +} + +Num * fnubits(int, Num **a) { if(a[0]->sign < 0){ @@ -986,6 +1032,7 @@ main(int argc, char **argv) regfunc("ceil", fnceil, 2); regfunc("trunc", fntrunc, 2); regfunc("xtend", fnxtend, 2); + regfunc("clog", fnclog, -1); regfunc("ubits", fnubits, 1); regfunc("sbits", fnsbits, 1); regfunc("nsa", fnnsa, 1); |