Пример #1
0
static void
do_buttondown(GR_EVENT_BUTTON *ep)
{
	mwin *	mwp;
	static int app_no;
	char *userargs;
	int r,taskid,queid,n;
	char s[16];
	char *argv[2];

	if (ep->wid == w1) {
		app_no = ep->y / fheight;
		if (app_no >= num_apps) {
			app_no = num_apps - 1;
		}
		
		taskid=syscall_pgm_load(
			Apps[app_no].app_path,
			SYSCALL_PGM_TYPE_VGA|SYSCALL_PGM_TYPE_IO);
		if(taskid<0) {
			display_puts("load error=");
			int2dec(-taskid,s);
			display_puts(s);
			display_puts("\n");
			return;
		}

		argv[0]=Apps[app_no].app_path;
		argv[1]="";
		userargs=environment_copy_session();
		n = environment_get_session_size();
		environment_make_args(userargs, 2, argv);
		r = syscall_pgm_setargs(taskid, userargs, n);
		if(r<0) {
			display_puts("setargs error=");
			int2dec(-r,s);
			display_puts(s);
			display_puts("\n");
			return;
		}
		mfree(userargs);

		queid = environment_getqueid();
		r=syscall_pgm_start(taskid, queid);
		if(r<0) {
			display_puts("start error=");
			int2dec(-r,s);
			display_puts(s);
			display_puts("\n");
			return;
		}

	} else if ((mwp = IsDecoration(ep->wid)) != NULL) {
		GrRaiseWindow(mwp->wid);
		GrRaiseWindow(mwp->fid);
		in_motion = mwp;
		move_xoff = ep->x;
		move_yoff = ep->y;
 	}
}
Пример #2
0
void task_dbg_dumplist(void *lst)
{
  char s[10];
  struct TASK *tsk,*head=lst;
  list_for_each(head,tsk) {
    console_puts("T(");
    int2dec(tsk->id,s);
    console_puts(s);
    console_puts(",");
    int2dec(tsk->status,s);
    console_puts(s);
    console_puts(")");
  }
Пример #3
0
int cdfs_getinfo_response(unsigned short *seq, int *typecode)
{
  union cdfs_msg msg;
  int rc;

  if(cdfs_queid==0) {
    rc=cdfs_init();
    if(rc<0)
      return rc;
  }

  msg.h.size=sizeof(msg);
  rc=message_receive(MESSAGE_MODE_WAIT,CDFS_SRV_CDFS, CDFS_CMD_GETINFO, &msg);
  if(rc<0) {
    display_puts("getcode getresp=");
    int2dec(-rc,s);
    display_puts(s);
    display_puts("\n");
    return rc;
  }
  *seq = msg.getinfo.res.seq;
  *typecode = msg.getinfo.res.type;

  return 0;
}
Пример #4
0
int cdfs_getinfo_request(unsigned short seq,unsigned short devid)
{
  int rc;
  union cdfs_msg msg;

  if(cdfs_queid==0) {
    rc=cdfs_init();
    if(rc<0)
      return rc;
  }

  msg.h.size=sizeof(struct cdfs_req_getinfo);
  msg.h.service=CDFS_SRV_CDFS;
  msg.h.command=CDFS_CMD_GETINFO;
  msg.h.arg=environment_getqueid();
  msg.getinfo.req.seq=seq;
  msg.getinfo.req.devid=devid;
/*
int2dec(msg.req.queid,s);
display_puts(s);
*/
  rc=message_send(cdfs_queid, &msg);
  if(rc<0) {	
    display_puts("getcode sndcmd=");
    int2dec(-rc,s);
    display_puts(s);
    display_puts("\n");
    return rc;
  }

  return 0;
}
Пример #5
0
static int program_wait(int *exitcode, int tryflg)
{
  int taskid;
  char *userargs;
  int usersize;

  usersize = environment_get_session_size();
  userargs = malloc(usersize);
  if(userargs==0)
    return ERRNO_RESOURCE;

  taskid=environment_wait(exitcode, tryflg, userargs, usersize);
  if(taskid==ERRNO_OVER) {
    mfree(userargs);
    return taskid;
  }

  if(taskid<0) {
    display_puts("wait error=");
    int2dec(-taskid,s);
    display_puts(s);
    display_puts("\n");
    mfree(userargs);
    return taskid;
  }

  if(*exitcode & 0x8000) {
    exception_dump((void*)userargs, display_puts);
  }
  mfree(userargs);
  return taskid;
}
Пример #6
0
int cdfs_stat_response(unsigned short *seq, struct file_info *info, unsigned long bufsize)
{
  union cdfs_msg msg;
  int rc;

  if(cdfs_queid==0) {
    rc=cdfs_init();
    if(rc<0)
      return rc;
  }

  msg.h.size=sizeof(msg);
  rc=message_receive(MESSAGE_MODE_WAIT,CDFS_SRV_CDFS, CDFS_CMD_STAT, &msg);
  if(rc<0) {
    display_puts("getcode getresp=");
    int2dec(-rc,s);
    display_puts(s);
    display_puts("\n");
    return rc;
  }
  *seq = msg.stat.res.seq;
  unsigned long len = sizeof(struct file_info);
  if(len>bufsize)
    len = bufsize;
  memcpy(info, &msg.stat.res.info, len);
  if((int)(msg.stat.res.info.size) == -1)
    return 0;
  if(bufsize < sizeof(struct file_info))
    return 0;

  return 0;
}
Пример #7
0
int cdfs_stat_request(unsigned short seq,int handle)
{
  int rc;
  union cdfs_msg msg;

  if(cdfs_queid==0) {
    rc=cdfs_init();
    if(rc<0)
      return rc;
  }

  msg.h.size=sizeof(struct cdfs_req_readdir);
  msg.h.service=CDFS_SRV_CDFS;
  msg.h.command=CDFS_CMD_STAT;
  msg.h.arg=environment_getqueid();
  msg.stat.req.seq=seq;
  msg.stat.req.handle=handle;
/*
int2dec(msg.req.queid,s);
display_puts(s);
*/
  rc=message_send(cdfs_queid, &msg);
  if(rc<0) {	
    display_puts("cdfs_stat sndcmd=");
    int2dec(-rc,s);
    display_puts(s);
    display_puts("\n");
    return rc;
  }

  return 0;
}
Пример #8
0
int cdfs_read_response(unsigned short *seq, int *readbyte)
{
  union cdfs_msg msg;
  int rc;

  if(cdfs_queid==0) {
    rc=cdfs_init();
    if(rc<0)
      return rc;
  }

  msg.h.size=sizeof(msg);
  rc=message_receive(MESSAGE_MODE_WAIT,CDFS_SRV_CDFS, CDFS_CMD_READ, &msg);
  if(rc<0) {
    display_puts("getcode getresp=");
    int2dec(-rc,s);
    display_puts(s);
    display_puts("\n");
    return rc;
  }
  *seq = msg.read.res.seq;
  *readbyte = msg.read.res.readbyte;

  return rc;
}
Пример #9
0
int cdfs_open_response(unsigned short *seq, int *handle)
{
  union cdfs_msg msg;
  int rc;

  if(cdfs_queid==0) {
    rc=cdfs_init();
    if(rc<0)
      return rc;
  }

  msg.h.size=sizeof(msg);
  rc=message_receive(MESSAGE_MODE_WAIT,CDFS_SRV_CDFS, CDFS_CMD_OPEN, &msg);
  if(rc<0) {
    display_puts("cdfs open=");
    int2dec(-rc,s);
    display_puts(s);
    display_puts("\n");
    return rc;
  }
  *seq = msg.open.res.seq;
  *handle = msg.open.res.handle;

  return rc;
}
Пример #10
0
static void *pci_scan_bios(void)
{
  unsigned char *bios_addr;
  for(bios_addr = (void*)CFG_MEM_BIOSSTART;
      (unsigned long)bios_addr < CFG_MEM_BIOSMAX-sizeof(struct pci_bios) ;
      bios_addr++  )
  {
    if(memcmp(bios_addr,"_32_",4)!=0)
      continue;
    struct pci_bios *info=(void*)bios_addr;
    if(info->revision!=0)
      continue;
    if(info->length!=(unsigned char)1)
      continue;
    unsigned char i,checksum=0;
    for(i=0;i<sizeof(struct pci_bios);i++) {
      checksum += bios_addr[i];
    }
    if(checksum!=info->checksum)
      continue;

display_puts("entry=");
long2hex(info->entry,s);
display_puts(s);
display_puts(",rev=");
int2dec(info->revision,s);
display_puts(s);
display_puts(",len=");
int2dec(info->length,s);
display_puts(s);
display_puts(",chk=");
byte2hex(info->checksum,s);
display_puts(s);
display_puts("\n");

    return (void*)info->entry;
    //display_puts(".");
    //syscall_wait(100);
  }
  display_puts("PCI BIOS is not found\n");
  dump((void*)CFG_MEM_BIOSSTART);
  return 0;
}
Пример #11
0
static void indicateCannotComputeLog(int indexBase, int indexExp)
{
  char *ptrText;
  struct sFactors *pstFactors = &astFactorsGO[indexBase + 1];
  strcpy(textExp, "Cannot compute discrete logarithm: subgroup=");
  UncompressBigInteger(pstFactors->ptrFactor, &tmpBase);
  Bin2Dec(tmpBase.limbs, textExp + strlen(textExp), tmpBase.nbrLimbs, groupLen);
  strcpy(textExp + strlen(textExp), ", exponent=");
  ptrText = textExp + strlen(textExp);
  int2dec(&ptrText, indexExp);
  DiscreteLogPeriod.sign = SIGN_NEGATIVE;
}
Пример #12
0
int mouse_poll(void)
{
  union mou_msg msg;
  int r;

  msg.req.h.size=sizeof(msg);
  r=message_poll(mou_quewait,MOU_SRV_MOUSE, MOU_CMD_GETCODE, &msg);
  if(r<0) {
    display_puts("mousepoll getresp=");
    int2dec(-r,s);
    display_puts(s);
    display_puts("\n");
    return r;
  }

  return r;
}
Пример #13
0
int mouse_getcode(int *button, int *dx, int *dy)
{
  union mou_msg msg;
  int r;

  msg.req.h.size=sizeof(msg);
  r=message_receive(mou_quewait,MOU_SRV_MOUSE, MOU_CMD_GETCODE, &msg);
  if(r==ERRNO_OVER)
    return 0;
  if(r<0) {
    display_puts("getcode getresp=");
    int2dec(-r,s);
    display_puts(s);
    display_puts("\n");
    return r;
  }

  mouse_decode_code(&msg, button, dx, dy);
  return 1;
}
Пример #14
0
static int program_exec(int taskid,int argc, char *argv[])
{
  char *session;

  session=environment_copy_session();
  environment_make_args(session, argc, argv);
  taskid = environment_execimage(taskid, session);
  mfree(session);
  if(taskid==ERRNO_NOTEXIST)
    return taskid;
  if(taskid<0) {
    display_puts("exec error error=");
    int2dec(-taskid,s);
    display_puts(s);
    display_puts("\n");
    return taskid;
  }

  return taskid;
}
Пример #15
0
void tst_key(void)
{
  int r;

  r=keyboard_init();
  if(r<0) {
    display_puts("kbd init=");
    long2hex(-r,s);
    display_puts(s);
    display_puts("\n");
    return;
  }

  for(;;)
  {
    r=keyboard_getcode();
    if(r<0) {
      display_puts("kbd getcode=");
      int2dec(-r,s);
      display_puts(s);
      display_puts("\n");
      return;
    }
/*    display_puts("key=");
    byte2hex(r,s);
    display_puts(s);
*/
    s[0]=r;
    s[1]='1';
    s[2]=0;
    display_puts(s);
/*
    int2dec(r,s);
    display_puts(s);
    display_puts("1");
*/
  }

}
Пример #16
0
int cdfs_read_request(unsigned short seq,int handle,unsigned long pos,unsigned int shmname,unsigned long offset,unsigned long bufsize)
{
  int rc;
  union cdfs_msg msg;

  if(cdfs_queid==0) {
    rc=cdfs_init();
    if(rc<0)
      return rc;
  }

  msg.h.size=sizeof(struct cdfs_req_read);
  msg.h.service=CDFS_SRV_CDFS;
  msg.h.command=CDFS_CMD_READ;
  msg.h.arg=environment_getqueid();
  msg.read.req.seq=seq;
  msg.read.req.handle=handle;
  msg.read.req.pos=pos;
  msg.read.req.shmname=shmname;
  msg.read.req.offset=offset;
  msg.read.req.bufsize=bufsize;
/*
int2dec(msg.req.queid,s);
display_puts(s);
*/
  rc=message_send(cdfs_queid, &msg);
  if(rc<0) {	
    display_puts("cdfs_read sndcmd=");
    int2dec(-rc,s);
    display_puts(s);
    display_puts("\n");
    return rc;
  }

  return 0;
}
Пример #17
0
int cdfs_open_request(unsigned short seq,unsigned short devid,char *fullpath)
{
  int rc;
  union cdfs_msg msg;

  if(cdfs_queid==0) {
    rc=cdfs_init();
    if(rc<0)
      return rc;
  }

  msg.h.service=CDFS_SRV_CDFS;
  msg.h.command=CDFS_CMD_OPEN;
  msg.h.arg=environment_getqueid();
  msg.open.req.seq=seq;
  msg.open.req.devid=devid;
  strncpy(msg.open.req.fullpath,fullpath,CDFS_FULLPATH_MAXLENGTH);
  msg.open.req.fullpath[CDFS_FULLPATH_MAXLENGTH-1]=0;

  msg.h.size=(unsigned long)(&msg.open.req.fullpath[0])-(unsigned long)(&msg)+strlen(msg.open.req.fullpath)+1;

/*
int2dec(msg.req.queid,s);
display_puts(s);
*/
  rc=message_send(cdfs_queid, &msg);
  if(rc<0) {	
    display_puts("cdfs open sndcmd=");
    int2dec(-rc,s);
    display_puts(s);
    display_puts("\n");
    return rc;
  }

  return 0;
}
Пример #18
0
int tst_bucket()
{
  int fd;
  char s[16];
  int rc;
  char *buffer;
  int j;
  fd_set fdset;
  int fdsize=0;

  rc=fd=bucket_open();
  if(rc<0) {
    display_puts("open error=");
    int2dec(-rc,s);
    display_puts(s);
    display_puts("\n");
    return 1;
  }

  rc=bucket_connect(fd, BKT_QNM_BUCKET, BKT_SRV_BUCKET);
  if(rc<0) {
    display_puts("connect error=");
    int2dec(-rc,s);
    display_puts(s);
    display_puts("\n");
    return 1;
  }


  buffer=malloc(4096);
  memcpy(buffer,"ABC",3);
  rc=bucket_send(fd, buffer, 3);
  if(rc<0) {
    display_puts("send error=");
    int2dec(-rc,s);
    display_puts(s);
    display_puts("\n");
    return 1;
  }
  memcpy(buffer,"DEF",3);
  rc=bucket_send(fd, buffer, 3);
  if(rc<0) {
    display_puts("send error=");
    int2dec(-rc,s);
    display_puts(s);
    display_puts("\n");
    return 1;
  }

//  rc=bucket_shutdown(fd);
//  if(rc<0) {
//    display_puts("shutdown error=");
//    int2dec(-rc,s);
//    display_puts(s);
//    display_puts("\n");
//    return 1;
//  }

  rc=bucket_shutdown(fd);

  j=0;
  while(j<5) {
    display_puts("receiving(client)...");
    fdsize=max(fdsize,fd);
    FD_ZERO(&fdset);
    FD_SET(fd,&fdset);
    rc=bucket_select(fdsize+1,&fdset, 0);
    if(rc<0) {
      display_puts("select error=");
      int2dec(-rc,s);
      display_puts(s);
      display_puts("\n");
      return 1;
    }
    display_puts("\n");

    rc=bucket_recv(fd, buffer, 6);
    if(rc<0) {
      display_puts("recv error=");
      int2dec(-rc,s);
      display_puts(s);
      display_puts("\n");
      return 1;
    }
    display_puts("received(client) bucket:");
    int2dec(rc,s);
    display_puts(s);
    display_puts("byte.(");
    buffer[rc]=0;
    display_puts(buffer);
    display_puts(")\n");

    if(rc==0)
      break;

syscall_wait(100);
    j++;
  }

  rc=bucket_close(fd);
  display_puts("done(client)\n");

  return 0;
}
Пример #19
0
void DiscreteLogarithm(void)
{
  BigInteger groupOrder, subGroupOrder, powSubGroupOrder, powSubGroupOrderBak;
  BigInteger Exponent, runningExp, baseExp, mod;
  BigInteger logar, logarMult, runningExpBase;
  BigInteger currentExp;
  int indexBase, indexExp;
  int index, expon;
  limb addA, addB, addA2, addB2;
  limb mult1, mult2;
  double magnitude, firstLimit, secondLimit;
  long long brentK, brentR;
  unsigned char EndPollardBrentRho;
  int nbrLimbs;
  struct sFactors *pstFactors;
  enum eLogMachineState logMachineState;
  char *ptr;

#ifdef __EMSCRIPTEN__
  lModularMult = 0;
#endif
  NumberLength = modulus.nbrLimbs;
  if (!TestBigNbrEqual(&LastModulus, &modulus))
  {
    CompressBigInteger(nbrToFactor, &modulus);
    Bin2Dec(modulus.limbs, tofactorDec, modulus.nbrLimbs, groupLen);
    factor(&modulus, nbrToFactor, factorsMod, astFactorsMod, NULL);
    NbrFactorsMod = astFactorsMod[0].multiplicity;
  }
  intToBigInteger(&DiscreteLog, 0);       // DiscreteLog <- 0
  intToBigInteger(&DiscreteLogPeriod, 1); // DiscreteLogPeriod <- 1
  for (index = 1; index <= NbrFactorsMod; index++)
  {
    int mostSignificantDword, leastSignificantDword;
    int NbrFactors;
    int *ptrPrime;
    int multiplicity;

    ptrPrime = astFactorsMod[index].ptrFactor;
    NumberLength = *ptrPrime;
    UncompressBigInteger(ptrPrime, &groupOrder);
    groupOrder.sign = SIGN_POSITIVE;
    BigIntRemainder(&base, &groupOrder, &tmpBase);
    if (tmpBase.nbrLimbs == 1 && tmpBase.limbs[0].x == 0)
    {     // modulus and base are not relatively prime.
      int ctr;
      multiplicity = astFactorsMod[index].multiplicity;
      CopyBigInt(&bigNbrA, &power);
      for (ctr = multiplicity; ctr > 0; ctr--)
      {
        BigIntRemainder(&bigNbrA, &groupOrder, &bigNbrB);
        if (bigNbrB.nbrLimbs != 1 || bigNbrB.limbs[0].x != 0)
        {    // Exit loop if integer division cannot be performed
          break;
        }
        BigIntDivide(&bigNbrA, &groupOrder, &bigNbrB);
        CopyBigInt(&bigNbrA, &bigNbrB);
      }
      if (ctr == 0)
      {  // Power is multiple of prime^exp.
        continue;
      }
      // Compute prime^mutliplicity.
      BigIntPowerIntExp(&groupOrder, multiplicity, &tmp2);
      BigIntRemainder(&base, &tmp2, &tmpBase);
      // Get tentative exponent.
      ctr = multiplicity - ctr;
      intToBigInteger(&bigNbrB, ctr);   // Convert exponent to big integer.
      NumberLength = tmp2.nbrLimbs;
      memcpy(TestNbr, tmp2.limbs, (NumberLength + 1) * sizeof(limb));
      GetMontgomeryParms(NumberLength);
      BigIntModularPower(&tmpBase, &bigNbrB, &bigNbrA);
      BigIntRemainder(&power, &tmp2, &bigNbrB);
      BigIntSubt(&bigNbrA, &bigNbrB, &bigNbrA);
      if (bigNbrA.nbrLimbs == 1 && bigNbrA.limbs[0].x == 0)
      {
        intToBigInteger(&DiscreteLog, ctr);     // DiscreteLog <- exponent
        intToBigInteger(&DiscreteLogPeriod, 0); // DiscreteLogPeriod <- 0
        break;
      }
      showText("There is no discrete logarithm");
      DiscreteLogPeriod.sign = SIGN_NEGATIVE;
      return;
    }
    else
    {     // modulus and base are relatively prime.
      BigIntRemainder(&power, &groupOrder, &bigNbrB);
      if (bigNbrB.nbrLimbs == 1 && bigNbrB.limbs[0].x == 0)
      {   // power is multiple of prime. Error.
        showText("There is no discrete logarithm");
        DiscreteLogPeriod.sign = SIGN_NEGATIVE;
        return;
      }
    }
    CompressLimbsBigInteger(baseMontg, &tmpBase);
    BigIntRemainder(&power, &groupOrder, &tmpBase);
    CompressLimbsBigInteger(powerMontg, &tmpBase);
    // Compute group order as the prime minus 1.
    groupOrder.limbs[0].x--;
    showText("Computing discrete logarithm...");
    CompressBigInteger(nbrToFactor, &groupOrder);
    factor(&groupOrder, nbrToFactor, factorsGO, astFactorsGO, NULL);  // factor groupOrder.
    NbrFactors = astFactorsGO[0].multiplicity;
    NumberLength = *ptrPrime;
    UncompressBigInteger(ptrPrime, &mod);
    intToBigInteger(&logar, 0);     // logar <- 0
    intToBigInteger(&logarMult, 1); // logarMult <- 1
    NumberLength = mod.nbrLimbs;
    memcpy(TestNbr, mod.limbs, NumberLength * sizeof(limb));
    TestNbr[NumberLength].x = 0;
    //    yieldFreq = 1000000 / (NumberLength*NumberLength);
    GetMontgomeryParms(NumberLength);
#if 0
    char *ptrText = textExp;
    strcpy(ptrText, "<p>NumberLength (2) = ");
    ptrText = ptrText + strlen(ptrText);
    int2dec(&ptrText, NumberLength);
    strcpy(ptrText, "</p>");
    DiscreteLogPeriod.sign = SIGN_NEGATIVE;
    return;
#endif
    // Convert base and power to Montgomery notation.
    modmult(baseMontg, MontgomeryMultR2, baseMontg);
    modmult(powerMontg, MontgomeryMultR2, powerMontg);
    mostSignificantDword = NumberLength - 1;
    if (NumberLength == 1)
    {
      leastSignificantDword = NumberLength - 1;
      firstLimit = (double)TestNbr[leastSignificantDword].x / 3;
    }
    else
    {
      leastSignificantDword = NumberLength - 2;
      firstLimit = ((double)TestNbr[mostSignificantDword].x * LIMB_RANGE +
        TestNbr[leastSignificantDword].x) / 3;
    }
    secondLimit = firstLimit * 2;
    for (indexBase = 0; indexBase < NbrFactors; indexBase++)
    {
      NumberLength = *astFactorsGO[indexBase + 1].ptrFactor;
      UncompressBigInteger(astFactorsGO[indexBase + 1].ptrFactor, &subGroupOrder);
      subGroupOrder.sign = SIGN_POSITIVE;
      strcpy(textExp, "Computing discrete logarithm in subgroup of ");
      Bin2Dec(subGroupOrder.limbs, textExp + strlen(textExp), subGroupOrder.nbrLimbs, groupLen);
      ptr = textExp + strlen(textExp);
      if (astFactorsGO[indexBase + 1].multiplicity > 1)
      {
        *ptr++ = '<';
        *ptr++ = 's';
        *ptr++ = 'u';
        *ptr++ = 'p';
        *ptr++ = '>';
        int2dec(&ptr, astFactorsGO[indexBase + 1].multiplicity);
        *ptr++ = '<';
        *ptr++ = '/';
        *ptr++ = 's';
        *ptr++ = 'u';
        *ptr++ = 'p';
        *ptr++ = '>';
      }
      strcpy(ptr, " elements.");
      showText(textExp);
      NumberLength = mod.nbrLimbs;
      memcpy(TestNbr, mod.limbs, NumberLength * sizeof(limb));
      NumberLengthOther = subGroupOrder.nbrLimbs;
      memcpy(TestNbrOther, subGroupOrder.limbs, NumberLengthOther * sizeof(limb));
      TestNbr[NumberLength].x = 0;
      GetMontgomeryParms(NumberLength);
      nbrLimbs = subGroupOrder.nbrLimbs;
      dN = (double)subGroupOrder.limbs[nbrLimbs - 1].x;
      if (nbrLimbs > 1)
      {
        dN += (double)subGroupOrder.limbs[nbrLimbs - 2].x / LIMB_RANGE;
        if (nbrLimbs > 2)
        {
          dN += (double)subGroupOrder.limbs[nbrLimbs - 3].x / LIMB_RANGE / LIMB_RANGE;
        }
      }
      CopyBigInt(&baseExp, &groupOrder);
      // Check whether base is primitive root.
      BigIntDivide(&groupOrder, &subGroupOrder, &tmpBase);
      modPow(baseMontg, tmpBase.limbs, tmpBase.nbrLimbs, primRootPwr);
      if (!memcmp(primRootPwr, MontgomeryMultR1, NumberLength * sizeof(limb)))
      {        // Power is one, so it is not a primitive root.
        logMachineState = CALC_LOG_BASE;
        // Find primitive root
        primRoot[0].x = 1;
        if (NumberLength > 1)
        {
          memset(&primRoot[1], 0, (NumberLength - 1) * sizeof(limb));
        }
        do
        {
          primRoot[0].x++;
          modPow(primRoot, tmpBase.limbs, tmpBase.nbrLimbs, primRootPwr);
        } while (!memcmp(primRootPwr, MontgomeryMultR1, NumberLength * sizeof(limb)));
      }
      else
      {           // Power is not 1, so the base is a primitive root.
        logMachineState = BASE_PRIMITIVE_ROOT;
        memcpy(primRoot, baseMontg, NumberLength * sizeof(limb));
      }
      for (;;)
      {                  // Calculate discrete logarithm in subgroup.
        runningExp.nbrLimbs = 1;     // runningExp <- 0
        runningExp.limbs[0].x = 0;
        runningExp.sign = SIGN_POSITIVE;
        powSubGroupOrder.nbrLimbs = 1;     // powSubGroupOrder <- 1
        powSubGroupOrder.limbs[0].x = 1;
        powSubGroupOrder.sign = SIGN_POSITIVE;
        CopyBigInt(&currentExp, &groupOrder);
        if (logMachineState == BASE_PRIMITIVE_ROOT)
        {
          memcpy(basePHMontg, baseMontg, NumberLength * sizeof(limb));
          memcpy(currPowerMontg, powerMontg, NumberLength * sizeof(limb));
        }
        else if (logMachineState == CALC_LOG_BASE)
        {
          memcpy(basePHMontg, primRoot, NumberLength * sizeof(limb));
          memcpy(currPowerMontg, baseMontg, NumberLength * sizeof(limb));
        }
        else
        {           // logMachineState == CALC_LOG_POWER
          memcpy(primRoot, basePHMontg, NumberLength * sizeof(limb));
          memcpy(currPowerMontg, powerMontg, NumberLength * sizeof(limb));
        }
        for (indexExp = 0; indexExp < astFactorsGO[indexBase + 1].multiplicity; indexExp++)
        {
          /* PH below comes from Pohlig-Hellman algorithm */
          BigIntDivide(&currentExp, &subGroupOrder, &currentExp);
          modPow(currPowerMontg, currentExp.limbs, currentExp.nbrLimbs, powerPHMontg);
          BigIntDivide(&baseExp, &subGroupOrder, &baseExp);
          if (subGroupOrder.nbrLimbs == 1 && subGroupOrder.limbs[0].x < 20)
          {       // subGroupOrder less than 20.
            if (!ComputeDLogModSubGroupOrder(indexBase, indexExp, &Exponent, &subGroupOrder))
            {
              return;
            }
          }
          else
          {        // Use Pollard's rho method with Brent's modification
            memcpy(nbrPower, powerPHMontg, NumberLength * sizeof(limb));
            memcpy(nbrBase, primRootPwr, NumberLength * sizeof(limb));
            memcpy(nbrR2, nbrBase, NumberLength * sizeof(limb));
            memset(nbrA2, 0, NumberLength * sizeof(limb));
            memset(nbrB2, 0, NumberLength * sizeof(limb));
            nbrB2[0].x = 1;
            addA2.x = addB2.x = 0;
            mult2.x = 1;
            brentR = 1;
            brentK = 0;
            EndPollardBrentRho = FALSE;
            do
            {
              memcpy(nbrR, nbrR2, NumberLength * sizeof(limb));
              memcpy(nbrA, nbrA2, NumberLength * sizeof(limb));
              memcpy(nbrB, nbrB2, NumberLength * sizeof(limb));
              addA = addA2;
              addB = addB2;
              mult1 = mult2;
              brentR *= 2;
              do
              {
                brentK++;
                if (NumberLength == 1)
                {
                  magnitude = (double)nbrR2[leastSignificantDword].x;
                }
                else
                {
                  magnitude = (double)nbrR2[mostSignificantDword].x * LIMB_RANGE +
                    nbrR2[leastSignificantDword].x;
                }
                if (magnitude < firstLimit)
                {
                  modmult(nbrR2, nbrPower, nbrROther);
                  addA2.x++;
                }
                else if (magnitude < secondLimit)
                {
                  modmult(nbrR2, nbrR2, nbrROther);
                  mult2.x *= 2;
                  addA2.x *= 2;
                  addB2.x *= 2;
                }
                else
                {
                  modmult(nbrR2, nbrBase, nbrROther);
                  addB2.x++;
                }
                // Exchange nbrR2 and nbrROther
                memcpy(nbrTemp, nbrR2, NumberLength * sizeof(limb));
                memcpy(nbrR2, nbrROther, NumberLength * sizeof(limb));
                memcpy(nbrROther, nbrTemp, NumberLength * sizeof(limb));
                if (addA2.x >= (int)(LIMB_RANGE / 2) || addB2.x >= (int)(LIMB_RANGE / 2) ||
                    mult2.x >= (int)(LIMB_RANGE / 2))
                {
                  // nbrA2 <- (nbrA2 * mult2 + addA2) % subGroupOrder
                  AdjustExponent(nbrA2, mult2, addA2, &subGroupOrder);
                  // nbrB2 <- (nbrB2 * mult2 + addB2) % subGroupOrder
                  AdjustExponent(nbrB2, mult2, addB2, &subGroupOrder);
                  mult2.x = 1;
                  addA2.x = addB2.x = 0;
                }
                if (!memcmp(nbrR, nbrR2, NumberLength * sizeof(limb)))
                {
                  EndPollardBrentRho = TRUE;
                  break;
                }
              } while (brentK < brentR);
            } while (EndPollardBrentRho == FALSE);
            ExchangeMods();                  // TestNbr <- subGroupOrder
            // nbrA <- (nbrA * mult1 + addA) % subGroupOrder
            AdjustExponent(nbrA, mult1, addA, &subGroupOrder);
            // nbrB <- (nbrB * mult1 + addB) % subGroupOrder
            AdjustExponent(nbrB, mult1, addB, &subGroupOrder);
            // nbrA2 <- (nbrA * mult2 + addA2) % subGroupOrder
            AdjustExponent(nbrA2, mult2, addA2, &subGroupOrder);
            // nbrB2 <- (nbrA * mult2 + addB2) % subGroupOrder
            AdjustExponent(nbrB2, mult2, addB2, &subGroupOrder);
            // nbrB <- (nbrB2 - nbrB) % subGroupOrder
            SubtBigNbrMod(nbrB2, nbrB, nbrB);
            SubtBigNbrMod(nbrA, nbrA2, nbrA);
            if (BigNbrIsZero(nbrA))
            {     // Denominator is zero, so rho does not work.
              ExchangeMods();           // TestNbr <- modulus
              if (!ComputeDLogModSubGroupOrder(indexBase, indexExp, &Exponent, &subGroupOrder))
              {
                return;   // Cannot compute discrete logarithm.
              }
            }
            else
            {
              // Exponent <- (nbrB / nbrA) (mod subGroupOrder)
              UncompressLimbsBigInteger(nbrA, &bigNbrA);
              UncompressLimbsBigInteger(nbrB, &bigNbrB);
              BigIntModularDivisionSaveTestNbr(&bigNbrB, &bigNbrA, &subGroupOrder, &Exponent);
              Exponent.sign = SIGN_POSITIVE;
              ExchangeMods();           // TestNbr <- modulus
            }
          }
          modPow(primRoot, Exponent.limbs, Exponent.nbrLimbs, tmpBase.limbs);
          ModInvBigNbr(tmpBase.limbs, tmpBase.limbs, TestNbr, NumberLength);
          modmult(tmpBase.limbs, currPowerMontg, currPowerMontg);
          BigIntMultiply(&Exponent, &powSubGroupOrder, &tmpBase);
          BigIntAdd(&runningExp, &tmpBase, &runningExp);
          BigIntMultiply(&powSubGroupOrder, &subGroupOrder, &powSubGroupOrder);
          modPow(primRoot, subGroupOrder.limbs, subGroupOrder.nbrLimbs, tmpBase.limbs);
          memcpy(primRoot, tmpBase.limbs, NumberLength * sizeof(limb));
        }
        if (logMachineState == BASE_PRIMITIVE_ROOT)
        {         // Discrete logarithm was determined for this subgroup.
          ExponentsGOComputed[indexBase] = astFactorsGO[indexBase + 1].multiplicity;
          break;
        }
        if (logMachineState == CALC_LOG_BASE)
        {
          CopyBigInt(&runningExpBase, &runningExp);
          logMachineState = CALC_LOG_POWER;
        }
        else
        {  // Set powSubGroupOrderBak to powSubGroupOrder.
           // if runningExpBase is not multiple of subGroupOrder,
           // discrete logarithm is runningExp/runningExpBase mod powSubGroupOrderBak.
           // Otherwise if runningExp is multiple of subGroupOrder, there is no logarithm.
           // Otherwise, divide runningExp, runnignExpBase and powSubGroupOrderBak by subGroupOrder and repeat.
          ExponentsGOComputed[indexBase] = astFactorsGO[indexBase + 1].multiplicity;
          CopyBigInt(&powSubGroupOrderBak, &powSubGroupOrder);
          do
          {
            BigIntRemainder(&runningExpBase, &subGroupOrder, &tmpBase);
            if (tmpBase.nbrLimbs > 1 || tmpBase.limbs[0].x != 0)
            {    // runningExpBase is not multiple of subGroupOrder
              BigIntModularDivisionSaveTestNbr(&runningExp, &runningExpBase, &powSubGroupOrderBak, &tmpBase);
              CopyBigInt(&runningExp, &tmpBase);
              break;
            }
            BigIntRemainder(&runningExp, &subGroupOrder, &tmpBase);
            if (tmpBase.nbrLimbs > 1 || tmpBase.limbs[0].x != 0)
            {    // runningExpBase is not multiple of subGroupOrder
              showText("There is no discrete logarithm");
              DiscreteLogPeriod.sign = SIGN_NEGATIVE;
              return;
            }
            BigIntDivide(&runningExp, &subGroupOrder, &tmpBase);
            CopyBigInt(&runningExp, &tmpBase);
            BigIntDivide(&runningExpBase, &subGroupOrder, &tmpBase);
            CopyBigInt(&runningExpBase, &tmpBase);
            BigIntDivide(&powSubGroupOrderBak, &subGroupOrder, &tmpBase);
            CopyBigInt(&powSubGroupOrderBak, &tmpBase);
            ExponentsGOComputed[indexBase]--;
            if (tmpBase.nbrLimbs == 1 && tmpBase.limbs[0].x == 1)
            {
              break;
            }
            BigIntRemainder(&runningExpBase, &subGroupOrder, &tmpBase);
          } while (tmpBase.nbrLimbs == 1 && tmpBase.limbs[0].x == 0);
          CopyBigInt(&powSubGroupOrder, &powSubGroupOrderBak);
          // The logarithm is runningExp / runningExpBase mod powSubGroupOrder
          // When powSubGroupOrder is even, we cannot use Montgomery.
          if (powSubGroupOrder.limbs[0].x & 1)
          {          // powSubGroupOrder is odd.
            BigIntModularDivisionSaveTestNbr(&runningExp, &runningExpBase, &powSubGroupOrder, &tmpBase);
            CopyBigInt(&runningExp, &tmpBase);
          }
          else
          {          // powSubGroupOrder is even (power of 2).
            NumberLength = powSubGroupOrder.nbrLimbs;
            CompressLimbsBigInteger(nbrB, &runningExpBase);
            ComputeInversePower2(nbrB, nbrA, nbrB2);  // nbrB2 is auxiliary var.
            CompressLimbsBigInteger(nbrB, &runningExp);
            multiply(nbrA, nbrB, nbrA, NumberLength, NULL);   // nbrA <- quotient.
            UncompressLimbsBigInteger(nbrA, &runningExp);
          }
          break;
        }
      }
      CopyBigInt(&nbrV[indexBase], &runningExp);
      NumberLength = powSubGroupOrder.nbrLimbs;
      memcpy(TestNbr, powSubGroupOrder.limbs, NumberLength * sizeof(limb));
      TestNbr[NumberLength].x = 0;
      GetMontgomeryParms(NumberLength);
      for (indexExp = 0; indexExp < indexBase; indexExp++)
      {
        // nbrV[indexBase] <- (nbrV[indexBase] - nbrV[indexExp])*
        //                     modinv(PrimesGO[indexExp]^(ExponentsGO[indexExp]),
        //                     powSubGroupOrder)
        NumberLength = mod.nbrLimbs;
        BigIntSubt(&nbrV[indexBase], &nbrV[indexExp], &nbrV[indexBase]);
        BigIntRemainder(&nbrV[indexBase], &powSubGroupOrder, &nbrV[indexBase]);
        if (nbrV[indexBase].sign == SIGN_NEGATIVE)
        {
          BigIntAdd(&nbrV[indexBase], &powSubGroupOrder, &nbrV[indexBase]);
        }
        pstFactors = &astFactorsGO[indexExp + 1];
        UncompressBigInteger(pstFactors->ptrFactor, &tmpBase);
        BigIntPowerIntExp(&tmpBase, ExponentsGOComputed[indexExp], &tmpBase);
        BigIntRemainder(&tmpBase, &powSubGroupOrder, &tmpBase);
        NumberLength = powSubGroupOrder.nbrLimbs;
        CompressLimbsBigInteger(tmp2.limbs, &tmpBase);
        modmult(tmp2.limbs, MontgomeryMultR2, tmp2.limbs);
        if (NumberLength > 1 || TestNbr[0].x != 1)
        {           // If TestNbr != 1 ...
          ModInvBigNbr(tmp2.limbs, tmp2.limbs, TestNbr, NumberLength);
        }
        tmpBase.limbs[0].x = 1;
        memset(&tmpBase.limbs[1], 0, (NumberLength - 1) * sizeof(limb));
        modmult(tmpBase.limbs, tmp2.limbs, tmp2.limbs);
        UncompressLimbsBigInteger(tmp2.limbs, &tmpBase);
        BigIntMultiply(&tmpBase, &nbrV[indexBase], &nbrV[indexBase]);
      }
      BigIntRemainder(&nbrV[indexBase], &powSubGroupOrder, &nbrV[indexBase]);
      BigIntMultiply(&nbrV[indexBase], &logarMult, &tmpBase);
      BigIntAdd(&logar, &tmpBase, &logar);
      BigIntMultiply(&logarMult, &powSubGroupOrder, &logarMult);
    }
    multiplicity = astFactorsMod[index].multiplicity;
    UncompressBigInteger(ptrPrime, &bigNbrB);
    expon = 1;
    if (bigNbrB.nbrLimbs == 1 && bigNbrB.limbs[0].x == 2)
    {            // Prime factor is 2. Base and power are odd at this moment.
      int lsbBase = base.limbs[0].x;
      int lsbPower = power.limbs[0].x;
      if (multiplicity > 1)
      {
        int mask = (multiplicity == 2? 3 : 7);
        expon = (multiplicity == 2 ? 2 : 3);
        if ((lsbPower & mask) == 1)
        {
          intToBigInteger(&logar, 0);
          intToBigInteger(&logarMult, (lsbBase == 1 ? 1 : 2));
        }
        else if (((lsbPower - lsbBase) & mask) == 0)
        {
          intToBigInteger(&logar, 1);
          intToBigInteger(&logarMult, 2);
        }
        else
        {
          showText("There is no discrete logarithm");
          DiscreteLogPeriod.sign = SIGN_NEGATIVE;
          return;
        }
      }
    }
    for (; expon < multiplicity; expon++)
    {    // Repeated factor.
      // L = logar, LM = logarMult
      // B = base, P = power, p = prime

      // B^n = P (mod p^(k+1)) -> n = L + m*LM   m = ?
      // B^(L + m*LM) = P
      // (B^LM) ^ m = P*B^(-L)
      // B^LM = r*p^k + 1, P*B^(-L) = s*p^k + 1
      // (r*p^k + 1)^m = s*p^k + 1
      // From binomial theorem: m = s / r (mod p)
      // If r = 0 and s != 0 there is no solution.
      // If r = 0 and s = 0 do not change LM.
      BigIntPowerIntExp(&bigNbrB, expon + 1, &bigNbrA);
      NumberLength = bigNbrA.nbrLimbs;
      memcpy(TestNbr, bigNbrA.limbs, NumberLength * sizeof(limb));
      GetMontgomeryParms(NumberLength);
      BigIntRemainder(&base, &bigNbrA, &tmpBase);
      CompressLimbsBigInteger(baseMontg, &tmpBase);
      modmult(baseMontg, MontgomeryMultR2, baseMontg);
      modPow(baseMontg, logarMult.limbs, logarMult.nbrLimbs, primRootPwr); // B^LM
      tmpBase.limbs[0].x = 1;   // Convert from Montgomery to standard notation.
      memset(&tmpBase.limbs[1], 0, (NumberLength - 1) * sizeof(limb));
      modmult(primRootPwr, tmpBase.limbs, primRootPwr);                    // B^LM
      ModInvBigNbr(baseMontg, tmpBase.limbs, TestNbr, NumberLength);       // B^(-1)
      modPow(tmpBase.limbs, logar.limbs, logar.nbrLimbs, primRoot);        // B^(-L)
      BigIntRemainder(&power, &bigNbrA, &tmpBase);
      CompressLimbsBigInteger(tmp2.limbs, &tmpBase);
      modmult(primRoot, tmp2.limbs, primRoot);                             // P*B^(-L)
      BigIntDivide(&bigNbrA, &bigNbrB, &tmpBase);
      UncompressLimbsBigInteger(primRootPwr, &tmp2);
      BigIntDivide(&tmp2, &tmpBase, &bigNbrA);                             // s
      UncompressLimbsBigInteger(primRoot, &baseModGO);   // Use baseMontGO as temp var.
      BigIntDivide(&baseModGO, &tmpBase, &tmp2);                           // r
      if (bigNbrA.nbrLimbs == 1 && bigNbrA.limbs[0].x == 0)
      {            // r equals zero.
        if (tmp2.nbrLimbs != 1 || tmp2.limbs[0].x != 0)
        {          // s does not equal zero.
          showText("There is no discrete logarithm");
          DiscreteLogPeriod.sign = SIGN_NEGATIVE;
          return;
        }
      }
      else
      {            // r does not equal zero.
        BigIntModularDivisionSaveTestNbr(&tmp2, &bigNbrA, &bigNbrB, &tmpBase);          // m
        BigIntMultiply(&tmpBase, &logarMult, &tmp2);
        BigIntAdd(&logar, &tmp2, &logar);
        BigIntMultiply(&logarMult, &bigNbrB, &logarMult);
      }
    }
    // Based on logar and logarMult, compute DiscreteLog and DiscreteLogPeriod
    // using the following formulas, that can be deduced from the Chinese
    // Remainder Theorem:
    // L = logar, LM = logarMult, DL = DiscreteLog, DLP = DiscreteLogPeriod.
    // The modular implementation does not allow operating with even moduli.
    //
    // g <- gcd(LM, DLP)
    // if (L%g != DL%g) there is no discrete logarithm, so go out.
    // h <- LM / g
    // if h is odd:
    //   t <- (L - DL) / DLP (mod h)
    //   t <- DLP * t + DL
    // else
    //   i <- DLP / g
    //   t <- (DL - L) / LM (mod i)
    //   t <- LM * t + L
    // endif
    //   DLP <- DLP * h
    //   DL <- t % DLP

    BigIntGcd(&logarMult, &DiscreteLogPeriod, &tmpBase);
    BigIntRemainder(&logar, &tmpBase, &bigNbrA);
    BigIntRemainder(&DiscreteLog, &tmpBase, &bigNbrB);
    if (!TestBigNbrEqual(&bigNbrA, &bigNbrB))
    {
      showText("There is no discrete logarithm");
      DiscreteLogPeriod.sign = SIGN_NEGATIVE;
      return;
    }
    BigIntDivide(&logarMult, &tmpBase, &tmp2);
    if (tmp2.limbs[0].x & 1)
    {     // h is odd.
      BigIntSubt(&logar, &DiscreteLog, &tmpBase);
      BigIntModularDivisionSaveTestNbr(&tmpBase, &DiscreteLogPeriod, &tmp2, &bigNbrA);
      BigIntMultiply(&DiscreteLogPeriod, &bigNbrA, &tmpBase);
      BigIntAdd(&tmpBase, &DiscreteLog, &tmpBase);
    }
    else
    {     // h is even.
      BigIntDivide(&DiscreteLogPeriod, &tmpBase, &bigNbrB);
      BigIntSubt(&DiscreteLog, &logar, &tmpBase);
      BigIntModularDivisionSaveTestNbr(&tmpBase, &logarMult, &bigNbrB, &bigNbrA);
      BigIntMultiply(&logarMult, &bigNbrA, &tmpBase);
      BigIntAdd(&tmpBase, &logar, &tmpBase);
    }
    BigIntMultiply(&DiscreteLogPeriod, &tmp2, &DiscreteLogPeriod);
    BigIntRemainder(&tmpBase, &DiscreteLogPeriod, &DiscreteLog);
  }
#if 0
  textExp.setText(DiscreteLog.toString());
  textPeriod.setText(DiscreteLogPeriod.toString());
  long t = OldTimeElapsed / 1000;
  labelStatus.setText("Time elapsed: " +
    t / 86400 + "d " + (t % 86400) / 3600 + "h " + ((t % 3600) / 60) + "m " + (t % 60) +
    "s    mod mult: " + lModularMult);
#endif
}
Пример #20
0
int display_puts(char *chr)
{
  union display_msg msg;
  short len;
  int r;

  if(display_queid==0) {
    r=display_init();
    if(r<0)
      return r;
  }
/*
if(display_queid<100) {
  syscall_puts(" qid=");
  int2dec(display_queid,s);
  syscall_puts(s);
  syscall_puts("\n");
 }
*/
  len=strlen(chr);
  if(len>=DISPLAY_STRLEN-1)
    len=DISPLAY_STRLEN-1;

//  msg.h.size=msg_size(sizeof(struct msg_head)+len+1);
  msg.h.size=sizeof(struct msg_head)+len+1;
  msg.h.service=DISPLAY_SRV_DISPLAY;
  msg.h.command=DISPLAY_CMD_PUTS;
  msg.h.arg=len;
  strncpy(msg.s.s, chr, DISPLAY_STRLEN);
/*
{
char *ms=(char *)&msg;
syscall_puts("sz=");
int2dec(msg.h.size,s);
syscall_puts(s);
syscall_puts("arg=");
int2dec(msg.h.arg,s);
syscall_puts(s);
syscall_puts("str=");
byte2hex(ms[8],&s[0]);
byte2hex(ms[9],&s[2]);
syscall_puts(s);
}
*/
  for(;;) {
    r=message_send(display_queid, &msg);
    if(r!=ERRNO_OVER)
      break;
    syscall_wait(10);
  }
  if(r<0) {
    syscall_puts("puts sndcmd=");
    int2dec(-r,s);
    syscall_puts(s);
    syscall_puts(" qid=");
    int2dec(display_queid,s);
    syscall_puts(s);
    syscall_puts(" str=");
    syscall_puts(chr);
    syscall_puts("\n");

    return r;
  }

  return 0;
}
Пример #21
0
  // Convert little-endian number to a string with space every groupLen digits.
  // In order to perform a faster conversion, use groups of DIGITS_PER_LIMB digits.
void Bin2Dec(limb *binary, char *decimal, int nbrLimbs, int groupLength)
{
  int len, index, index2, count;
  limb *ptrSrc = binary + nbrLimbs - 1;
  char *ptrDest;
  int significantZero = 0;
  int groupCtr;
  int digit[DIGITS_PER_LIMB];
  int digits=0;
  int showDigitsText = TRUE;

  if (groupLength <= 0)
  {
    groupLength = -groupLength;
    showDigitsText = FALSE;
  }
  power10000[0].x = ptrSrc->x % MAX_LIMB_CONVERSION;
  power10000[1].x = ptrSrc->x / MAX_LIMB_CONVERSION;
  len = (power10000[1].x == 0 ? 1 : 2); // Initialize array length.
  for (index = nbrLimbs - 2; index >= 0; index--)
  {
    double dCarry, dQuotient;
    limb *ptrPower;

    // Multiply by FIRST_MULT and then by SECOND_MULT, so there is never
    // more than 53 bits in the product.

    ptrPower = power10000;
    dQuotient = 0;
    for (index2 = 0; index2 < len; index2++)
    {
      dCarry = dQuotient + (double)ptrPower->x * FIRST_MULT;
      dQuotient = floor(dCarry / MAX_LIMB_CONVERSION);
      (ptrPower++)->x = (int)(dCarry - dQuotient * MAX_LIMB_CONVERSION);
    }
    if (dQuotient != 0)
    {
      (ptrPower++)->x = (int)dQuotient;
      len++;
    }
    ptrPower = power10000;
    dQuotient = (--ptrSrc)->x;
    for (index2 = 0; index2 < len; index2++)
    {
      dCarry = dQuotient + (double)ptrPower->x * SECOND_MULT;
      dQuotient = floor(dCarry / MAX_LIMB_CONVERSION);
      (ptrPower++)->x = (int)(dCarry - dQuotient * MAX_LIMB_CONVERSION);
    }
    if (dQuotient != 0)
    {
      (ptrPower++)->x = (int)dQuotient;
      len++;
    }
  }
  // At this moment the array power10000 has the representation
  // of the number in base 10000 in little-endian. Convert to
  // ASCII separating every groupLength characters.
  ptrDest = decimal;
  ptrSrc = &power10000[len-1];
  groupCtr = len * DIGITS_PER_LIMB;
  if (groupLength != 0)
  {
    groupCtr %= groupLength;
    if (groupCtr == 0)
    {
      groupCtr = groupLength;
    }
  }
  for (index = len; index > 0; index--)
  {
    int value = (int)(ptrSrc--)->x;
    for (count = 0; count < DIGITS_PER_LIMB; count++)
    {
      digit[count] = value % 10;
      value /= 10;
    }
    for (count = DIGITS_PER_LIMB-1; count >= 0; count--)
    {
      if (digit[count] != 0 || significantZero != 0)
      {
        digits++;
        *ptrDest++ = (char)(digit[count] + (int)'0');
        if (groupCtr == 1)
        {
          *ptrDest++ = ' ';
        }
        significantZero = 1;
      }
      if (--groupCtr == 0)
      {
        groupCtr = groupLength;
      }
    }
  }
  if (significantZero == 0)
  {     // Number is zero.
    *ptrDest++ = '0';
    *ptrDest = '\0';
    return;
  }
  if (digits > 30 && showDigitsText)
  {
    *ptrDest++ = '(';
    int2dec(&ptrDest, digits);
    strcpy(ptrDest, (lang==0?" digits)":" dígitos)"));
    ptrDest += strlen(ptrDest);
  }
  else if (ptrDest > decimal)
  {
    *(ptrDest-1) = '\0';       // Add terminator.
  }
}