NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

## All the Perl that's Practical to Extract and Report

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.

Full
Abbreviated
Hidden
• #### That implies...(Score:2)

...that you're trying to move a long long between C and Perl. Do you need to do that? Can't the long longs just live inside the C?

It's probably not too hard to write the code to thunk between long long and Math::BigInt - would that help?

• #### Re:That implies...(Score:2)

by Ovid (2709) on 2008.02.23 11:02 (#61268) Homepage Journal

I don't know since my C and XS skills are so poor. The relevant bit of XS code is this:

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include <stdbool.h>

#include "ppport.h"

/* This function calculates (ab)%c */
int modulo(int a,int b,int c){
long long x=1,y=a; // long long is taken to avoid overflow
// of intermediate results
// skipping implementation
}

/* this function calculates (a*b)%c taking into account
that a*b might overflow */
long long mulmod(long long a,long long b,long long c){
long long x = 0,y=a%c;
// skipping implementation
}

/* Miller-Rabin primality test, iteration signifies the accuracy of the test */
bool Miller(long long p,int iteration){
if(p<2){
return false;
}
if(p!=2 && p%2==0){
return false;
}
long long s=p-1;
while(s%2==0){
s/=2;
}
int i;
for(i=0;i<iteration;i++){
long long a=rand()%(p-1)+1,temp=s;
long long mod=modulo(a,temp,p);
while(temp!=p-1 && mod!=1 && mod!=p-1){
mod=mulmod(mod,mod,p);
temp *= 2;
}
if(mod!=p-1 && temp%2==0){
return false;
}
}
return true;
}

MODULE = Number::Properties     PACKAGE = Number::Properties

void Miller(p, iteration)
long long p
int iteration

In other words, I just need to figure out the interface to the Miller() function and this should work, but I'm unsure.

• #### Re:(Score:2)

If you're prepared to limit the input to 32 bit integers you can probably just change the `long long` to `long` in the prototype of Miller(). It should still use `long long` internally.

To be more strictly correct you could use the output of

perl -MConfig -le 'print \$Config{ivtype}'

as the type of that argument. That will be `long` for 32 bit Perl and `long long` for 64 bit Perl.

And if you want to be really sneaky write a version that bypasses XS type mapping and correctly handles Math::BigInt objects :)

• #### Re:(Score:2)

If you're prepared to limit the input to 32 bit integers
A plain float in Perl has 53 bits of precision, which means you can represent 53 bit integers exactly, which is better than merely 32 bits.

Or, am I missing a point?

• #### Re:(Score:2)

No, I think you're quite right :)

This little program:

#!/usr/bin/perl

my \$num  = 1;
my \$bits = 0;
while ( \$num + 1 != \$num ) {
\$num *= 2;
\$bits++;
}

print "\$bits\n";

prints 53.

So Ovid - make that argument a double and then cast it to a long long inside the function.

• #### Re:(Score:1)

If (and its a big if) you need the full 64 bit input, might I suggest passing the number as a string/PV, then doing a strtoll() or its equivalent in your non-XS functions ?

void Miller(char *p, int iteration)

and the Miller function becomes

bool Miller(char *p_as_str,int iteration){
long long p = stroll(p_as_str);
if(p<2){

Caveat: obviously, if you put something other than a number in p_as_str, things will go awry. Also, different platforms (e.

• #### Re:(Score:1)

DOH! That should be strtoll()...