r = emalloc(sizeof(Num));
r->ref = 1;
- r->p = emalloc(0);
+ r->p = emalloc(sizeof(mpdigit));
mpassign(mpzero, r);
return r;
}
else
mpassign(b, a);
break;
+ case '$':
+ a->b = b->b;
+ mpxtend(b, mptoi(a), a);
+ break;
}
numdecref(b);
return a;
if(mpcmp(n, mpzero) != 0)
switch(b){
case 16: *--q = 'x'; *--q = '0'; break;
- case 10: if(outbase != 0 && outbase != 10) {*--q = 'd'; *--q = '0';} break;
+ case 10: if(outbase != 0 && outbase != 10 || inbase != 10) {*--q = 'd'; *--q = '0';} break;
case 8: *--q = '0'; break;
case 2: *--q = 'b'; *--q = '0'; break;
}
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;
%left unary
%left '*' '/' '%'
%right LOEXP
+%right '$'
%{
int save;
| '-' expr %prec unary { $$ = nummod($2); if($$ != nil) mpsub(mpzero, $$, $$); }
| '~' expr %prec unary { $$ = nummod($2); if($$ != nil) mpnot($$, $$); }
| '!' expr %prec unary { $$ = nummod($2); if($$ != nil) {itomp(mpcmp($$, mpzero) == 0, $$); $$->b = 0; } }
+ | '$' expr { $$ = nummod($2); if($$ != nil) if($2->sign > 0) mpxtend($2, mpsignif($2), $$); else mpassign($2, $$); }
| expr '?' expr ':' expr %prec '?' {
if($1 == nil || mpcmp($1, mpzero) != 0){
$$ = $3;
if($$ == nil) error("no last result");
else numincref($$);
}
+ | expr '$' expr { $$ = numbin('$', $1, $3); }
elist: { $$.n = 0; } | elist1
elist1: expr { $$.x[0] = $1; $$.n = 1; }
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)
{
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);