Vasili Burdo on Wed, 15 Jul 2015 19:36:45 +0200


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Support of binary and hexadecimal integers in PARI/GP


Hi,

The patch I sent in first message was incorrect - I didnt create
function declaration file
As result, full rebuild has destroyed my changes in default.h

Here is correct patch which fixes this problem.
BTW, I'm not very good at writing documentation - feel free to fix
desription I added to src/functions/default/base
diff --git a/src/functions/default/base b/src/functions/default/base
new file mode 100644
index 0000000..357ccc8
--- /dev/null
+++ b/src/functions/default/base
@@ -0,0 +1,16 @@
+Function: _def_base
+Class: default
+Section: default
+C-Name: sd_base
+Prototype:
+Help:
+Doc: set base for printing integer numbers.
+ Possible values are \kbd{"dec"}, \kbd{"hex"}, \kbd{"HEX"}.
+
+ Value \kbd{"dec"} sets output format to decimal.
+ Value \kbd{"hex"} sets output format to lower case hexadecimal.
+ Value \kbd{"HEX"} sets output format to upper case hexadecimal.
+
+ The default value is \kbd{"dec"} - print integer numbers in
+ decimal.
+
diff --git a/src/headers/paridecl.h b/src/headers/paridecl.h
index 520673c..793b2f2 100644
--- a/src/headers/paridecl.h
+++ b/src/headers/paridecl.h
@@ -2217,6 +2217,7 @@ GEN sd_debugmem(const char *v, long flag);
 GEN sd_factor_add_primes(const char *v, long flag);
 GEN sd_factor_proven(const char *v, long flag);
 GEN sd_format(const char *v, long flag);
+GEN sd_base(const char *v, long flag);
 GEN sd_histsize(const char *v, long flag);
 GEN sd_log(const char *v, long flag);
 GEN sd_logfile(const char *v, long flag);
@@ -2447,7 +2448,7 @@ GEN     Str(GEN g);
 GEN     Strchr(GEN g);
 GEN     Strexpand(GEN g);
 GEN     Strtex(GEN g);
-void    brute(GEN g, char format, long dec);
+void    brute(GEN g, char format, long dec, int base);
 void    dbgGEN(GEN x, long nb);
 void    error0(GEN g);
 void    dbg_pari_heap(void);
