pc(1): fix memory leak and add clog() function

This commit is contained in:
aiju 2017-04-02 14:47:23 +00:00
parent e0087b2a78
commit e09adf5944
2 changed files with 52 additions and 2 deletions

View file

@ -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

View file

@ -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;
@ -819,6 +832,39 @@ fnxtend(int, Num **a)
return a[0];
}
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)
{
@ -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);