View Single Post
Old 2012-10-27, 22:08   #1
EdH
 
EdH's Avatar
 
"Ed Hall"
Dec 2009
Adirondack Mtns

76438 Posts
Default Porting pari/gp routines into a C program??

This will be detailed; possibly much more information than is needed, but I'm getting frustrated (again).

Background: I'm trying to learn how to use some pari/gp routines within some c programs, via an IDE called Code::Blocks. Unfortunately, I don't understand some of the declarations for the inner workings of pari/gp. I didn't think I needed to, to construct a simple executable. Apparently, I was wrong (yet, again).

I have the following function, called cycle02.gp, that looks for aliquot cycles:
Code:
findcycle(a,b)=
{
  for(e=a,b,
    i=e;
    for(c=1,10,
      i=sigma(i)-i;
      if(i<e,
        break()
      );
      if(i==e,
        print(i,"  ",c);
        break()
      )
    );
  )
}
I can load this into gp and run it:
Code:
[user@comp pari]$ gp2c-run -g cycle02.gp
                  GP/PARI CALCULATOR Version 2.3.5 (released)
          amd64 running linux (x86-64/GMP-4.3.2 kernel) 64-bit version
      compiled: Feb  8 2011, gcc-4.6.0 20110205 (Red Hat 4.6.0-0.6) (GCC) 
    (readline v6.2 enabled [was v6.1 in Configure], extended help available)

                     Copyright (C) 2000-2006 The PARI Group

PARI/GP is free software, covered by the GNU General Public License, and 
comes WITHOUT ANY WARRANTY WHATSOEVER.

Type ? for help, \q to quit.
Type ?12 for how to get moral (and possibly technical) support.

parisize = 8000000, primelimit = 500000
? findcycle(10000,20000)
10744  2
12285  2
12496  5
17296  2
?
gp2c creates the following file cycle02.gp.c:
Code:
/*-*- compile-command: "/usr/bin/gcc -c -o cycle02.gp.o -O3 -Wall -fno-strict-aliasing -fomit-frame-pointer -fPIC -I/usr/include cycle02.gp.c && /usr/bin/gcc -o cycle02.gp.so -shared -O3 -Wall -fno-strict-aliasing -fomit-frame-pointer -fPIC -Wl,-shared cycle02.gp.o -lc -ldl -lm -L/usr/lib64 -lgmp -L/usr/lib64 -lpari"; -*-*/
#include <pari/pari.h>
/*
GP;install("init_cycle02","v","init_cycle02","./cycle02.gp.so");
GP;install("findcycle","vD0,G,D0,G,","findcycle","./cycle02.gp.so");
*/
void init_cycle02(void);
void findcycle(GEN a, GEN b);
/*End of prototype*/

void
init_cycle02(void)      /* void */
{
  pari_sp ltop = avma;
  avma = ltop;
  return;
}

void
findcycle(GEN a, GEN b)      /* void */
{
  pari_sp ltop = avma;
  GEN i = pol_x[fetch_user_var("i")];
  {
    pari_sp btop = avma, st_lim = stack_lim(btop, 1);
    GEN e = gen_0;
    for (e = gcopy(a); gcmp(e, b) <= 0; e = gaddgs(e, 1))
    {
      i = e;
      {
        pari_sp btop = avma, st_lim = stack_lim(btop, 1);
        long c;
        for (c = 1; c <= 10; ++c)
        {
          i = gsub(gsumdiv(i), i);
          if (gcmp(i, e) < 0)
            break;
          if (gequal(i, e))
          {
            pariprintf("%Z  %ld\n", i, c);
            break;
          }
          if (low_stack(st_lim, stack_lim(btop, 1)))
            i = gerepilecopy(btop, i);
        }
      }
      if (low_stack(st_lim, stack_lim(btop, 1)))
        gerepileall(btop, 2, &e, &i);
    }
  }
  avma = ltop;
  return;
}
I took the above routines and tried to build a basic program in c using Code::Blocks:
Code:
#include <stdio.h>
#include <stdlib.h>
#include "pari.h"

void init_cycle02(void);
void findcycle(GEN a, GEN b);


int main(int argc, char *argv[])
{
    GEN j, k;

    j=(GEN)100000;
    k=(GEN)200000;

    findcycle(j, k);
    return 0;
}

void
init_cycle02(void)      /* void */
{
  pari_sp ltop = avma;
  avma = ltop;
  return;
}

void
findcycle(GEN a, GEN b)      /* void */
{
  pari_sp ltop = avma;
  GEN i = pol_x[fetch_user_var("i")];
  {
    pari_sp btop = avma, st_lim = stack_lim(btop, 1);
    GEN e = gen_0;
    for (e = gcopy(a); gcmp(e, b) <= 0; e = gaddgs(e, 1))
    {
      i = e;
      {
        pari_sp btop = avma, st_lim = stack_lim(btop, 1);
        long c;
        for (c = 1; c <= 10; ++c)
        {
          i = gsub(gsumdiv(i), i);
          if (gcmp(i, e) < 0)
            break;
          if (gequal(i, e))
          {
            pariprintf("%Z  %ld\n", i, c);
            break;
          }
          if (low_stack(st_lim, stack_lim(btop, 1)))
            i = gerepilecopy(btop, i);
        }
      }
      if (low_stack(st_lim, stack_lim(btop, 1)))
        gerepileall(btop, 2, &e, &i);
    }
  }
  avma = ltop;
  return;
}
and, then I compiled and ran the program:
Code:
Process returned -1 (0xFFFFFFFF)   execution time: 0.004 s
Press ENTER to continue.
So, then I ran the debugger:
Code:
Program received signal SIGSEGV, Segmentation fault.
In fetch_named_var () (usr/lib64/libpari-gmp.so.2)
Debugger finished with status 0
I am obviously missing something...

Would anyone like to point me in a direction where I can find the missing details on how to use pari/gp functions within c programs?

Thanks!
EdH is offline   Reply With Quote