Ayala 发表于 2016-7-28 23:38:46

大数乘法c源码 -fft

本帖最后由 Ayala 于 2016-7-28 23:39 编辑

用c写代码对我来说好痛苦!


double sin(double x);
double cos(double x);

double acos(double x);
double fmod(double x,double y);
double fabs(double x);
double floor(double x);
double ceil(double x);



typedef struct
{
        double real;
        double img;
}complex;

#ifdef cp
#undef cp
typedef complex cp;
#else
typedef complex cp;
#endif

#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif

#define N 1<<16


__int64 a;
__int64 b;
__int64 c;
double cc;
double PI;

const int LEN = 2, MOD = 100;
const double MODf = 100.0;


#ifdef x86_xp
#ifndef _ftol2

__int64 _ftol2(double x)
{
__int16 e,ee;
__int64 r;
__asm
{
    fld qword ptr x
   
    fstsw word ptr
    mov ax,word ptr
    or ah,0xc
    mov word ptr ,ax
   
    fldcw word ptr
    fistp qword ptr
    fldcw word ptr
   
    mov eax,dword ptr
    mov edx,dword ptr
}
}
#endif
#endif

void   add(complex   a,complex   b,complex   *c)      
{
//_fpreset();
        c->real        =a.real        +        b.real;      
        c->img        =a.img        +        b.img;      
}

void   sub(complex   a,complex   b,complex   *c)      
{
//_fpreset();
        c->real=a.real-b.real;      
        c->img=a.img-b.img;      
}

void   mul(complex   a,complex   b,complex   *c)      
{      
//_fpreset();
        c->real        =a.real*b.real-   a.img*b.img;      
        c->img        =a.real*b.img   +   a.img*b.real;      
}      


void   divi(complex   a,complex   b,complex   *c)      
{      
//_fpreset();
        c->real        =(a.real*b.real+a.img*b.img)/(b.real*b.real+b.img*b.img);      
        c->img        =(a.img*b.real-a.real*b.img)/(b.real*b.real+b.img*b.img);
}       

   
void bit_reverse_copy(cp a[], int n, cp b[])   
{   
    int i, j, k, u, m;   
    for (u = 1, m = 0; u < n; u <<= 1, ++m);   
    for (i = 0; i < n; ++i)   
    {   
      j = i; k = 0;   
      for (u = 0; u < m; ++u, j >>= 1)   
            k = (k << 1) | (j & 1);   
      b = a;   
      //printf("b[%d]=%.2lf+%.2lfi\n",k,b.real,b.img);
    }   
}



void FFT(cp _x[], int n, int flag)   
{   
    static cp x={0.0};   
    int i, j, k, kk, p, m;   
    double alpha;   
   
    cp wn,w,u,t,up,down;
    //_fpreset();
   
    bit_reverse_copy(_x, n, x);
   
    alpha = 2.0 * acos(-1.0);
    if (flag) alpha = -alpha;   
   
    for (i = 1, m = 0; i < n; i <<= 1, ++m);   
   
    for (i = 0, k = 2; i < m; ++i, k <<= 1)   
    {   
      wn.real = cos(alpha / k);
      wn.img= sin(alpha / k);
      for (j = 0; j < n; j += k)   
      {   
            w.real = 1.0;
            w.img= 0.0;
            kk = k >> 1;   
            for (p = 0; p < kk; ++p)   
            {      
                mul(w, x,&t);
                add(x,t,&up);
                sub(x,t,&down);
               
                x      = up;   
                x = down;   
               
                mul(w,wn,&u);
                w = u;   
            }   
      }   
    }   
    memcpy(_x, x, sizeof(cp) * n);   
}   


void polynomial_multiply(__int64 a[], int na, __int64 b[], int nb, __int64 c[], int *nc)   
{   
    static cp x, y,u;
    int i, n;
    //_fpreset();
    i = max(na, nb) << 1;   
    for (n = 1; n < i; n <<= 1);
   
    for (i = 0; i < na; ++i)
    {
      x.real = a;
      x.img= 0;
      //printf("x[%i]=%.2lf+%.2lfi\n",i,x.real,x.img);
    }
   
    for (; i < n; ++i)
    {
      x.real = 0;   
      x.img= 0;
    }
   
    FFT(x, n, 0);   
   
   
    for (i = 0; i < nb; ++i)
    {
      y.real = b;   
      y.img= 0;
      //printf("y[%i]=%.2lf+%.2lfi\n",i,y.real,y.img);
    }
   
    for (; i < n; ++i)
    {
      y.real = 0;   
      y.img= 0;
    }
   
    FFT(y, n, 0);   
   
    for (i = 0; i < n; ++i)
    {
      //printf("x[%i]=%.2lf+%.2lfi\n",i,x.real,x.img);
      //printf("y[%i]=%.2lf+%.2lfi\n",i,y.real,y.img);
      mul(x,y,&u);   
      //printf("u[%i]=%.2lf+%.2lfi\n",i,u.real,u.img);
    }
   
    FFT(u, n, 1);   
   
    for (i = 0; i < n; ++i)   
    {   
      //printf("c[%d] .lf = %.53lf\n",i,u.real / n + 0.5);
      c = _ftol2(u.real / n + 0.5);
      //printf("c[%d]I64d = %I64d\n",i,c);
    }   
    for (i = na + nb - 1; i > 1 && !c; --i);
    *nc = i;
}   


