#define __USE_SYSBASE
#include "carac.h"
#include <proto/dos.h>
#include <proto/exec.h>
#include <exec/execbase.h>
#include <exec/memory.h>
#include <proto/mathieeesingtrans.h>
#include <proto/mathieeesingbas.h>
#include <string.h>

#define MEM MEMF_PUBLIC|MEMF_CLEAR
#define TEMPLATE "NUMBER/N,DISPLAY/S,TEST/S"
#define TXT GRAS"\n   YAYASieve 1.3"NORM"\n\n   © Allenbrand Brice 1997\n\n   Ringard'Production\n\n\0$VER: YAYASieve 1.3 ** "__DATE__

void Test(unsigned int i);
void Go(unsigned int i,unsigned int k,unsigned char *s);

struct DosLibrary *DOSBase;
struct Library *MathIeeeSingTransBase;
struct Library *MathIeeeSingBasBase;
struct ExecBase *SysBase;

__saveds int main(void)
{
 struct RDArgs *rdargs;
 int opts[]={0,0,0};
 unsigned int i,j,k;
 unsigned char *s;
 struct DateStamp ds1,ds2;

 SysBase=(*(struct ExecBase **)4);
 if(DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",37))
 {
  if(MathIeeeSingTransBase=(struct Library *)OpenLibrary("mathieeesingtrans.library",0))
  {
   if(MathIeeeSingBasBase=(struct Library *)OpenLibrary("mathieeesingbas.library",0))
   {
    if(rdargs=ReadArgs(TEMPLATE,(long *)opts,NULL))
    {
     if(opts[0])
     {
      i=*((unsigned int *)(opts[0]));
      if(i<10)
       i=10;
      if(opts[2])
       Test(i);
      else
      {
       k=IEEESPFix(IEEESPAdd(IEEESPSqrt(IEEESPFlt(i)),(float)0.5));
       i++;
       i>>=1;
       k++;
       k>>=1;
       if(s=(unsigned char *)AllocVec(((i>>5)+20)<<2,MEM))
       {
        Forbid();
        DateStamp(&ds1);
        Go(i,k,s);
        DateStamp(&ds2);
        Permit();
        Printf("Done\n");
        k=0;
        for(j=i;j;j--)
         if(!((s[j>>3])&(1<<(j&7))))
          k++;
        Printf("%ld primes found\n",k);
        if(opts[1])
        {
         k=0;
         Printf(" %9ld",2);
         for(j=2;j<=i;j++)
          if(!((s[j>>3])&(1<<(j&7))))
          {
           k++;
           if(!(k%7))
            Printf("\n");
           Printf(" %9ld",j+j-1);
          }
        }
        j=(ds2.ds_Minute-ds1.ds_Minute)*3000+(ds2.ds_Tick-ds1.ds_Tick);
        Printf("\n(%ld s %ld ticks)\n\n",j/50,j%50);
        FreeVec(s);
       }
      }
     }
     else
      Printf(TXT);
     FreeArgs(rdargs);
    }
    CloseLibrary(MathIeeeSingBasBase);
   }
   CloseLibrary(MathIeeeSingTransBase);
  }
  CloseLibrary((struct Library *)DOSBase);
 }
 return(0);
}

void Go(unsigned int i,unsigned int k,unsigned char *s)
{
 unsigned int j=4,a,b=7,l=25;
 unsigned char buf[]={105,150,52,75,154,37,205,146,102,73,179,164,89,210,44};

 *s=32;
 repmem(s+1,&buf[0],15,i/120+1);

 for(;j<=k;b+=2,l+=(j<<2),j++)
  if(!(s[j>>3]&(1<<(j&7))))
   for(a=l;a<=i;a+=b)
    s[a>>3]|=(1<<(a&7));
}

void Test(unsigned int i)
{
 unsigned int j,k;
 unsigned int *e,*p,pp=1;

 if(e=AllocVec(16*8,MEM))
 {
  p=e+16*4;
  Printf("\n%ld=",i);
  k=IEEESPFix(IEEESPSqrt(IEEESPFlt(i)))+1;
  for(j=2;j<=k;j++)
   for(;;)
   {
    if(i%j)
     break;
    i/=j;
    if(e[pp]==j)
     p[pp]++;
    else
    {
     if(e[pp])
      pp++;
     e[pp]=j;
     p[pp]=1;
    }
   }
  if(i!=1)
   if(e[pp]==i)
    p[pp]++;
   else
   {
    if(e[pp])
     pp++;
    e[pp]=i;
    p[pp]=1;
   }
  for(;pp;pp--)
   if(p[pp]!=1)
    Printf("%ld^%ld*",e[pp],p[pp]);
   else
    Printf("%ld*",e[pp]);
  Printf("\b \n\n");
  FreeVec(e);
 }
}
