Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

HugeMotherFuckingInt

Name: Anonymous 2011-08-15 7:48

I'm trying to write a HugeMotherFuckingInt processing library in C.

My first try, I stored the numbers as a char[] and computed them using basic arithmetic.

My second try, I stored the numbers as unsigned long char[]. This proved to be a faster, easier and clearer approach.

Still though, it seems to be a bit too slow.

What other data structures might result in faster execution of basic arithmetic +/*-?

Also, are there any algorithms to speed up the arithmetic operations themselves?

Name: Anonymous 2011-08-15 8:18

unsigned long char[]

Actually, I meant an unsigned long int[].

Name: n3n7i 2011-08-15 8:25

=) been there... 360 Digit -Base 10- Reporting in
You should be using at least int's [4 byte per array pos].... thats 0 - 4294967296 as unsigned // just use signed ints (Max ~2000000000) and Use BASE 1,000,000,000 [Largest/Easiest fit](10^n is just nicest to use... 2^n if you like)

Leaving at least one bit spare - lets you add two arrays together plus carry the ones

 And have your arrays set up (Big / Little?? Endian) lowest base first (Whichever-really=) - I think lowest is nicer cos you can run your loops from element 0... An stitch 'em up


c=0;
for(i = 0 to 10){
     a[i] = a[i] + b[i] + c;
     c=0;
     if(a[i]>=1000000000){
          a[i]=-1000000000;
          c++;
          }
     }

Name: Anonymous 2011-08-15 8:28

>>2
You're better off using unsigned short because then you can easily use 32bit arithmetic.

Also, for multiplication you need faster algorithms, refer to the Python implementation: http://svn.python.org/view/python/trunk/Objects/longobject.c?view=markup

Name: Anonymous 2011-08-15 8:38


#include <stdio.h>
#include <stdlib.h>

int main ()
{
    int x = 2;
    unsigned long int a[101], b[101], c[101];
   
    for(int i = 0; i < 100; i++)
    {
            c[i] = 0;
            b[i] = 0;
            a[i] = 0;
    }   
    a[0] = 1;
    b[0] = 1;
    c[0] = 0;

    while(a[99] < 1000000000)
    {
        x++;

        for(int i = 0; i < 100; i++)
        {
            c[i] = b[i];
            b[i] = a[i];
            a[i] = 0;
        }       

        unsigned int carry = 0;

        for(int i = 0; ((b[i] != 0) || (c[i] != 0) || (carry != 0)) && (i < 100); i++)
        {
            unsigned long int d = b[i], e = c[i];
            d += e + carry;

            printf("%d  %lu  %lu  %lu \n", i, d, e, carry);
           
            carry = 0;
            if (d > 9999999999)
            {   
                carry = d/10000000000;
                d %= 10000000000;
            }
            a[i] = d; 
        }

        printf("------------------------------------\n");
        for(int i = 0; i < 100;i++)
            printf("%10lu   %d\n", a[i], i+1);    
        printf("------------------------------------\n");

    }
    printf("\n\n%d\n", x);
    return 0;
}

Name: n3n7i 2011-08-15 8:55

...Fast multiplication by Doubling (Double Binary // 2 log2 max)
Eg X*27
X= 1X
X+X = 2X
2X+2X = 4X
4X .. 8X
8X .. 16X

16X + 8X + 2X + 1X = 27X (Done in 7 Additions vs 27)

...Fast exponents by squaring (Same thing)

..Might need a couple of matrices

Name: Anonymous 2011-08-15 10:00

For multiplication, switch to katsuraba algorithm when it becomes about >=256~1024 bit long. Find the perfect combination.

Name: Anonymous 2011-08-15 10:24

LLLLLLLLLLLOOOOOOOOOOOOOOOOOOOOOOOOOOOOLLLLLLLLLLLLLLLLL

Name: Anonymous 2011-08-15 11:02

You should use an unsigned int representation for efficiency as this is the machine word size. C ensures unsigned addition wraps around so you can implement most algorithms quite easily. Some tricks are needed for multiplication which aren't worth discussing. Endianness doesn't really matter.

typedef struct _biginteger {
    int length;
    int capacity;
    unsigned int* data;
} bigint;


If you are actually planning to use the library rather than write a toy implementation you should just use an existing implementation, eg GMP.

GMP makes available an extremely useful algorithms reference at http://gmplib.org/manual/Algorithms.html#Algorithms which you may find useful.

Unless you have ~500 limb integers long multiplication will probably be the fastest method available- so any performance improvements need to come from micro optimizations. Or rather, hand coding assembly, which is why you don't really want to write your own.

Name: Anonymous 2011-08-15 14:23

>>6
I wonder how this compares to FFT multiplication.  I might benchmark them sometime in-between masturbation sessions.

Name: Anonymous 2011-08-15 15:25

>unsigned addition wraps around
C1X 6.2.5 : 9
Woah I was so sure of C having obscure arcane rules for both signed and unsigned addition operators that I never bothered to check until now.
I guess the committee realized that some times the best way to introduce arbitrary retardation is to inject bits of sanity at random.

Name: Anonymous 2011-08-15 20:08

I'm also making a toy big integer library.
I was wondering what's an efficient way to divide integers.
Most of the methods I've come across involve inversion of the denominator but I'm not interested in decimal places of arbitrary precision.

Name: n3n7i 2011-08-15 22:24

Can make a pretty fast modulo style divide...
-Just use the multiply trick (above)-

Here's where i got up to last night... (before it got too cold to code at least..)

//-------------------------------
#include <stdio.h>
#include <stdlib.h>

const RRay = 50;       //      Max array Size //
const CutOff = 1000;   //      Base

int aa[52]; int ab[52]; int ac[52];


//----------------------------------
   
void Add(int xa[], int xb[]){
    int i, iCarry=0, raymax=0;
   
    raymax = xa[RRay];
    if(xb[RRay]>raymax) raymax = xb[RRay]; 
    ac[RRay] = raymax;
   
    for(i=0;i<=ac[RRay];i++){
    ac[i] = xa[i] + xb[i] + iCarry;
    iCarry=0;
    if(ac[i]>CutOff){
        iCarry++;
        ac[i]-=CutOff;
        }
    if((i==ac[RRay])+(iCarry==1)==2) ac[RRay]++;
    }
}

//-----------------------------------
   
void Entry(int x[]){
     int i, i2, i3;
     printf("Enter Base size"); //<<------- xRAY [Base length]
     scanf("%i",&i3);         
     if(i3>RRay) i3 = RRay;
     for(i=i3;i>=0;i--){
        printf("Enter No i");
        scanf("%i",&i2);
        printf("Entered %i\n", i2);
        x[i]=i2;   
        }
    x[RRay] = i3;           //<<------- xRAY [store current length]
for(i=i3;i>=0;i--) printf("%3i,", x[i]);   
}

//------------------------------------

void Printout(int xX[]){
     int i;
     for(i=xX[RRay];i>=0;i--) printf("%3i,", xX[i]);
}

//====================================

int main(){
    Entry(ac);
    Add(ac, ac);
    printf("\n (* 2 =) \n");
    Printout(ac);   

    Add(ac, ac);
    printf("\n (* 2 =) \n");
    Printout(ac);   

    Add(ac, ac);
    printf("\n (* 2 =) \n");
    Printout(ac);   
return 0;

}

//Using signed int's =) You'll see why when it comes to subtraction =D

Name: n3n7i 2011-08-15 22:45


//----------------------------------
   
void Add(int xa[], int xb[]){
    int i, iCarry=0, raymax=0;
   
    raymax = xa[RRay];
    if(xb[RRay]>raymax) raymax = xb[RRay]; 
    ac[RRay] = raymax;
   
    for(i=0;i<=ac[RRay];i++){
    ac[i] = xa[i] + xb[i] + iCarry;
    iCarry=0;
    [b]if(ac[i]>=CutOff){[/b] //<<Corrected
        iCarry++;
        ac[i]-=CutOff;
        }
    if((i==ac[RRay])+(iCarry==1)==2) ac[RRay]++;
    }
}
//----------------------------------
   
void Sub(int xa[], int xb[]){
    int i, iCarry=0, raymax=0;
   
    raymax = xa[RRay];
    if(xb[RRay]>raymax){ printf("Problem!"); raymax = xb[RRay];  }
    ac[RRay] = raymax;
   
    for(i=0;i<=ac[RRay];i++){
    ac[i] = xa[i] - (xb[i] + iCarry);
    iCarry=0;
    if(ac[i]<0){
        iCarry++;
        ac[i]+=CutOff;
        }
    if((i==ac[RRay])+(iCarry==1)==2){ printf("Negative!"); ac[RRay]++; }
    }
}

//-----------------------------------

Name: n3n7i 2011-08-15 23:38

more...?
#include <stdio.h>
#include <stdlib.h>

const RRay = 50;       //      Max array Size //
const CutOff = 1000;   //      Base

int aa[52]; int ab[52]; int ac[52];


//----------------------------------------------------

void Set(int xa[], int xb[]){
int i;
for(i=0;i<=RRay;i++) xa[i] = xb[i];
}

//----------------------------------

int GOWFish(int a, int b){
int ret=0;
if(a!=b){
    if(a>b) ret= 1;
    if(a<b) ret=-1;
    }
return ret;
}

//---------------------

int GreaterOrWhat(int xa[], int xb[]){
int a, b, i, ret=0;
a = xa[RRay];
b = xb[RRay];
i =a+1;
ret = GOWFish(a, b);
while((ret==0) + (i>=0)==2){
    i--;
    a = xa[i];
    b = xb[i];
    ret = GOWFish(a, b);
    }
return ret;
}

//----------------------------------------------   
   
void Add(int xa[], int xb[]){
    int i, iCarry=0, raymax=0;
   
    raymax = xa[RRay];
    if(xb[RRay]>raymax) raymax = xb[RRay]; 
    ac[RRay] = raymax;
   
    for(i=0;i<=ac[RRay];i++){
    ac[i] = xa[i] + xb[i] + iCarry;
    iCarry=0;
    if(ac[i]>=CutOff){
        iCarry++;
        ac[i]-=CutOff;
        }
    if((i==ac[RRay])+(iCarry==1)==2) ac[RRay]++;
    }
}
//----------------------------------

void CheckRRay(int xa[]){
int i, iTop=0;
for(i=0;i<RRay;i++){
    if(xa[i]>0) iTop=i;
    }
if(xa[RRay]!=iTop){ printf("Fixed RRay"); xa[RRay]=iTop;}
}

//-------------------------------------
   
void Sub(int xa[], int xb[]){
    int i, iCarry=0, raymax=0;
   
    raymax = xa[RRay];
    if(xb[RRay]>raymax){ printf("Problem!"); raymax = xb[RRay];  }
    ac[RRay] = raymax;
   
    for(i=0;i<=ac[RRay];i++){
    ac[i] = xa[i] - (xb[i] + iCarry);
    iCarry=0;
    if(ac[i]<0){
        iCarry++;
        ac[i]+=CutOff;
        }
    if((i==ac[RRay])+(iCarry==1)==2){ printf("Negative!"); ac[RRay]++; }
    }
     CheckRRay(ac);
}

//-----------------------------------
   
void Entry(int x[]){
     int i, i2, i3;
     printf("Enter Base size"); //<<------- xRAY [Base length]
     scanf("%i",&i3);         
     if(i3>RRay) i3 = RRay;
     for(i=i3;i>=0;i--){
        printf("Enter No i");
        scanf("%i",&i2);
        printf("Entered %i\n", i2);
        x[i]=i2;   
        }
    x[RRay] = i3;           //<<------- xRAY [store current length]
for(i=i3;i>=0;i--) printf("%3i,", x[i]);   
}

//------------------------------------

void Printout(int xX[]){
     int i;
     for(i=xX[RRay];i>=0;i--) printf("%3i,", xX[i]);
     printf("\n");
}

//====================================

int main(){
    Entry(aa);
    Set(ac, aa);
    Add(ac, ac);
   
   printf("\n (* 2 =) \n");
    Printout(ac);   

    Add(ac, ac);
    printf("\n (* 2 =) \n");
    Printout(ac);   

    Add(ac, ac);
    printf("\n (* 2 =) \n");
    Printout(ac);   

    printf("\n ( - ) \n aa : ");
    Printout(aa);
    Set(ab, ac);
    Sub(ac, aa);
    printf("\n ac : ");
    Printout(ac);
   
    printf("aa > ac?");
    printf("%i", GreaterOrWhat(aa, ac));
   
    printf("\nab > ac?");
    printf("%i", GreaterOrWhat(ab, ac));
   
    printf("\nab + ac\n");
    Add(ab, ac);
    Printout(ac);

return 0;

}

Name: Anonymous 2011-08-16 0:05

>>14-15
You don't need any ``kewl trix'' for subtraction, it is addition with the second operand's sign bit flipped. Use unsigned ints and keep a sign bit.

Name: n3n7i 2011-08-16 0:31

hmm? i don't quite follow.. Signed ints Aren't easier??
Better not forget this bit (InitArrays // Zero) >>

//----------------------------------

void Zero(int xa[]){
int i;
for(i=0;i<=RRay;i++) xa[i] = 0;
}

//----------------------------------

Name: Anonymous 2011-08-16 0:31

Integral division with remainder is discussed in detail in Knuth volume 2, section 4.3.1

Your code is also ugly as fuck and I would advise that you cease development and look into finding a more idiomatic C style first.

Name: n3n7i 2011-08-16 0:54

=)
I already know a fast division... with remainder (aka modulo) // Binary method again
X = 27
Z / X

X + X = 2X
2X + 2X = 4X
4X + 4X = 8X
8X + 8X = 16X

Z - (16X + 8X...etc)
if Z<X Remainder = Z
Z / X = 16 + 8 + etc...

Name: Anonymous 2011-08-16 1:23

>>19
D'oh.

Name: Anonymous 2011-08-16 1:26

>>19
You think your are smarter than Knuth?

Name: Anonymous 2011-08-16 1:53

>>17
They aren't. In C, if a signed int overflows, it's undefined behaviour, unsigned ints are guaranteed to wrap around (>>9), so you can portably check for overflow. You're wasting one bit for each limb, which is worse than the 7 bits wasted to store the sign bit (that can be reused for some other flags, unlike the integers' sign bit), to store redundant information, reducing the length of each limb. Unsigned integer operations are also usually faster than signed one.

Also, please, learn to properly (read: not randomly) capitalize words, link to posts you're responding to, and drop the emoticons and the name (this is an anonymous programming textboard, and that's what made /prog/ great).

Name: n3n7i 2011-08-16 2:11

...i Don't know Knuth, so I can't really say
...Yes it's ugly [u can make it pretty if u want ;]
...Its being caught before it wraps (Hence no prob) // 30 out of 32 bit aint bad?
...Anything Else?


int main(){
int i=0;
Zero(aZero);
One(aOne);


Zero(aa);
One(aCount);
//One(bCount);


Entry(aa);
Set(ac, aa);

printf("\n----------------------------------\n");

while(GreaterOrWhat(aa, aCount)==1){   
   
    //Printout(aCount);
    //Printout(ac);

    Add(ac, aa, ac);
    Add(aCount, aOne, aCount);
    }

Printout(aCount);
Printout(ac);

return;
}

Name: Anonymous 2011-08-16 2:29

>>23
If 31 out of 32 is bad, 30 out of 32 is doubly bad. Good enough is enemy of better, which is enemy of perfect.
Even if it is a toy implementation, you should do it properly.

And, again, proper grammar and punctuation, please.

Name: n3n7i 2011-08-16 2:43

my enemies enemy is my friend =D

Name: Anonymous 2011-08-16 2:55

I think it would be best for everyone if you returned to the imageboards.

Name: Anonymous 2011-08-16 3:06

>>25
And so, after this post, I've completely lost faith in humanity.

Name: n3n7i 2011-08-16 3:09

*enemy's? lol

I guess i should point out i'm using signed ints (Obv) to make a 'HugeUnsignedInt' .... (Not-so-Obv)

...If you actually tried to make one of these on your own (Without just copy-pasta-ing it) you might see some wisdom in them codes....

Its less than a days work.... of course its ugly...(keep in mind i have written one of these b4 // have an idea of the problems/ some solutions? already /// wasn't so fAST the first time around) 

...Search / Replace would clean it up easy enough??

Name: Anonymous 2011-08-16 3:18

>>28
i'm using signed ints [...] to make a 'HugeUnsignedInt'
And I even thought you couldn't get worse!
Seriously, that's retarded, it should be rewritten from scratch to clean it up.

Name: Anonymous 2011-08-16 4:20

>>28
I can insure you both me and the Sussman have implemented multiple precision libraries. Would you leave us be?

Name: n3n7i 2011-08-16 4:31

Your using unsigned int >> signed int
Im using signed int >> unsigned int

Really they are not so dissimilar... Synergetic even....
Perhaps i only need Unsigned Big Numbers? El-Gamal and the like don't use anything below zero....

Name: Anonymous 2011-08-16 5:09

No, I'm using unsigned+sign bit, and there's a reason for it (unsigned ops are faster, 1 bit wider, etc).
You have no reason to make unsigned bigints from signed ints: you waste space, it's slower, it's stupid.
I mean, what's next, 32 bit numbers using bigints?

Name: n3n7i 2011-08-16 5:22

How do you add if you're using every last bit? =.

Name: n3n7i 2011-08-16 5:32

...perhaps storing highest used base a la XRAY[50] for quick Greater-than eval / Saving a few loop Reps here and there /// was a bit too advanced / Unclear?

+I spy a memory / speed tradeoff or two? //More spare bits is equiv to larger max addition ops (Instead of just two // add 4 or even 8 bigvals at once [2-3bit tradeoff's]).....

Name: Anonymous 2011-08-16 5:46

>>33
Uints wrap around, unsigned addition always yields something >= to the greater operand, so you can check for unsigned overflow with c = a + b; c < max(a,b) // true = overflow. Also, the architecture is likely to have a carry flag and an add-with-carry instruction.

Name: Anonymous 2011-08-16 5:52

>>35
You should not use max(a, b) as it generates a conditional jump, it is sufficient to test that c < a because b < 2^32.

Name: Anonymous 2011-08-16 5:58

>>34
>=, >, <, <= are implemented by just comparing the sign bits, if equal compare last valid index of the bigint vectors (because you store the length), and if equal compare the last elements. No loops involved.
I haven't read your code because it's absolute shit. Learn to program, then come back.
Also, what the fuck are those slashes?

Name: Anonymous 2011-08-16 6:04

>>36
You mean c <= a (think of a+0, even though you probably do nothing on addition to 0)? You're right, though, I was just being lazy and didn't want to check if that could work.

Name: n3n7i 2011-08-16 7:01

...It's working again =)

Anyone Got some big (Hopefully easy to enter) Numbers?

eg 1, 1, 1, 1, is Equiv to 1, 000,000,001, 000,000,001, 000,000,001

Doing multiply at least...

Name: Anonymous 2011-08-16 7:13

1999999999666666666 * 2333555444111222333 =
4,667110887,444592849,740555592,925851778

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List