void convert(char *s, __int64 a[], int * n)   
{   
    int len = strlen(s), i, j, k,r;
    for (r = 0, i = len - LEN; i >= 0; i -= LEN)   
    {   
      for (j = k = 0; j < LEN; ++j)
      {
            k = k * 10 + (s - '0');   
      }
      a = k;   
      //printf("@207 k = %d\n",k);
    }   
    i += LEN;   
    if (i)   
    {   
      for (j = k = 0; j < i; ++j)
      {
            k = k * 10 + (s - '0');   
      }
      a = k;   
      //printf("@217 k = %d\n",k);
    }   
    *n=r;
    //printf("@220 r = %d\n",r);
}   
   
void print(__int64 a[], int n)   
{   
    printf("%I64d", a[--n]);   
    while (n) printf("%02I64d", a[--n]);   
    puts("");   
}   


char buf;   

#ifndef EOF
#define EOF (-1)
#endif

#ifndef false
#define false 0
#endif

#ifndef true
#define true 1
#endif


/*
void conc()
{

SetConsoleCP(936);
SetConsoleOutputCP(936);
SetConsoleMode(GetStdHandle(-10),0x7F);//STD_INPUT_HANDLE
}
*/

int mainCRTStartup()   
{   
    int i,na, nb, nc,sign,e;   
    __int64 t1, t2;   
    double f1,f2;
      
    //conc();
    printf("******************************************************\n");
    printf("*                                                    *\n");
    printf("******************************************************\n");
    while (scanf("%s", buf) != EOF)   
    {   
      sign = false;   
      if (buf == '-')   
      {   
            sign = !sign;   
            convert(buf + 1, a, &na);   
      }   
      else convert(buf, a, &na);   
      scanf("%s", buf);   
      if (buf == '-')   
      {   
            sign = !sign;   
            convert(buf + 1, b, &nb);   
      }   
      else convert(buf, b, &nb);   
      
   
          polynomial_multiply(a, na, b, nb, c, &nc);
         t1 = 0;   
            for (i = 0; i < nc; ++i)   
            {   
            t2 = t1 + c;   
            c = t2 % MOD;   
            t1 = t2 / MOD;   
            }   
            for (; t1; t1 /= MOD) c = t1 % MOD;   
            if (sign) putchar('-');   
            print(c, nc);
      
      printf("******************************************************\n");
    }   
    return 0;   
}

   

@echo off
:re
cls
echo /*********************************************/
echo /   构建命令                              /
echo /*********************************************/
.\tools\x86\cl.exe .\src\hello_world.c /I".\inc\crt" /D"x86_xp" /I".\inc\api" /Fp:strict /Fa"Debug\hello_world.asm" /Fo"Debug\hello_world.obj" /c /MD

echo /*********************************************/
echo /                                             /
echo /*********************************************/


.\tools\x86\link.exe .\Debug\hello_world.obj /LIBPATH:".\lib\wxp\i386" /LIBPATH:".\lib\Crt\i386"/OUT:"Debug\hello_world.exe" /NOLOGO /SUBSYSTEM:CONSOLE /MACHINE:X86 "kernel32.lib"
echo /*********************************************/
echo /                                             /
echo /*********************************************/


pause
goto re

0xAA55 发表于 2016-7-29 17:21:35

咦,附件呢。。

Ayala 发表于 2016-7-29 19:52:57

...








0xAA55 发表于 2016-7-30 15:41:49

看样子我还得说明一下解压的办法,首先这后缀是zip但它不是zip压缩包,因此改后缀,去掉所有的“.zip”。
那么4个文件,应该是这样的文件名:
_hello_world.7z.001
_hello_world.7z.002
_hello_world.7z.003
_hello_world.7z.004
然后选中第一个文件,也就是_hello_world.7z.001,右键用7z打开就行了。
RAR能不能打开我还不知道。。但我还是自己上传一个单压缩文件免得有人不会解压。。。

elephantcaptain 发表于 2016-8-25 13:53:00

請問一下,除了加上這些preprocessor之外,還需要加上甚麼嗎? compile之後出現error
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <complex.h>

jasonchen 发表于 2016-11-17 10:31:59

支持    !!

jasonchen 发表于 2016-11-17 10:32:20

支持    !!

jasonchen 发表于 2016-11-17 10:32:45

支持    !!
页: [1]
查看完整版本: 大数乘法c源码 -fft