Hi Folks,

It was quite the trek, but we now have a working plugin that allows us 
to manipulate very large primes in a reasonable period (4ms with the 
plugin vs. 14ms under Python vs. 40SECs as a native RB class.

Here's the final code and I'll describe the gotchas below:

------------------------
void modular_exp(unsigned short * base, unsigned short * power, unsigned 
short * result) {
    unsigned short z, sqr[BIGNUM_SHORTS], exp[BIGNUM_SHORTS];
    int i = 0;
       
    for(i=0; i<BIGNUM_SHORTS; i++) {
        result[i] = one[i];
        exp[i]    = power[i];
    }
   
    modular_product(base, one, sqr);
   
    for(;;) {
        if (exp[0] & 1)
            montgomery_reduction(sqr, result, result);
       
        z = 0;
        for(i=0; i<BIGNUM_SHORTS-1; i++) {
            exp[i] = (exp[i] >> 1) | ((exp[i+1] & 1) << 15);
            z |= exp[i];
        }
       
        exp[BIGNUM_SHORTS-1] >>= 1;
        z |= exp[BIGNUM_SHORTS-1];
       
        if (z == 0)
            break;
       
        montgomery_reduction(sqr, sqr, sqr);
    }
   
    modular_product(result, rp, result);
}

void ModularExp(REALmemoryBlock base, REALmemoryBlock power, 
REALmemoryBlock result)
{
    unsigned short *mbase, *mpower, *mresult;
    mbase = (unsigned short *) REALMemoryBlockGetPtr(base);
    mpower = (unsigned short *) REALMemoryBlockGetPtr(power);
    mresult = (unsigned short *) REALMemoryBlockGetPtr(result);
    modular_exp(mbase, mpower, mresult);
}

REALmethodDefinition ModularExpdefn = {
    (REALproc) ModularExp, nil,
    "ModularExp(base As MemoryBlock, power As MemoryBlock, result As 
MemoryBlock)",
    REALconsoleSafe
};
   
   
void PluginEntry(void)
{
    REALRegisterMethod(&ModularExpdefn);
}
---------------------------

The first issue that we ran into was understanding how to configure the 
passing of the "unsigned short *" memoryblocks from RB to the plugin.  
At this time, we did not have the ModularExp() function defined - more 
on that in a moment.  The first thought was that we needed to pass the 
memoryblocks ByRef because the third memoryblock's contents needed to be 
mutable as the result of the math would be stored into that array of 
unsigned shorts.  Therefore, we changed the "REALmethodDefinition" to 
looks like this:

    REALmethodDefinition ModularExpdefn = {
        (REALproc) ModularExp, nil,
        "ModularExp(ByRef base As MemoryBlock,
            ByRef power As MemoryBlock,
            ByRef result As MemoryBlock)",
        REALconsoleSafe
    };

Unfortunately, this did not resolve the issue and we ended up with a 
crash in the RB project when we called ModularExp(m1, m2, m3).  The next 
attempt was to remove the ByRef from the first two references and only 
pass the third ByRef as it was the only memoryblock that needed to be 
mutable.  The function then became:

    REALmethodDefinition ModularExpdefn = {
        (REALproc) ModularExp, nil,
        "ModularExp(base As MemoryBlock,
            power As MemoryBlock,
            ByRef result As MemoryBlock)",
        REALconsoleSafe
    };

While this change cause a different SIGSEGV in the plugin, it didn't fix 
the problem.  I then noted in one of the PluginTest functions that the 
passing of a memoryblock use a remap of the char * definition to a 
REALmemoryBlock, so I made a change to the real function (modular_exp()) 
to use a REALmemoryBlock * instead of unsigned short *.  However, this 
resulted in a compile failure.  Tim Hare to the rescue -

Tim noticed that we needed to get the pointer to the memoryblocks to 
pass into our real function and offered up this new function:

    void ModularExp(REALmemoryBlock base, REALmemoryBlock power, 
REALmemoryBlock result)
    {
        unsigned short *mbase, *mpower, *mresult;
        mbase = (unsigned short *) REALMemoryBlockGetPtr(base);
        mpower = (unsigned short *) REALMemoryBlockGetPtr(power);
        mresult = (unsigned short *) REALMemoryBlockGetPtr(result);
        modular_exp(mbase, mpower, mresult);
    }

I agreed that this was what was needed, made the change (changing my 
errant REALmemoryBlock * back to the original unsigned short *), and 
compiled and prepped the plugin.  Unfortunately, we still suffered from 
a SIGSEGV on the line where we copy the contents of an internal lookup 
table into the result[] array.

Back to gdb... - what's this, the first two memoryblocks' addresses are 
being passed properly, but the result memoryblock is coming through as 
0x00.  More digging and I finally realized that I'd neglected to remove 
the final "ByRef" change that I'd made in my early attempts at solving 
this.  I remove that vestigial ByRef, recompiled, re-converted, and 
VOILA! We now can perform exponentiation on very large primes in 
milliseconds instead of excruciatingly painful seconds.

As an aside, if you are working on plugins and want real debug support, 
build your project and then execute the actual binary within gdb.  You 
can set breakpoints and step/manipulate things very easily (if you know 
gdb).

Is it just me, or do we really need a bit more SDK documentation?

Now off to Windows and Linux.

Tim

_______________________________________________
Unsubscribe or switch delivery mode:
<http://www.realsoftware.com/support/listmanager/>

Search the archives:
<http://support.realsoftware.com/listarchives/lists.html>

Reply via email to