Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Re^3: OT: Finding Factor Closest To Square Root

by Limbic~Region (Chancellor)
on Feb 24, 2005 at 16:20 UTC ( [id://434114]=note: print w/replies, xml ) Need Help??


in reply to Re^2: OT: Finding Factor Closest To Square Root
in thread OT: Finding Factor Closest To Square Root

QM,
My latest obsession is with Perl internals, improving my C skills. Inline::C is a great way to do both, so I figured I would translate my previous code (minus the %seen cache). It actually loses when checking just one number, but running it in a loop of a lot of numbers it wins hands down.
#!/usr/bin/perl use strict; use warnings; use Inline 'C'; use Math::Pari qw/factorint PARImat/; my $num = $ARGV[0]; print nearest_sqrt($num, prime_factors( $num ) ) || 'prime'; sub prime_factors { my $num = shift; my %p_fact = PARImat( factorint( $num ) ) =~ /(\d+)/g; return [ map { ($_) x $p_fact{$_} } keys %p_fact ]; } __END__ __C__ int nearest_sqrt (double num, SV* input) { int len = av_len((AV *)SvRV(input)); int tot = len + 1; int i = 0; double list[ tot ]; int position[ tot ]; int stop[ tot ]; double offset = -1; int end_pos; int done = 0; int winner = 0; int by = 0; int next = 1; while ( i <= len ) { list[ i ] = SvNV(* av_fetch((AV *)SvRV(input), i, 0)); ++i; } while ( done == 0 ) { int j; int cur; double factor; double diff; if ( next == 1 ) { int c = 0; int p = 0; int s = 0; ++by; if ( by > tot ) break; if ( by >= 2 ) { for (p = 0; p <= by - 2; ++p) { position[ p ] = p; } } position[ p ] = by - 2; end_pos = p; for ( s = tot - by; s <= len; ++s ) { stop[ c ] = s; ++c; } next = 0; } cur = end_pos; while ( 1 ) { if ( ++position[ cur ] > stop[ cur ] ) { int k; int new_pos; position[ --cur ]++; if ( position[ cur ] > stop[ cur ] ) continue; new_pos = position[ cur ]; for (k = cur; k <= end_pos; ++k) { position[ k ] = new_pos++; } } break; } if ( position[0] == stop[0] ) { if ( position[0] == tot ) { done = 1; } else { next = 1; } } factor = 1; for (j = 0; j <= end_pos; ++j) { factor *= list[ position[ j ] ]; } diff = (num / factor) - factor; if ( diff >= 0 && (offset == -1 || diff < offset) ) { winner = factor; offset = diff; } } return( winner ); }
I am sure someone more knowledgeable could make the C cleaner if not faster.

Cheers - L~R

Updated - copy/paste fixed as sleepingsquirrel pointed out below

Replies are listed 'Best First'.
Re^4: OT: Finding Factor Closest To Square Root
by sleepingsquirrel (Chaplain) on Feb 24, 2005 at 17:28 UTC
    I took a quick glance at your code, and found this snippet to be a little odd...
    end_pos = p; for (p = 0; p <= end_pos; ++p) { }
    ...perhaps there was something between the brackes in an earlier version?


    -- All code is 100% tested and functional unless otherwise noted.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://434114]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others admiring the Monastery: (7)
As of 2024-04-25 08:57 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found