Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions Makefile.PL
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use ExtUtils::MakeMaker;
use Config;

my $broken64 = (18446744073709550592 == ~0);
if ($broken64) {
Expand All @@ -15,6 +16,24 @@ I highly recommend upgrading to a newer version of Perl.
EOW
}

my $msvc_Oi = !!0;
{
my ($cc, $ver) = $Config{cc};
if ($cc eq 'cl') {
my @ver = `$cc 2>&1`; # Interesting output in STDERR
$ver = join('', @ver);

#print 'VER:'.$ver.':'."\n";
if ($ver =~ /Version (\d[\d\.]+)/ms) {
$ver = $1;
}
else {
die "Unknown version of Microsoft Visual C";
}
$msvc_Oi = '-Oi' if $ver < 14 && $ver >= 13; #VC2002/2003 only
}
}

WriteMakefile1(
NAME => 'Math::Prime::Util',
ABSTRACT => 'Utilities related to prime numbers, including fast sieves and factoring',
Expand Down Expand Up @@ -81,6 +100,7 @@ WriteMakefile1(
},

MIN_PERL_VERSION => 5.006002,
DEFINE => $msvc_Oi,
);

sub WriteMakefile1 { # Cribbed from eumm-upgrade by Alexandr Ciornii
Expand Down
26 changes: 26 additions & 0 deletions util.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,32 @@ static UV count_zero_bits(const unsigned char* m, UV nbytes)
return count;
}

#if defined(_MSC_VER) && _MSC_VER < 1300
/* used for testing
unsigned char __fastcall _2BitScanForward(unsigned long* Index, unsigned long Mask) {
return _BitScanForward(Index,Mask);
}
unsigned char __fastcall _2BitScanReverse(unsigned long* Index, unsigned long Mask) {
return _BitScanReverse(Index,Mask);
}*/

unsigned char __declspec( naked ) __fastcall _BitScanForward(unsigned long* Index, unsigned long Mask) {
__asm {
bsf eax, edx /* edx is Mask */
mov [ecx], eax /*ecx is Index */
setnz al
retn
};
}
unsigned char __declspec( naked ) __fastcall _BitScanReverse(unsigned long* Index, unsigned long Mask) {
__asm {
bsr eax, edx /* edx is Mask */
mov [ecx], eax /*ecx is Index */
setnz al
retn
};
}
#endif

/* Does trial division or prob tests, assuming x not divisible by 2, 3, or 5 */
static int _is_prime7(UV n)
Expand Down
19 changes: 19 additions & 0 deletions util.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,26 @@ static int is_perfect_square(UV n)
#define log2floor(n) ((n) ? 31-__builtin_clzl(n) : 0)
#endif
#elif defined (_MSC_VER)
#if _MSC_VER >= 1400
#include <intrin.h>
#elif _MSC_VER >= 1300
/* undocumented for VC 2003, not in headers or .libs
-Oi required for this to work in -O1 or -Od mode
http://www.geoffchappell.com/studies/msvc/language/preprocessor/directives/pragma/intrinsic.htm
*/
unsigned char _BitScanForward(unsigned long* Index, unsigned long Mask);
unsigned char _BitScanReverse(unsigned long* Index, unsigned long Mask);
unsigned char _BitScanForward64(unsigned long * Index,unsigned __int64 Mask);
unsigned char _BitScanReverse64(unsigned long * Index,unsigned __int64 Mask);
#pragma intrinsic(_BitScanForward)
#pragma intrinsic(_BitScanReverse)
#pragma intrinsic(_BitScanForward64)
#pragma intrinsic(_BitScanReverse64)
#else
unsigned char __fastcall _BitScanForward(unsigned long* Index, unsigned long Mask);
unsigned char __fastcall _BitScanReverse(unsigned long* Index, unsigned long Mask);
#endif

#ifdef FUNC_ctz
static int ctz(UV n) {
UV tz = 0;
Expand Down