@@ -2464,7 +2465,7 @@ void    gpinstall(const char *s, const char *code,
 GEN     gsprintf(const char *fmt, ...);
 GEN     gvsprintf(const char *fmt, va_list ap);
 char*   itostr(GEN x);
-void    matbrute(GEN g, char format, long dec);
+void    matbrute(GEN g, char format, long dec, int base);
 char*   os_getenv(const char *s);
 void    (*os_signal(int sig, void (*f)(int)))(int);
 void    outmat(GEN x);
diff --git a/src/headers/paristio.h b/src/headers/paristio.h
index 5ff7bdf..faca0a7 100644
--- a/src/headers/paristio.h
+++ b/src/headers/paristio.h
@@ -226,6 +226,7 @@ typedef struct {
 typedef struct {
   char format; /* e,f,g */
   long sigd;   /* -1 (all) or number of significant digits printed */
+  int base;    /* 10, 16, -16 - i.e. decimal, 0xhex, or 0xHEX */
   int sp;      /* 0 = suppress whitespace from output */
   int prettyp; /* output style: raw, prettyprint, etc */
   int TeXstyle;
diff --git a/src/language/anal.c b/src/language/anal.c
index f77cf3a..fd01269 100644
--- a/src/language/anal.c
+++ b/src/language/anal.c
@@ -436,11 +436,35 @@ type0(GEN x)
 /*******************************************************************/
 
 #ifdef LONG_IS_64BIT
-static const long MAX_DIGITS = 19;
+static const long MAX_DIGITS  = 19;
+static const long MAX_XDIGITS = 15;
+static const long MAX_BDIGITS = 63;
 #else
-static const long MAX_DIGITS = 9;
+static const long MAX_DIGITS  = 9;
+static const long MAX_XDIGITS = 7;
+static const long MAX_BDIGITS = 31;
 #endif
 
+static int
+ishex(const char **s)
+{
+    if('0' == **s && ('x' == (*s)[1] || 'X' == (*s)[1])) {
+        *s += 2;
+        return 1;
+    }
+    return 0;
+}
+
+static int
+isbin(const char **s)
+{
+    if('0' == **s && ('b' == (*s)[1] || 'B' == (*s)[1])) {
+        *s += 2;
+        return 1;
+    }
+    return 0;
+}
+
 static ulong
 number(int *n, const char **s)
 {
@@ -450,6 +474,43 @@ number(int *n, const char **s)
   return m;
 }
 
+static ulong
+hexnumber(int *n, const char **s)
+{
+  ulong m = 0;
+  for(*n = 0; *n < MAX_XDIGITS; (*n)++,(*s)++)
+  {
+    if( **s >= '0' && **s <= '9') {
+        m = 16*m + (**s - '0');
+        continue;
+    }
+    if( **s >= 'A' && **s <= 'F') {
+        m = 16*m + (**s - 'A' + 10);
+        continue;
+    }
+    if( **s >= 'a' && **s <= 'f') {
+        m = 16*m + (**s - 'a' + 10);
+        continue;
+    }
+    break;
+  }
+  return m;
+}
+
+static ulong
+binnumber(int *n, const char **s)
+{
+  ulong m = 0;
+  for(*n = 0; *n < MAX_BDIGITS; (*n)++,(*s)++)
+  {
+    if( **s == '0' || **s == '1') {
+        m = 2*m + (**s - '0');
+    } else
+        break;
+  }
+  return m;
+}
+
 ulong
 u_pow10(int n)
 {
@@ -494,6 +555,34 @@ int_read_more(GEN y, const char **ps)
   return y;
 }
 
+static GEN
+hex_read_more(GEN y, const char **ps)
+{
+  pari_sp av = avma;
+  int i = 0, nb;
+  while (isxdigit((int)**ps))
+  {
+    ulong m = hexnumber(&nb, ps);
+    if (avma != av && ++i > 4) { avma = av; i = 0; } /* HACK gerepile */
+    y = addumului(m, 1UL << (nb*4), y);
+  }
+  return y;
+}
+
+static GEN
+bin_read_more(GEN y, const char **ps)
+{
+  pari_sp av = avma;
+  int i = 0, nb;
+  while (**ps == '0' || **ps == '1')
+  {
+    ulong m = binnumber(&nb, ps);
+    if (avma != av && ++i > 4) { avma = av; i = 0; } /* HACK gerepile */
+    y = addumului(m, 1UL << nb, y);
+  }
+  return y;
+}
+
 static long
 exponent(const char **pts)
 {
@@ -563,8 +652,19 @@ static GEN
 int_read(const char **s)
 {
   int nb;
-  GEN y = utoi(number(&nb, s));
-  if (nb == MAX_DIGITS) y = int_read_more(y, s);
+  GEN y;
+  if (isbin(s)) {
+    y = utoi(binnumber(&nb, s));
+    if (nb == MAX_BDIGITS) y = bin_read_more(y, s);
+  } else
+  if (ishex(s)) {
+    y = utoi(hexnumber(&nb, s));
+    if (nb == MAX_XDIGITS) y = hex_read_more(y, s);
+  } else
+  {
+    y = utoi(number(&nb, s));
+    if (nb == MAX_DIGITS) y = int_read_more(y, s);
+  }
   return y;
 }
 
@@ -688,6 +788,16 @@ pari_lex(union token_value *yylval, struct node_loc *yylloc, char **lex)
     yylloc->end=*lex;
     return '.';
   }
+  if (isbin((const char**)lex))
+  {
+    while (**lex=='0' || **lex=='1') ++*lex;
+    return KINTEGER;
+  }
+  if (ishex((const char**)lex))
+  {
+    while (isxdigit((int)**lex)) ++*lex;
+    return KINTEGER;
+  }
   if (isdigit((int)**lex))
   {
     int token=skipconstante(lex);
diff --git a/src/language/default.c b/src/language/default.c
index bf7b337..75aad76 100644
--- a/src/language/default.c
+++ b/src/language/default.c
@@ -354,6 +354,35 @@ sd_format(const char *v, long flag)
 }
 
 GEN
+sd_base(const char *v, long flag)
+{
+  pariout_t *fmt = GP_DATA->fmt;
+  if(v) {
+    if (0 == strcmp(v,"dec")) {
+      fmt->base = 10;
+    } else
+    if (0 == strcmp(v,"hex")) {
+      fmt->base = 16;
+    } else
+    if (0 == strcmp(v,"HEX")) {
+      fmt->base = -16;
+    } else {
+      pari_err(e_SYNTAX,"default: bad base",v,v);
+    }
+  }
+  if (flag == d_RETURN)  {
+    return stoi(fmt->base);
+  }
+  if (flag == d_ACKNOWLEDGE)
+    pari_printf("   base = %s\n",
+        fmt->base == 10 ? "dec" :
+        fmt->base == 16 ? "hex" :
+        fmt->base ==-16 ? "HEX" :
+        "error");
+  return gnil;
+}
+
+GEN
 sd_compatible(const char *v, long flag)
 {
   const char *msg[] = {
@@ -774,9 +803,9 @@ static void
 init_fmt(gp_data *D)
 {
 #ifdef LONG_IS_64BIT
-  static pariout_t DFLT_OUTPUT = { 'g', 38, 1, f_PRETTYMAT, 0 };
+  static pariout_t DFLT_OUTPUT = { 'g', 38, 10, 1, f_PRETTYMAT, 0 };
 #else
-  static pariout_t DFLT_OUTPUT = { 'g', 28, 1, f_PRETTYMAT, 0 };
+  static pariout_t DFLT_OUTPUT = { 'g', 28, 10, 1, f_PRETTYMAT, 0 };
 #endif
   D->fmt = &DFLT_OUTPUT;
 }
diff --git a/src/language/es.c b/src/language/es.c
index 2ac5919..8194be6 100644
--- a/src/language/es.c
+++ b/src/language/es.c
@@ -2743,7 +2743,18 @@ bruti_intern(GEN g, pariout_t *T, outString *S, int addsign)
   {
     case t_INT:
       if (addsign && signe(g) < 0) str_putc(S, '-');
-      str_absint(S, g); break;
+      int base=T->base;
+      if(base != 10) {
+        if(cmpiu(g,16) < 0)
+          base = 10;
+      }
+      if(base != 10) {
+        str_putc(S, '0');
+        str_putc(S, 'x');
+      }
+      fmtnum(S,0,absi(g),base,-1,0,0,0);
+      //str_absint(S, g);
+      break;
     case t_REAL:
     {
       pari_sp av;
@@ -3239,10 +3250,11 @@ texi_sign(GEN g, pariout_t *T, outString *S, int addsign)
 /**                                                               **/
 /*******************************************************************/
 static void
-_initout(pariout_t *T, char f, long sigd, long sp)
+_initout(pariout_t *T, char f, long sigd, long sp, int base)
 {
   T->format = f;
   T->sigd = sigd;
+  T->base = base;
   T->sp = sp;
 }
 
@@ -3269,32 +3281,32 @@ gen_output(GEN x, pariout_t *T)
 }
 
 void
-brute(GEN g, char f, long d)
+brute(GEN g, char f, long d, int base)
 {
-  pariout_t T; _initout(&T,f,d,0);
+  pariout_t T; _initout(&T,f,d,0,base);
   gen_output_fun(g, &T, &bruti);
 }
 
 void
-matbrute(GEN g, char f, long d)
+matbrute(GEN g, char f, long d, int base)
 {
-  pariout_t T; _initout(&T,f,d,1);
+  pariout_t T; _initout(&T,f,d,1,base);
   gen_output_fun(g, &T, &matbruti);
 }
 
 void
 texe(GEN g, char f, long d)
 {
-  pariout_t T; _initout(&T,f,d,0);
+  pariout_t T; _initout(&T,f,d,0,10);
   gen_output_fun(g, &T, &texi);
 }
 
 void
 output(GEN x)
-{ brute(x,'g',-1); pari_putc('\n'); pari_flush(); }
+{ brute(x,'g',-1,10); pari_putc('\n'); pari_flush(); }
 void
 outmat(GEN x)
-{ matbrute(x,'g',-1); pari_putc('\n'); pari_flush(); }
+{ matbrute(x,'g',-1,10); pari_putc('\n'); pari_flush(); }
 
 void
 err_printf(const char* fmt, ...)
diff --git a/src/language/gplib.c b/src/language/gplib.c
index 93c5996..189e9dd 100644
--- a/src/language/gplib.c
+++ b/src/language/gplib.c
@@ -301,6 +301,8 @@ slash_commands(void)
 ##      : print time for last result\n\
 \\\\      : comment up to end of line\n\
 \\a {n}  : print result in raw format (readable by PARI)\n\
+\\A {n}  : print result in different base - i.e. in decimal\n\
+          when hex is default or vice versa\n\
 \\B {n}  : print result in beautified format\n\
 \\c      : list all commands (same effect as ?*)\n\
 \\d      : print all defaults\n\
@@ -312,6 +314,9 @@ slash_commands(void)
 \\l {f}  : enable/disable logfile (set logfile=f)\n\
 \\m {n}  : print result in prettymatrix format\n\
 \\o {n}  : set output method (0=raw, 1=prettymatrix, 2=prettyprint, 3=2-dim)\n\
+\\ox     : print integers in lower case hexadecimal: 0x1234abcd\n\
+\\oX     : print integers in upper case hexadecimal: 0x1234ABCD\n\
+\\od     : print integers in decimal\n\
 \\p {n}  : change real precision\n\
 \\ps{n}  : change series precision\n\
 \\q      : quit completely this GP session\n\
@@ -1690,7 +1695,7 @@ escape(const char *tch, int ismain)
   char c;
   switch ((c = *s++))
   {
-    case 'w': case 'x': case 'a': case 'b': case 'B': case 'm':
+    case 'w': case 'x': case 'a': case 'A': case 'b': case 'B': case 'm':
     { /* history things */
       long d;
       GEN x;
@@ -1706,8 +1711,9 @@ escape(const char *tch, int ismain)
         case 'B': /* prettyprinter */
           if (tex2mail_output(x,0)) break;
         case 'b': /* fall through */
-        case 'm': matbrute(x, GP_DATA->fmt->format, -1); break;
-        case 'a': brute(x, GP_DATA->fmt->format, -1); break;
+        case 'm': matbrute(x, GP_DATA->fmt->format, -1, GP_DATA->fmt->base); break;
+        case 'a': brute(x, GP_DATA->fmt->format, -1, GP_DATA->fmt->base); break;
+        case 'A': brute(x, GP_DATA->fmt->format, -1, GP_DATA->fmt->base == 10 ? -16 : 10); break;
         case 'x': dbgGEN(x, get_int(s, -1)); break;
         case 'w':
           s = get_sep(s); if (!*s) s = current_logfile;
@@ -1740,7 +1746,14 @@ escape(const char *tch, int ismain)
       }
       (void)sd_log(pari_logfile?"0":"1",d_ACKNOWLEDGE);
       break;
-    case 'o': (void)sd_output(*s? s: NULL,d_ACKNOWLEDGE); break;
+    case 'o': //(void)sd_output(*s? s: NULL,d_ACKNOWLEDGE); break;
+      switch(*s) {
+        case 'd': (void)sd_base("dec",d_ACKNOWLEDGE); break;
+        case 'x': (void)sd_base("hex",d_ACKNOWLEDGE); break;
+        case 'X': (void)sd_base("HEX",d_ACKNOWLEDGE); break;
+        default:  (void)sd_output(*s? s: NULL,d_ACKNOWLEDGE); break;
+      }
+      break;
     case 'p':
       switch (*s)
       {