program Midl3dig;
{$IFDEF FPC}
  {$MODE Delphi} //result /integer => Int32 aka longInt etc..
{$ELSE}
  {$APPTYPE console} // Delphi
{$ENDIF}
uses
  sysutils;   //IntToStr
function GetMid3dig(i:NativeInt):Ansistring;
var
  n,l: NativeInt;
Begin
  setlength(result,0);
  //n = |i| jumpless abs
  n := i-((ORD(i>0)-1)AND (2*i));
  //calculate digitcount
  IF n > 0 then
    l := trunc(ln(n)/ln(10))+1
  else
    l := 1;
  if l<3 then Begin  write('got too few digits');  EXIT; end;
  If Not(ODD(l)) then Begin write('got even number of digits'); EXIT; end;
  result:= copy(IntToStr(n),l DIV 2,3);
end;
const
  Test : array [0..16] of NativeInt =
    ( 123,12345,1234567,987654321,10001,-10001,
    -123,-100,100,-12345,1,2,-1,-10,2002,-2002,0);
var
  i,n : NativeInt;
Begin
  For i := low(Test) to High(Test) do
  Begin
    n := Test[i];
    writeln(n:9,': ',GetMid3dig(Test[i]));
  end;
end.


#!/usr/bin/perl
use strict ;
use warnings ;

sub middlethree {
   my $number = shift ;
   my $testnumber = abs $number ;
   my $error = "Middle 3 digits can't be shown" ;
   my $numberlength = length $testnumber ;
   if ( $numberlength < 3 ) {
      print "$error : $number too short!\n" ;
      return ;
   }
   if ( $numberlength % 2 == 0 ) {
      print "$error : even number of digits in $number!\n" ;
      return ;
   }
   my $middle = int ( $numberlength  / 2 ) ;
   print "Middle 3 digits of $number : " . substr( $testnumber , $middle - 1 , 3 ) . " !\n" ;
   return ;
}

my @numbers = ( 123, 12345, 1234567, 987654321, 10001, -10001, -123, -100, 100, -12345 ,
      1, 2, -1, -10, 2002, -2002, 0 ) ;
map { middlethree( $_ ) } @numbers ;


// 32-bit builds of PHP: Integers can be from -2147483648 to 2147483647
// 64-bit builds of PHP: Integers can be from -9223372036854775808 to 9223372036854775807

function middlethree($integer)
{
	$int 	= (int)str_replace('-','',$integer);
	$length = strlen($int);

	if(is_int($int))
	{
		if($length >= 3)
		{
			if($length % 2 == 1)
			{
				$middle = floor($length / 2) - 1;
				return substr($int,$middle, 3);
			}
			else
			{
				return 'The value must contain an odd amount of digits...';
			}
		}
		else
		{
			return 'The value must contain at least three digits...';
		}
	}
	else
	{
		return 'The value does not appear to be an integer...';
	}
}

$numbers = array(123, 12345, 1234567, 987654321, 10001, -10001, -123, -100, 100, -12345, 1, 2, -1, -10, 2002, -2002, 0);

foreach($numbers as $nums)
{
	echo $nums.' : '.middlethree($nums). '<br>';
}


get_middle_f1(Str) = [X,Y,Z] =>
  append(Pre,[X,Y,Z],Post,Str),
  length(Pre) = length(Post).


(de middle3digits (N)
   (let (Lst (chop (abs N))  Len (length Lst))
      (tab (10 -2 -30)
         N
         ":"
         (cond
            ((> 3 Len) "not enough digits")
            ((bit? 1 Len)
               (head 3 (nth Lst (/ Len 2))) )
            (T "even number of digits") ) ) ) )


string middlethree(int i) {
	i = abs(i);
	int length = sizeof((string)i);

	if(length >= 3) {
		if(length % 2 == 1) {
			int middle = (int)floor(length / 2) - 1;
			return(((string)i)[middle..middle+2]);
		}
		else {
			return "The value must contain an odd amount of digits...";
		}
	}
	else {
			return "The value must contain at least three digits...";
	}
}

int main() {
	array(int) numbers = ({123, 12345, 1234567, 987654321, 10001, -10001, -123, -100, 100, -12345, 1, 2, -1, -10, 2002, -2002, 0});

	foreach(numbers, int nums) {
		write((string)nums + " : " + middlethree(nums) + "\n");
	}
	return 0;
}


middle: procedure options (main);      /* 29 October 2013 */
   declare n fixed (15);
   declare s character (25) varying;
   declare in file input;

   open file (in) title ('/MIDDLE.DAT,type(text),recsize(100)');
   on endfile (in) stop;

   do forever;
      get file (in) list (n); put skip list (n);
      n = abs(n);
      s = trim(n);
      if length(s) < 3 then put list ('not possible');
      else  if mod(length(s), 2) = 0 then put list ('not possible');
      else
         do;
            do while (length(s) > 3);
               s = substr(s, 2, length(s)-2);
            end;
            put list ('The middle three digits are: ' || s);
         end;
   end;

end middle;


To run:
Start up.
Test 123.
Test 12345.
Test 1234567.
Test 987654321.
Test 10001.
Test -10001.
Test -123.
Test -100.
Test 100.
Test -12345.
Test 1.
Test 2.
Test -1.
Test -10.
Test 2002.
Test -2002.
Test 0.
Wait for the escape key.
Shut down.

To get the middle three digits of a number giving a string:
Privatize the number.
De-sign the number.
Convert the number to the string.
If the string's length is less than 3, put "Number has fewer than three digits" into the string; exit.
If the string's length is even, put "Number has no middle" into the string; exit.
Put the string's length divided by 2 into a midpoint number.
Slap a substring on the string.
Put the substring's first plus the midpoint minus 1 into the substring's first.
Put the substring's first plus 2 into the substring's last.
Put the substring into the string.

To test a number:
Get the middle three digits of the number giving a string.
Write "" then the number then "  ->  " then the string on the console.


function middle3($inp){

	$str = [Math]::abs($inp)

	$leng = "$str".length

	if ($leng -lt 3){
		Write-host $inp":	[ERROR] too short."
		Return
	}
	if (($leng % 2) -eq 0){
		Write-host $inp":	[ERROR] even number of digits."
	} else {
		$trimmer = ($leng - 3) / 2
		$ans = "$str".subString($trimmer,3)

		Write-host $inp":	$ans"
	}
	Return
}

$sample = 123, 12345, 1234567, 987654321, 10001, -10001, -123, -100, 100, -12345, 1, 2, -1, -10, 2002, -2002, 0

foreach ($x in $sample){middle3 $x}


middle_3_digits(Number, [D1,D2,D3]) :-
    verify_middle_3_able(Number, Digits),
    append(FrontDigits, [D1,D2,D3| BackDigits], Digits),
    same_length(FrontDigits, BackDigits).

verify_middle_3_able(Number, Digits) :-
    must_be(number, Number),
    AbsNumber is abs(Number),
    number_chars(AbsNumber, Digits),
    length(Digits, NumDigits),
    ( 3 > NumDigits         ->  domain_error('at least 3 digits',    Number)
    ; 0 is NumDigits mod 2  ->  domain_error('odd number of digits', Number)
    ; true
    ).


>>> def middle_three_digits(i):
	s = str(abs(i))
	length = len(s)
	assert length >= 3 and length % 2 == 1, "Need odd and >= 3 digits"
	mid = length // 2
	return s[mid-1:mid+2]

>>> passing = [123, 12345, 1234567, 987654321, 10001, -10001, -123, -100, 100, -12345]
>>> failing = [1, 2, -1, -10, 2002, -2002, 0]
>>> for x in passing + failing:
	try:
		answer = middle_three_digits(x)
	except AssertionError as error:
		answer = error
	print("middle_three_digits(%s) returned: %r" % (x, answer))

middle_three_digits(123) returned: '123'
middle_three_digits(12345) returned: '234'
middle_three_digits(1234567) returned: '345'
middle_three_digits(987654321) returned: '654'
middle_three_digits(10001) returned: '000'
middle_three_digits(-10001) returned: '000'
middle_three_digits(-123) returned: '123'
middle_three_digits(-100) returned: '100'
middle_three_digits(100) returned: '100'
middle_three_digits(-12345) returned: '234'
middle_three_digits(1) returned: AssertionError('Need odd and >= 3 digits',)
middle_three_digits(2) returned: AssertionError('Need odd and >= 3 digits',)
middle_three_digits(-1) returned: AssertionError('Need odd and >= 3 digits',)
middle_three_digits(-10) returned: AssertionError('Need odd and >= 3 digits',)
middle_three_digits(2002) returned: AssertionError('Need odd and >= 3 digits',)
middle_three_digits(-2002) returned: AssertionError('Need odd and >= 3 digits',)
middle_three_digits(0) returned: AssertionError('Need odd and >= 3 digits',)
>>>


  [ 1 & not ]                       is even    (   n --> b )

  [ over size -
    space swap of
    swap join ]                     is justify ( $ n --> $ )

  [ abs number$
    dup size dup 3 < iff
      [ 2drop $ "too few digits" ]
      done
    dup even iff
      [ 2drop $ "even digit count" ]
      done
    dup 3 = iff
      drop done
    3 - 2 /
    tuck split nip
    swap negate split drop ]        is middle3 (   n --> $ )

   ' [ 123 12345 1234567
       987654321 10001 -10001
       -123 -100 100 -12345 1
       2 -1 -10 2002 -2002 0 ]

   witheach
     [ dup number$ 9 justify echo$
       say " --> "
       middle3 echo$ cr ]


#lang racket
(define (middle x)
  (cond
    [(negative? x) (middle (- x))]
    [(< x 100)     "error: number too small"]
    [else
     (define s (number->string x))
     (define l (string-length s))
     (cond [(even? l) "error: number has even length"]
           [else (define i (quotient l 2))
                 (substring s (- i 1) (+ i 2))])]))

(map middle (list 123 12345 1234567 987654321 10001 -10001 -123 -100 100 -12345))
(map middle (list 1 2 -1 -10 2002 -2002 0))


sub middle-three($n) {
    given $n.abs {
        when .chars < 3  { "$n is too short" }
        when .chars %% 2 { "$n has an even number of digits" }
        default          { "The three middle digits of $n are: ", .substr: (.chars - 3)/2, 3 }
    }
}

say middle-three($_) for <
    123 12345 1234567 987654321 10001 -10001 -123 -100 100 -12345
    1 2 -1 -10 2002 -2002 0
>;


/* REXX ***************************************************************
* 03.02.2013 Walter Pachl
* 19.04.2013 mid 3 is now a function returning the middle 3 digits
*            or an error indication
**********************************************************************/
sl='123 12345 1234567 987654321 10001 -10001 -123 -100 100 -12345',
   '2 -1 -10 2002 -2002 0 abc 1e3 -17e-3'
Do While sl<>''                        /* loop through test values   */
  Parse Var sl s sl                    /* pick next value            */
  Say left(s,12) '->' mid3(s)          /* test it                    */
  End
Exit

mid3: Procedure
Parse arg d                            /* take the argument          */
Select                                 /* first test for valid input */
  When datatype(d)<>'NUM'   Then  Return 'not a number'
  When pos('E',translate(d))>0 Then  Return 'not just digits'
  When length(abs(d))<3     Then  Return 'less than 3 digits'
  When length(abs(d))//2<>1 Then  Return 'not an odd number of digits'
  Otherwise Do                         /* input is ok                */
    dx=abs(d)                          /* get rid of optional sign   */
    ld=length(dx)                      /* length of digit string     */
    z=(ld-3)/2                         /* number of digits to cut    */
    res=substr(dx,z+1,3)               /* get middle 3 digits        */
    End
  End
  Return res


n = 1234567
middle(n)

func middle nr
     mnr = floor(len(string(nr))/2)
     lennr = len(string(nr))
     if lennr = 3 see "" + nr + nl
     but lennr < 3 see "Number must have at least three digits"
     but lennr%2=0 see "Number must have an odd number of digits"
     else cnr = substr(string(nr),mnr,3) see cnr + nl ok


def middle_three_digits(num)
  # minus sign doesn't factor into digit count,
  # and calling #abs acts as a duck-type assertion
  num = num.abs

  # convert to string and find length
  length = (str = num.to_s).length

  # check validity
  raise ArgumentError, "Number must have at least three digits" if length < 3
  raise ArgumentError, "Number must have an odd number of digits" if length.even?

  return str[length/2 - 1, 3].to_i
end


fn middle_three_digits(x: i32) -> Result<String, String> {
    let s: String = x.abs().to_string();
    let len = s.len();
    if len < 3 {
        Err("Too short".into())
    } else if len % 2 == 0 {
        Err("Even number of digits".into())
    } else {
        Ok(s[len/2 - 1 .. len/2 + 2].to_owned())
    }
}

fn print_result(x: i32) {
    print!("middle_three_digits({}) returned: ", x);
    match middle_three_digits(x) {
        Ok(s) => println!("Success, {}", s),
        Err(s) => println!("Failure, {}", s)
    }
}

fn main() {
    let passing = [123, 12345, 1234567, 987654321, 10001, -10001, -123, -100, 100, -12345];
    let failing = [1, 2, -1, -10, 2002, -2002, 0];
    for i in passing.iter() {
        print_result(*i);
    }
    for i in failing.iter() {
        print_result(*i);
    }
}


Educational Notes:
1) Array-style string manipulations (e.g. as = as[[1:]] ) always use bytes,
   not UTF-8 characters.  As digits and '-' are all ASCII, all is copacetic.
2) The task doesn't require 64-bit integer support, but I added it, dependant
   on whether the S-Lang library compile supports them, which it generally
   does.  [Main exception would be the current downloadable/installable MS-Win
   version of the Jed editor.]
3) S-Lang functions peel arguments off right-to-left, opposite of many
   languages.  To align the order with other solutions, I enclosed the
   parameters in a list.  One alternative would have been for m3() to call
   _stk_reverse(_NARGS), then pop each arg directly off the stack.  Or of
   course just list the numbers backwards.


/**
 * Optionally return the middle three digits of an integer.
 *
 * @example List(123,12345,-789,1234,12) flatMap (middleThree(_)), returns: List(123, 234, 789)
 */
def middleThree( s:Int ) : Option[Int] = s.abs.toString match {
  case v if v.length % 2 == 0   => None   // Middle three is undefined for even lengths
  case v if v.length < 3        => None
  case v                        =>
    val i = (v.length / 2) - 1
    Some( v.substring(i,i+3).toInt )
}

// A little test...
val intVals = List(123,12345,1234567,987654321,10001,-10001,-123,-100,100,-12345,1,2,-1,-10,2002,-2002,0)

intVals map (middleThree(_)) map {
  case None => "No middle three"
  case Some(v) => "%03d".format(v)  // Format the value, force leading zeroes
} mkString("\n")


$include "seed7_05.s7i";

const func string: middle3 (in integer: number) is func
  result
    var string: middle3 is "";
  begin
    middle3 := str(abs(number));
    if not odd(length(middle3)) or length(middle3) < 3 then
      middle3 := "error";
    else
      middle3 := middle3[succ((length(middle3) - 3) div 2) len 3];
    end if;
  end func;

const proc: main is func
  local
    var integer: number is 0;
    var string: mid3 is "";
  begin
    for number range [] (123, 12345, 1234567, 987654321, 10001, -10001, -123,
                         -100, 100, -12345, 1, 2, -1, -10, 2002, -2002, 0) do
      writeln(number <& ": " <& middle3(number));
    end for;
  end func;


set inputs to [123, 12345, 1234567, 987654321,
	10001, -10001, -123, -100, 100, -12345,
	1, 2, -1, -10, 2002, -2002, 0]

repeat with each num in inputs
	put num into output
	put middle3digits of num into character 15 of output -- will autofill with "."s
	put output
end repeat

to handle middle3digits of number
	put every occurrence of <digit> in number into digits
	if the number of items in digits is less than 3 then return "Error: too few digits"
	if the number of items in digits is an even number then return "Error: even number of digits"
	repeat while the number of items in digits is greater than 3
		delete the first item of digits
		delete the last item of digits
	end repeat
	return digits joined by empty
end middle3digits


func middle_three(n) {
  var l = n.len;
  if (l < 3) {
    "#{n} is too short"
  } elsif (l.is_even) {
    "#{n} has an even number of digits"
  } else {
    "The three middle digits of #{n} are: " + n.digits.ft(l-3 / 2, l/2 + 1).join
  }
}

var nums = %n(
    123 12345 1234567 987654321 10001 -10001 -123 -100 100 -12345
    1 2 -1 -10 2002 -2002 0
);
nums.each { say middle_three(_) };


;WITH DATA
     AS (SELECT CAST(ABS(NUMBER) AS NVARCHAR(MAX))      charNum,
                NUMBER,
                LEN(CAST(ABS(NUMBER) AS NVARCHAR(MAX))) LcharNum
         FROM   TABLE1)
SELECT CASE
         WHEN ( LCHARNUM >= 3
                AND LCHARNUM % 2 = 1 ) THEN SUBSTRING(CHARNUM, LCHARNUM / 2, 3)
         ELSE 'Error!'
       END    Output,
       NUMBER INPUT
FROM   DATA


var num:Int = \\enter your number here
if num<0{num = -num}
var numArray:[Int]=[]
while num>0{
	var temp:Int=num%10
	numArray.append(temp)
	num=num/10
}
var i:Int=numArray.count
if i<3||i%2==0{
	print("Invalid Input")
}
else{
	i=i/2
	print("\(numArray[i+1]),\(numArray[i]),\(numArray[i-1])")
}


proc middleThree n {
    if {$n < 0} {
	set n [expr {-$n}]
    }
    set idx [expr {[string length $n] - 2}]
    if {$idx % 2 == 0} {
	error "no middle three digits: input is of even length"
    }
    if {$idx < 1} {
	error "no middle three digits: insufficient digits"
    }
    set idx [expr {$idx / 2}]
    string range $n $idx [expr {$idx+2}]
}


function middle3digits
{
  typeset -i n="${1#-}"
  typeset -i l=${#n}
  if (( l < 3 )); then
    echo >&2 "$1 has less than 3 digits"
    return 1
  elif (( l % 2 == 0 )); then
    echo >&2 "$1 has an even number of digits"
    return 1
  else
    echo ${n:$((l/2-1)):3}
    return 0
  fi
}

# test
testdata=(123 12345 1234567 987654321 10001 -10001 -123 -100 100 -12345 1 2 -1
          -10 2002 -2002 0)
for n in ${testdata[@]}; do
  printf "%10d: " $n
  middle3digits "$n"
done


Option Explicit

Sub Main_Middle_three_digits()
Dim Numbers, i&
    Numbers = Array(123, 12345, 1234567, 987654321, 10001, -10001, -123, -100, _
    100, -12345, 1, 2, -1, -10, 2002, -2002, 0)
    For i = 0 To 16
        Debug.Print Numbers(i) & " Return : " & Middle3digits(CStr(Numbers(i)))
    Next
End Sub

Function Middle3digits(strNb As String) As String
    If Left(strNb, 1) = "-" Then strNb = Right(strNb, Len(strNb) - 1)
    If Len(strNb) < 3 Then
        Middle3digits = "Error ! Number of digits must be >= 3"
    ElseIf Len(strNb) Mod 2 = 0 Then
        Middle3digits = "Error ! Number of digits must be odd"
    Else
        Middle3digits = Mid(strNb, 1 + (Len(strNb) - 3) / 2, 3)
    End If
End Function


'http://rosettacode.org/wiki/Middle_three_digits

Function mid3n(n)
	'Remove the number's sign.
	n = CStr(Abs(n))
	If Len(n) < 3 Or Len(n) Mod 2 = 0 Then
		mid3n = "Invalid: Either the length of n < 3 or an even number."
	ElseIf Round(Len(n)/2) > Len(n)/2 Then
		mid3n = Mid(n,Round(Len(n)/2)-1,3)
	Else
		mid3n = Mid(n,Round(Len(n)/2),3)
	End If
End Function

'Calling the function.
arrn = Array(123,12345,1234567,987654321,10001,-10001,-123,-100,100,-12345,_
			1,2,-1,-10,2002,-2002,0)
For Each n In arrn
	WScript.StdOut.Write n & ": " & mid3n(n)
	WScript.StdOut.WriteLine
Next


do {
    #1 = Get_Num("Enter a number, or 0 to stop: ", STATLINE)
    Ins_Text("Input: ") Num_Ins(#1, COUNT, 10)
    Call("MIDDLE_3_DIGITS")
    Ins_Text("  Result: ") Reg_Ins(10) Ins_Newline
    Update()
} while (#1);
Return

// Find middle 3 digits of a number
//  in: #1 = numeric value
// out: @10 = the result, or error text
//
:MIDDLE_3_DIGITS:
Buf_Switch(Buf_Free)
Num_Ins(abs(#1), LEFT+NOCR)	// the input value as string
#2 = Cur_Col-1			// #2 = number of digits
if (#2 < 3) {
    Reg_Set(10, "Too few digits!")
} else {
    if ((#2 & 1) == 0) {
	Reg_Set(10, "Not odd number of digits!")
    } else {
	Goto_Pos((#2-3)/2)
	Reg_Copy_Block(10, Cur_Pos, Cur_Pos+3)
    }
}
Buf_Quit(OK)
Return


def (mid3 n)
  withs (digits  (with outstring  # itoa
                   (pr abs.n))
         max  len.digits
         mid  (int max/2))
    if (and odd?.max (max >= 3))
      (digits mid-1 mid+2)


import "/fmt" for Fmt

var middle3 = Fn.new { |n|
    if (n < 0) n = -n
    var s = "%(n)"
    var c = s.count
    if (c < 3) return "Minimum is 3 digits, only has %(c)."
    if (c%2 == 0) return "Number of digits must be odd, %(c) is even."
    if (c == 3) return s
    var d = (c - 3)/2
    return s[d..d+2]
}

var a = [123, 12345, 1234567, 987654321, 10001, -10001, -123, -100, 100, -12345,
    1, 2, -1, -10, 2002, -2002, 0]

for (e in a) {
    System.print("%(Fmt.s(9, e)) -> %(middle3.call(e))")
}


include c:\cxpl\stdlib;

func Mid3Digits(I);     \Return the middle three digits of I
int  I;
int  Len, Mid;
char S(10);
[ItoA(abs(I), S);
Len:= StrLen(S);
if Len<3 or (Len&1)=0 then return "Must be 3, 5, 7 or 9 digits";
Mid:= Len/2;
S:= S + Mid - 1;
S(2):= S(2) ! $80;      \terminate string
return S;               \WARNING: very temporary
];

int  Passing, Failing, X;
[Passing:= [123, 12345, 1234567, 987654321, 10001, -10001, -123, -100, 100, -12345];
 Failing:= [1, 2, -1, -10, 2002, -2002, 0];     \WARNING: nasty trick
for X:= 0 to 16 do
    [Text(0, "Middle three digits of ");  IntOut(0, Passing(X));
     Text(0, " returned: ");
     Text(0, Mid3Digits(Passing(X)));  CrLf(0);
    ];
]


F isProbablePrime(n, k = 10)
   I n < 2 | n % 2 == 0
      R n == 2

   V d = n - 1
   V s = 0
   L d % 2 == 0
      d I/= 2
      s++

   assert(2 ^ s * d == n - 1)

   L 0 .< k
      V a = random:(2 .< n)
      V x = pow(a, d, n)
      I x == 1 | x == n - 1
         L.continue
      L 0 .< s - 1
         x = pow(x, 2, n)
         I x == 1
            R 0B
         I x == n - 1
            L.break
      L.was_no_break
         R 0B

   R 1B

print((2..29).filter(x -> isProbablePrime(x)))


generic
   type Number is range <>;
package Miller_Rabin is

   type Result_Type is (Composite, Probably_Prime);

   function Is_Prime (N : Number; K : Positive := 10) return Result_Type;

end Miller_Rabin;


MODE LINT=LONG INT;
MODE LOOPINT = INT;

MODE POWMODSTRUCT = LINT;
PR READ "prelude/pow_mod.a68" PR;

PROC miller rabin = (LINT n, LOOPINT k)BOOL: (
    IF n<=3 THEN TRUE
    ELIF NOT ODD n THEN FALSE
    ELSE
        LINT d := n - 1;
        INT s := 0;
        WHILE NOT ODD d DO
            d := d OVER 2;
            s +:= 1
        OD;
        TO k DO
            LINT a := 2 + ENTIER (random*(n-3));
            LINT x :=  pow mod(a, d, n);
            IF x /= 1 THEN
                TO s DO
                    IF x = n-1 THEN done FI;
                    x := x*x %* n
                OD;
                else: IF x /= n-1 THEN return false FI;
                done: EMPTY
            FI
        OD;
        TRUE EXIT
        return false: FALSE
    FI
);

FOR i FROM 937 TO 1000 DO
  IF miller rabin(i, 10) THEN
    print((" ",whole(i,0)))
  FI
OD


MsgBox % MillerRabin(999983,10) ; 1
MsgBox % MillerRabin(999809,10) ; 1
MsgBox % MillerRabin(999727,10) ; 1
MsgBox % MillerRabin(52633,10)  ; 0
MsgBox % MillerRabin(60787,10)  ; 0
MsgBox % MillerRabin(999999,10) ; 0
MsgBox % MillerRabin(999995,10) ; 0
MsgBox % MillerRabin(999991,10) ; 0

MillerRabin(n,k) { ; 0: composite, 1: probable prime (n < 2**31)
   d := n-1, s := 0
   While !(d&1)
      d>>=1, s++

   Loop %k% {
      Random a, 2, n-2 ; if n < 4,759,123,141, it is enough to test a = 2, 7, and 61.
      x := PowMod(a,d,n)
      If (x=1 || x=n-1)
         Continue
      Cont := 0
      Loop % s-1 {
         x := PowMod(x,2,n)
         If (x = 1)
            Return 0
         If (x = n-1) {
            Cont = 1
            Break
         }
      }
      IfEqual Cont,1, Continue
      Return 0
   }
   Return 1
}

PowMod(x,n,m) { ; x**n mod m
   y := 1, i := n, z := x
   While i>0
      y := i&1 ? mod(y*z,m) : y, z := mod(z*z,m), i >>= 1
   Return y
}


seed = 1   /* seed of the random number generator */
scale = 0

/* Random number from 0 to 32767. */
define rand() {
  /* Cheap formula (from POSIX) for random numbers of low quality. */
  seed = (seed * 1103515245 + 12345) % 4294967296
  return ((seed / 65536) % 32768)
}

/* Random number in range [from, to]. */
define rangerand(from, to) {
  auto b, h, i, m, n, r

  m = to - from + 1
  h = length(m) / 2 + 1  /* want h iterations of rand() % 100 */
  b = 100 ^ h % m        /* want n >= b */
  while (1) {
    n = 0                /* pick n in range [b, 100 ^ h) */
    for (i = h; i > 0; i--) {
      r = rand()
      while (r < 68) { r = rand(); }  /* loop if the modulo bias */
      n = (n * 100) + (r % 100)       /* append 2 digits to n */
    }
    if (n >= b) { break; }  /* break unless the modulo bias */
  }
  return (from + (n % m))
}

/* n is probably prime? */
define miller_rabin_test(n, k) {
  auto d, r, a, x, s

  if (n <= 3) { return (1); }
  if ((n % 2) == 0) { return (0); }

  /* find s and d so that d * 2^s = n - 1 */
  d = n - 1
  s = 0
  while((d % 2) == 0) {
     d /= 2
     s += 1
  }

  while (k-- > 0) {
    a = rangerand(2, n - 2)
    x = (a ^ d) % n
    if (x != 1) {
      for (r = 0; r < s; r++) {
        if (x == (n - 1)) { break; }
        x = (x * x) % n
      }
      if (x != (n - 1)) {
        return (0)
      }
    }
  }
  return (1)
}

for (i = 1; i < 1000; i++) {
  if (miller_rabin_test(i, 10) == 1) {
    i
  }
}
quit


_modMul ← { n _𝕣: n|× }
MillerRabin ← {  𝕊n: 10𝕊n ; iter 𝕊 n: !2|n
  # n = 1 + d×2⋆s
  s ← 0 {𝕨 2⊸|◶⟨+⟜1𝕊2⌊∘÷˜⊢,⊣⟩ 𝕩} n-1
  d ← (n-1) ÷ 2⋆s

  # Arithmetic mod n
  Mul ← n _modMul
  Pow ← Mul{𝔽´𝔽˜⍟(/2|⌊∘÷⟜2⍟(↕1+·⌊2⋆⁼⊢)𝕩)𝕨}

  # Miller-Rabin test
  MR ← {
       1 =𝕩 ? 𝕨≠s ;
    (n-1)=𝕩 ? 0   ;
        𝕨≤1 ? 1   ;
    (𝕨-1) 𝕊 Mul˜𝕩
  }
  C ← { 𝕊a: s MR a Pow d }  # Is composite
  {0:1; C •rand.Range⌾(-⟜2) n ? 0; 𝕊𝕩-1} iter
}


#ifndef _MILLER_RABIN_H_
#define _MILLER_RABIN_H
#include <gmp.h>
bool miller_rabin_test(mpz_t n, int j);
#endif


public static class RabinMiller
{
    public static bool IsPrime(int n, int k)
    {
        if ((n < 2) || (n % 2 == 0)) return (n == 2);

        int s = n - 1;
        while (s % 2 == 0)  s >>= 1;

        Random r = new Random();
        for (int i = 0; i < k; i++)
        {
            int a = r.Next(n - 1) + 1;
            int temp = s;
            long mod = 1;
            for (int j = 0; j < temp; ++j)  mod = (mod * a) % n;
            while (temp != n - 1 && mod != 1 && mod != n - 1)
            {
                mod = (mod * mod) % n;
                temp *= 2;
            }

            if (mod != n - 1 && temp % 2 == 0) return false;
        }
        return true;
    }
}


(ns test-p.core
  (:require [clojure.math.numeric-tower :as math])
  (:require [clojure.set :as set]))

(def WITNESSLOOP "witness")
(def COMPOSITE "composite")

(defn m* [p q m]
  " Computes (p*q) mod m "
  (mod (*' p q) m))

(defn power
  "modular exponentiation (i.e. b^e mod m"
  [b e m]
  (loop [b b, e e, x 1]
    (if (zero? e)
      x
      (if (even? e) (recur (m* b b m) (quot e 2) x)
                    (recur (m* b b m) (quot e 2) (m* b x m))))))

; Sequence of random numbers to use in the test
(defn rand-num [n]
  " random number between 2 and n-2 "
  (bigint (math/floor (+' 2 (*' (- n 4) (rand))))))

; Unique set of random numbers
(defn unique-random-numbers [n k]
  " k unique random numbers between 2 and n-2 "
  (loop [a-set #{}]
    (cond
      (>= (count a-set) k) a-set
      :else (recur (conj a-set (rand-num n))))))

(defn find-d-s [n]
  " write n − 1 as 2s·d with d odd "
  (loop [d (dec n), s 0]
    (if (odd? d)
      [d s]
      (recur (quot d 2) (inc s)))))

(defn random-test
  ([n] (random-test n (min 1000 (bigint (/ n 2)))))
  ([n k]
  " Random version of primality test"
  (let [[d s] (find-d-s n)
        ; Individual Primality Test
        single-test (fn [a s]
                      (let [z (power a d n)]
                       (if (some #{z} [1 (dec n)])
                         WITNESSLOOP
                         (loop [x (power z 2 n), r s]
                           (cond
                             (= x 1) COMPOSITE
                             (= x (dec n)) WITNESSLOOP
                             (= r 0) COMPOSITE
                             :else (recur (power x 2 n) (dec r)))))))]
    ; Apply Test
    ;(not-any? #(= COMPOSITE (local-test % s))
    ;          (unique-random-numbers n k))))
    (not-any? #(= COMPOSITE (single-test % s)) (unique-random-numbers n k)))))

;; Testing
(println "Primes beteen 900-1000:")
(doseq [q (range 900 1000)
        :when (random-test q)]
  (print " " q))
(println)
(println "Is Prime?" 4547337172376300111955330758342147474062293202868155909489 (random-test 4547337172376300111955330758342147474062293202868155909489))
(println "Is Prime?" 4547337172376300111955330758342147474062293202868155909393 (random-test 4547337172376300111955330758342147474062293202868155909393))
(println "Is Prime?" 643808006803554439230129854961492699151386107534013432918073439524138264842370630061369715394739134090922937332590384720397133335969549256322620979036686633213903952966175107096769180017646161851573147596390153
         (random-test 643808006803554439230129854961492699151386107534013432918073439524138264842370630061369715394739134090922937332590384720397133335969549256322620979036686633213903952966175107096769180017646161851573147596390153))

(println "Is Prime?" 743808006803554439230129854961492699151386107534013432918073439524138264842370630061369715394739134090922937332590384720397133335969549256322620979036686633213903952966175107096769180017646161851573147596390153
         (random-test 743808006803554439230129854961492699151386107534013432918073439524138264842370630061369715394739134090922937332590384720397133335969549256322620979036686633213903952966175107096769180017646161851573147596390153))


100 PRINT CHR$(147); CHR$(18); "****  MILLER-RABIN PRIMALITY TEST   ****": PRINT
110 INPUT "NUMBER TO TEST"; N$
120 N = VAL(N$): IF N < 2 THEN 110
130 IF 0 = (N AND 1) THEN PRINT "(EVEN)": GOTO 380
140 INPUT "ITERATIONS"; K$
150 K = VAL(K$): IF K < 1 THEN 140
160 PRINT
170 DEF FNMD(M) = M - N * INT(M / N)
180 D = N - 1
190 S = 0
200 D = D / 2: S = S + 1
210 IF 0 = (D AND 1) THEN 200
220 P = 1
230 FOR I = 1 TO K
240 : A = INT(RND(.) * (N - 2)) + 2
250 : X = 1
260 : FOR J = 1 TO D
270 :   X = FNMD(X * A)
280 : NEXT J
290 : IF (X = 1) OR (X = (N - 1)) THEN 360
300 : FOR J = 1 TO S - 1
310 :   X = FNMD(X * X)
320 :   IF X = 1 THEN P = 0: GOTO 370
330 :   IF X = N - 1 THEN 360
340 : NEXT J
350 : P = 0: GOTO 370
360 NEXT I
370 P = P * (1 - 1 / (4 * K))
380 IF P THEN PRINT "PROBABLY PRIME ( P >="; P; ")": END
390 PRINT "COMPOSITE."


(defun factor-out (number divisor)
  "Return two values R and E such that NUMBER = DIVISOR^E * R,
  and R is not divisible by DIVISOR."
  (do ((e 0 (1+ e))
       (r number (/ r divisor)))
      ((/= (mod r divisor) 0) (values r e))))

(defun mult-mod (x y modulus) (mod (* x y) modulus))

(defun expt-mod (base exponent modulus)
  "Fast modular exponentiation by repeated squaring."
  (labels ((expt-mod-iter (b e p)
             (cond ((= e 0) p)
                   ((evenp e)
                    (expt-mod-iter (mult-mod b b modulus)
                                   (/ e 2)
                                   p))
                   (t
                    (expt-mod-iter b
                                   (1- e)
                                   (mult-mod b p modulus))))))
    (expt-mod-iter base exponent 1)))

(defun random-in-range (lower upper)
  "Return a random integer from the range [lower..upper]."
  (+ lower (random (+ (- upper lower) 1))))

(defun miller-rabin-test (n k)
  "Test N for primality by performing the Miller-Rabin test K times.
  Return NIL if N is composite, and T if N is probably prime."
  (cond ((= n 1)   nil)
        ((< n 4)     t)
        ((evenp n) nil)
        (t
         (multiple-value-bind (d s) (factor-out (- n 1) 2)
           (labels ((strong-liar? (a)
                      (let ((x (expt-mod a d n)))
                        (or (= x 1)
                            (loop repeat s
                                  for y = x then (mult-mod y y n)
                                  thereis (= y (- n 1)))))))
             (loop repeat k
                   always (strong-liar? (random-in-range 2 (- n 2)))))))))


require "big"

module Primes
  module MillerRabin

    def prime?(k = 15)             # increase k for more confidence
      neg_one_mod = d = self - 1
      s = 0
      while d.even?; d >>= 1; s += 1 end  # d is odd after s shifts
      k.times do
        b = 2 + rand(self - 4)     # random witness base b
        y = powmod(b, d, self)     # y = (b**d) mod self
        next if y == 1 || y == neg_one_mod
        (s - 1).times do
          y = (y * y) % self       # y = (y**2) mod self
          return false if y == 1
          break if y == neg_one_mod
        end
        return false if y != neg_one_mod
      end
      true                         # prime (with high probability)
    end

    # Compute b**e mod m
    private def powmod(b, e, m)
      r, b = 1, b.to_big_i
      while e > 0
        r = (b * r) % m if e.odd?
        b = (b * b) % m
        e >>= 1
      end
      r
    end
  end
end

struct Int; include Primes::MillerRabin end

puts 341521.prime?(20) # => true
puts 341531.prime?     # => false


import std.random;

bool isProbablePrime(in ulong n, in uint k=10) /*nothrow*/ @safe /*@nogc*/ {
    static ulong modPow(ulong b, ulong e, in ulong m)
    pure nothrow @safe @nogc {
        ulong result = 1;
        while (e > 0) {
            if ((e & 1) == 1)
                result = (result * b) % m;
            b = (b ^^ 2) % m;
            e >>= 1;
        }
        return result;
    }

    if (n < 2 || n % 2 == 0)
        return n == 2;

    ulong d = n - 1;
    ulong s = 0;
    while (d % 2 == 0) {
        d /= 2;
        s++;
    }
    assert(2 ^^ s * d == n - 1);

    outer:
    foreach (immutable _; 0 .. k) {
        immutable ulong a = uniform(2, n);
        ulong x = modPow(a, d, n);
        if (x == 1 || x == n - 1)
            continue;
        foreach (immutable __; 1 .. s) {
            x = modPow(x, 2, n);
            if (x == 1)
                return false;
            if (x == n - 1)
                continue outer;
        }
        return false;
    }

    return true;
}

void main() { // Demo code.
    import std.stdio, std.range, std.algorithm;

    iota(2, 30).filter!isProbablePrime.writeln;
}


def millerRabinPrimalityTest(n :(int > 0), k :int, random) :boolean {
  if (n <=> 2 || n <=> 3) { return true }
  if (n <=> 1 || n %% 2 <=> 0) { return false }
  var d := n - 1
  var s := 0
  while (d %% 2 <=> 0) {
    d //= 2
    s += 1
  }
  for _ in 1..k {
     def nextTrial := __continue
     def a := random.nextInt(n - 3) + 2     # [2, n - 2] = [0, n - 4] + 2 = [0, n - 3) + 2
     var x := a**d %% n                     # Note: Will do optimized modular exponentiation
     if (x <=> 1 || x <=> n - 1) { nextTrial() }
     for _ in 1 .. (s - 1) {
        x := x**2 %% n
        if (x <=> 1) { return false }
        if (x <=> n - 1) { nextTrial() }
     }
     return false
  }
  return true
}


(lib 'bigint)

;; output : #t if n probably prime
(define (miller-rabin n (k 7) (composite #f)(x))
(define d (1- n))
(define s 0)
(define a 0)
(while (even? d)
	(set! s (1+ s))
	(set! d (quotient d 2)))

(for [(i k)]
	(set! a (+ 2 (random (- n 3))))
	(set! x (powmod a d n))
	#:continue (or (= x 1) (= x (1- n)))
	(set! composite
	(for [(r (in-range 1 s))]
		(set! x (powmod x 2 n))
		#:break (= x 1) => #t
		#:break (= x (1- n)) =>  #f
		#t
		))
	 #:break composite => #f )
 (not composite))

;; output
(miller-rabin #101)
    → #t
(miller-rabin #111)
    → #f
(define big-prime (random-prime 1e+100))
3461396142610375479080862553800503306376298093021233334170610435506057862777898396429
6627816219192601527
(miller-rabin big-prime)
    → #t
(miller-rabin (1+ (factorial 100)))
    → #f
(prime? (1+ (factorial 100))) ;; native
    → #f


defmodule Prime do
  use Application
  alias :math, as: Math
  alias :rand, as: Rand

  def start( _type, _args ) do
    primes = 5..1000
      |> Enum.filter( fn( x ) -> (rem x, 2) == 1 end )
      |> Enum.filter( fn( x ) -> miller_rabin?( x, 10) == True end )
    IO.inspect( primes, label: "Primes: ", limit: :infinity )

    { :ok, self() }
  end

  def modular_exp( x, y, mod ) do
     with [ _ | bits ] = Integer.digits( y, 2 ) do
          Enum.reduce bits, x, fn( bit, acc ) -> acc * acc |> ( &( if bit == 1, do: &1 * x, else: &1 ) ).() |> rem( mod ) end
     end
  end

  def miller_rabin( d, s ) when rem( d, 2 ) == 0, do: { s, d }
  def miller_rabin( d, s ), do: miller_rabin( div( d, 2 ), s + 1 )

  def miller_rabin?( n, g ) do
       { s, d } = miller_rabin( n - 1, 0 )
       miller_rabin( n, g, s, d )
  end

  def miller_rabin( n, 0, _, _ ), do: True
  def miller_rabin( n, g, s, d ) do
    a = 1 + Rand.uniform( n - 3 )
    x = modular_exp( a, d, n )
    if x == 1 or x == n - 1 do
      miller_rabin( n, g - 1, s, d )
    else
      if miller_rabin( n, x, s - 1) == True, do: miller_rabin( n, g - 1, s, d ), else: False
    end
  end

  def miller_rabin( n, x, r ) when r <= 0, do: False
  def miller_rabin( n, x, r ) do
    x = modular_exp( x, 2, n )
    unless x == 1 do
      unless x == n - 1, do: miller_rabin( n, x, r - 1 ), else: True
    else
      False
    end
  end
end


-module(miller_rabin).

-export([is_prime/1, power/2]).

is_prime(1) -> false;
is_prime(2) -> true;
is_prime(3) -> true;
is_prime(N) when N > 3, ((N rem 2) == 0) -> false;
is_prime(N) when ((N rem 2) ==1), N < 341550071728321 ->
 			is_mr_prime(N, proving_bases(N));
is_prime(N) when ((N rem 2) == 1) ->
			is_mr_prime(N, random_bases(N, 100)).

proving_bases(N) when N < 1373653 ->
	[2, 3];
proving_bases(N) when N < 9080191 ->
    [31, 73];
proving_bases(N) when N < 25326001 ->
	[2, 3, 5];
proving_bases(N) when N < 3215031751 ->
	[2, 3, 5, 7];
proving_bases(N) when N < 4759123141 ->
    [2, 7, 61];
proving_bases(N) when N < 1122004669633 ->
	[2, 13, 23, 1662803];
proving_bases(N) when N < 2152302898747 ->
	[2, 3, 5, 7, 11];
proving_bases(N) when N < 3474749660383 ->
    [2, 3, 5, 7, 11, 13];
proving_bases(N) when N < 341550071728321 ->
    [2, 3, 5, 7, 11, 13, 17].

is_mr_prime(N, As) when N>2, N rem 2 == 1 ->
    {D, S} = find_ds(N),
         %% this is a test for compositeness; the two case patterns disprove
         %%    compositeness.
    not lists:any(fun(A) ->
                          case mr_series(N, A, D, S) of
                              [1|_] -> false;                     % first elem of list = 1
                              L     -> not lists:member(N-1, L)   % some elem of list = N-1
                          end
                  end,
                  As).

find_ds(N) ->
    find_ds(N-1, 0).

find_ds(D, S) ->
    case D rem 2 == 0 of
        true ->
            find_ds(D div 2, S+1);
        false ->
            {D, S}
    end.

mr_series(N, A, D, S) when N rem 2 == 1 ->
    Js = lists:seq(0, S),
    lists:map(fun(J) -> pow_mod(A, power(2, J)*D, N) end, Js).

pow_mod(B, E, M) ->
    case E of
        0 -> 1;
        _ -> case ((E rem 2) == 0) of
                 true  -> (power(pow_mod(B, (E div 2), M), 2)) rem M;
                 false -> (B*pow_mod(B, E-1, M)) rem M
             end
    end.

random_bases(N, K) ->
    [basis(N) || _ <- lists:seq(1, K)].

basis(N) when N>2 ->
    1 + random:uniform(N-3).  % random:uniform returns a single random number in range 1 -> N-3, to which is added 1, shifting the range to 2 -> N-2

power(B, E) ->
    power(B, E, 1).

power(_, 0, Acc) ->
    Acc;
power(B, E, Acc) ->
    power(B, E - 1, B * Acc).


\ modular multiplication and exponentiation
\
: 3rd  s" 2 pick" evaluate ; immediate

: mod*  ( a b m -- a*b {mod m} )
    >r um* r> ud/mod 2drop ;

: mod^  ( x n m -- x^n {mod m} )
    >r 1 swap
    begin ?dup while
        dup 1 and 1 =
        if
            swap 3rd [email protected] mod* swap 1-
        then dup 0>
        if
            rot dup [email protected] mod* -rot 2/
        then
    repeat nip rdrop ;

\ small divisor check: true => possibly prime; false => definitely not prime.
\
31 constant π-128
create maybe-prime?
      2 c,  3 c,  5 c,  7 c, 11 c,  13 c,  17 c,  19 c,  23 c,  29 c,
     31 c, 37 c, 41 c, 43 c, 47 c,  53 c,  59 c,  61 c,  67 c,  71 c,
     73 c, 79 c, 83 c, 89 c, 97 c, 101 c, 103 c, 107 c, 109 c, 113 c,
    127 c,
does>
    true -rot
    π-128 bounds do
        i [email protected] dup * over > if leave then
        dup i [email protected] mod 0= if 2drop false unloop exit then
    loop drop ;

\ actual Miller-Rabin test
\
: factor-2s  ( n -- s d )
    0 swap
    begin dup 1 and 0= while
        swap 1+  swap 2/
    repeat ;

: fermat-square-test ( n m s -- ? ) \ perform n = n^2 (mod m), s-1 times
    1- 0 ?do
        2dup - -1 =
        if   leave
        then >r dup [email protected] mod* r>
    loop
    - -1 = ;

: strong-fermat-pseudoprime? ( n a -- ? )
    over >r \ keep the modulus on the return stack
    >r 1- factor-2s r>  \ -- s d a
    swap [email protected] mod^        \ s d a -- s, a^d (mod n)
    dup 1 =             \ a^d == 1 (mod n) => Fermat pseudoprime
    if   2drop rdrop true
    else r> rot fermat-square-test
    then ;

4.759.123.141 drop constant mr-det-3   \ Deterministic threshold; 3 bases

create small-prime-bases 2 , 7 , 61 ,  \ deterministic up to mr-det-3
create large-prime-bases 2 , 325 , 9375 , 28178 , 450775 , 9780504 , 1795265022 , \ known to be deterministic for 64 bit integers.

: miler-rabin-bases ( n -- addr n )
    mr-det-3 <
    if    small-prime-bases 3
    else  large-prime-bases 7
    then ;

: miller-rabin-primality-test ( n -- f )
    dup miler-rabin-bases cells bounds do
        dup i @ strong-fermat-pseudoprime? invert
        if drop false unloop exit then
    cell +loop drop true ;

: prime? ( n -- f )
    dup 2 <
    if drop false
    else
        dup maybe-prime?
        if dup [ 127 dup * 1+ ] literal <
            if   drop true
            else miller-rabin-primality-test
            then
        else drop false
        then
    then ;


  module Miller_Rabin
  use PrimeDecompose
  implicit none

  integer, parameter :: max_decompose = 100

  private :: int_rrand, max_decompose

contains

  function int_rrand(from, to)
    integer(huge) :: int_rrand
    integer(huge), intent(in) :: from, to

    real :: o
    call random_number(o)
    int_rrand = floor(from + o * real(max(from,to) - min(from, to)))
  end function int_rrand

  function miller_rabin_test(n, k) result(res)
    logical :: res
    integer(huge), intent(in) :: n
    integer, intent(in) :: k

    integer(huge), dimension(max_decompose) :: f
    integer(huge)                     :: s, d, i, a, x, r

    res = .true.
    f = 0

    if ( (n <= 2) .and. (n > 0) ) return
    if ( mod(n, 2) == 0 ) then
       res = .false.
       return
    end if

    call find_factors(n-1, f)
    s = count(f == 2)
    d = (n-1) / (2 ** s)
    loop:  do i = 1, k
       a = int_rrand(2_huge, n-2)
       x = mod(a ** d, n)

       if ( x == 1 ) cycle
       do r = 0, s-1
          if ( x == ( n - 1 ) ) cycle loop
          x = mod(x*x, n)
       end do
       if ( x == (n-1) ) cycle
       res = .false.
       return
    end do loop
    res = .true.
  end function miller_rabin_test

end module Miller_Rabin


' version 29-11-2016
' compile with: fbc -s console

' TRUE/FALSE are built-in constants since FreeBASIC 1.04
' But we have to define them for older versions.
#Ifndef TRUE
    #Define FALSE 0
    #Define TRUE Not FALSE
#EndIf

Function mul_mod(a As ULongInt, b As ULongInt, modulus As ULongInt) As ULongInt
    ' returns a * b mod modulus
    Dim As ULongInt x, y = a ' a mod modulus, but a is already smaller then modulus

    While b > 0
        If (b And 1) = 1 Then
            x = (x + y) Mod modulus
        End If
        y = (y Shl 1) Mod modulus
        b = b Shr 1
    Wend

    Return x

End Function

Function pow_mod(b As ULongInt, power As ULongInt, modulus As ULongInt) As ULongInt
    ' returns b ^ power mod modulus
    Dim As ULongInt x = 1

    While power > 0
        If (power And 1) = 1 Then
            ' x = (x * b) Mod modulus
            x = mul_mod(x, b, modulus)
        End If
        ' b = (b * b) Mod modulus
        b = mul_mod(b, b, modulus)
        power = power Shr 1
    Wend

    Return x

End Function

Function miller_rabin_test(n As ULongInt, k As Integer) As Byte

    If n > 9223372036854775808ull Then ' limit 2^63, pow_mod/mul_mod can't handle bigger numbers
        Print "number is to big, program will end"
        Sleep
        End
    End If

    ' 2 is a prime, if n is smaller then 2 or n is even then n = composite
    If n = 2 Then Return TRUE
    If (n < 2) OrElse ((n And 1) = 0) Then Return FALSE

    Dim As ULongInt a, x, n_one = n - 1, d = n_one
    Dim As UInteger s

    While (d And 1) = 0
        d = d Shr 1
        s = s + 1
    Wend

    While k > 0
        k = k - 1
        a = Int(Rnd * (n -2)) +2          ' 2 <= a < n
        x = pow_mod(a, d, n)
        If (x = 1) Or (x = n_one) Then Continue While
        For r As Integer = 1 To s -1
            x = pow_mod(x, 2, n)
            If x = 1 Then Return FALSE
            If x = n_one Then Continue While
        Next
        If x <> n_one Then Return FALSE
    Wend
    Return TRUE

End Function
' ------=< MAIN >=------

Randomize Timer

Dim As Integer total
Dim As ULongInt y, limit = 2^63-1

For y = limit - 1000 To limit
    If miller_rabin_test(y, 5) = TRUE Then
        total = total + 1
        Print y,
    End If
Next

Print : Print
Print total; " primes between "; limit - 1000; " and "; y -1

' empty keyboard buffer
While Inkey <> "" : Wend
Print : Print "hit any key to end program"
Sleep
End


import util.rnd

def isProbablyPrimeMillerRabin( n, k ) =
  d = n - 1
  s = 0

  while 2|d
    s++
    d /= 2

  repeat k
    a = rnd( 2, n )
    x = a^d mod n

    if x == 1 or x == n - 1 then continue

    repeat s - 1
      x = x^2 mod n

      if x == 1 then return false

      if x == n - 1 then break
    else
      return false

  true

for i <- 3..100
  if isProbablyPrimeMillerRabin( i, 5 )
    println( i )


package main

import "log"

func main() {
    // max uint32 is not prime
    c := uint32(1<<32 - 1)
    // a few primes near the top of the range.  source: prime pages.
    for _, p := range []uint32{1<<32 - 5, 1<<32 - 17, 1<<32 - 65, 1<<32 - 99} {
        for ; c > p; c-- {
            if prime(c) {
                log.Fatalf("prime(%d) returned true", c)
            }
        }
        if !prime(p) {
            log.Fatalf("prime(%d) returned false", p)
        }
        c--
    }
}

func prime(n uint32) bool {
    // bases of 2, 7, 61 are sufficient to cover 2^32
    switch n {
    case 0, 1:
        return false
    case 2, 7, 61:
        return true
    }
    // compute s, d where 2^s * d = n-1
    nm1 := n - 1
    d := nm1
    s := 0
    for d&1 == 0 {
        d >>= 1
        s++
    }
    n64 := uint64(n)
    for _, a := range []uint32{2, 7, 61} {
        // compute x := a^d % n
        x := uint64(1)
        p := uint64(a)
        for dr := d; dr > 0; dr >>= 1 {
            if dr&1 != 0 {
                x = x * p % n64
            }
            p = p * p % n64
        }
        if x == 1 || uint32(x) == nm1 {
            continue
        }
        for r := 1; ; r++ {
            if r >= s {
                return false
            }
            x = x * x % n64
            if x == 1 {
                return false
            }
            if uint32(x) == nm1 {
                break
            }
        }
    }
    return true
}


module Primes where

import System.Random
import System.IO.Unsafe

-- Miller-Rabin wrapped up as an (almost deterministic) pure function
isPrime :: Integer -> Bool
isPrime n = unsafePerformIO (isMillerRabinPrime 100 n)

isMillerRabinPrime :: Int -> Integer -> IO Bool
isMillerRabinPrime k n
   | even n    = return (n==2)
   | n < 100   = return (n `elem` primesTo100)
   | otherwise = do ws <- witnesses k n
                    return $ and [test n (pred n) evens (head odds) a | a <- ws]
  where
    (evens,odds) = span even (iterate (`div` 2) (pred n))

test :: Integral nat => nat -> nat -> [nat] -> nat -> nat -> Bool
test n n_1 evens d a = x `elem` [1,n_1] || n_1 `elem` powers
  where
    x = powerMod n a d
    powers = map (powerMod n a) evens

witnesses :: (Num a, Ord a, Random a) => Int -> a -> IO [a]
witnesses k n
  | n < 9080191         = return [31,73]
  | n < 4759123141      = return [2,7,61]
  | n < 3474749660383   = return [2,3,5,7,11,13]
  | n < 341550071728321 = return [2,3,5,7,11,13,17]
  | otherwise           = do g <- newStdGen
                             return $ take k (randomRs (2,n-1) g)

primesTo100 :: [Integer]
primesTo100 = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]

-- powerMod m x n = x^n `mod` m
powerMod :: Integral nat => nat -> nat -> nat -> nat
powerMod m x n  = f (n - 1) x x `rem` m
  where
  f d a y = if d==0 then y else g d a y
  g i b y | even i    = g (i `quot` 2) (b*b `rem` m) y
          | otherwise = f (i-1) b (b*y `rem` m)


procedure main(A)
   every n := !A do write(n," is ",(mrp(n,5),"probably prime")|"composite")
end

procedure mrp(n, k)
    if n = 2 then return ""
    if n%2 = 0 then fail
    nm1 := decompose(n-1)
    s := nm1[1]
    d := nm1[2]
    every !k do {
        a := ?(n-2)+1
        x := (a^d)%n
        if x = (1|(n-1)) then next
        every !(s-1) do {
            x := (x*x)%n
            if x = 1 then fail
            if x = (n-1) then break next
            }
        fail
        }
    return ""
end

procedure decompose(nm1)
    s := 1
    d := nm1
    while d%2 = 0 do {
        d /:= 2
        s +:= 1
        }
    return [s,d]
end


import java.math.BigInteger;

public class MillerRabinPrimalityTest {
  public static void main(String[] args) {
    BigInteger n = new BigInteger(args[0]);
    int certainty = Integer.parseInt(args[1]);
    System.out.println(n.toString() + " is " + (n.isProbablePrime(certainty) ? "probably prime" : "composite"));
  }
}


function probablyPrime(n) {
  if (n === 2 || n === 3) return true
  if (n % 2 === 0 || n < 2) return false

  // Write (n - 1) as 2^s * d
  var s = 0,
    d = n - 1
  while ((d & 1) == 0) {
    d >>= 1
    ++s
  }

  let base = 2
  var x = Math.pow(base, d) % n

  if (x == 1 || x == n - 1) return true

  for (var i = 1; i <= s; i++) {
    x = (x * x) % n

    if (x === n - 1) return true
  }
  return false
}


// version 1.1.2

import java.math.BigInteger
import java.util.Random

val bigTwo = BigInteger.valueOf(2L)

fun isProbablyPrime(n: BigInteger, k: Int): Boolean {
    require (n > bigTwo && n % bigTwo == BigInteger.ONE) { "Must be odd and greater than 2" }
    var s = 0
    val nn = n - BigInteger.ONE
    var d: BigInteger
    do {
        s++
        d = nn.shiftRight(s)
    }
    while (d % bigTwo == BigInteger.ZERO)

    val rand = Random()
    loop@ for (i in 1..k) {
        var a: BigInteger
        do {
            a = BigInteger(n.bitLength(), rand)
        }
        while(a < bigTwo || a > nn) // make sure it's in the interval [2, n - 1]

        var x = a.modPow(d, n)
        if (x == BigInteger.ONE || x == nn) continue
        for (r in 1 until s) {
            x =  (x * x) % n
            if (x == BigInteger.ONE) return false
            if (x == nn) break@loop
        }
        return false
    }
    return true
}

fun main(args: Array<String>) {
    val k = 20 // say
    // obtain all primes up to 100
    println("The following numbers less than 100 are prime:")
    for (i in 3..99 step 2)
        if (isProbablyPrime(BigInteger.valueOf(i.toLong()), k)) print("$i ")
    println("\n")
    // check if some big numbers are probably prime
    val bia = arrayOf(
        BigInteger("4547337172376300111955330758342147474062293202868155909489"),
        BigInteger("4547337172376300111955330758342147474062293202868155909393")
    )
    for (bi in bia)
        println("$bi is ${if (isProbablyPrime(bi, k)) "probably prime" else "composite"}")
}


 function MRIsPrime(n, k)
  -- If n is prime, returns true (without fail).
  -- If n is not prime, then returns false with probability ≥ 4^(-k), true otherwise.
  -- First, deal with 1 and multiples of 2.
  if n == 1 then
    return false
  elseif n == 2 then
    return true
  elseif n%2 == 0 then
    return false
  end
  -- Now n is odd and greater than 1.
  -- Find the unique expression n = 1 + t*2^h for n, where t is odd and h≥1.
  t = (n-1)/2
  h = 1
  while t%2 == 0 do
    t = t/2
    h = h + 1
  end
  for i = 1, k do
    -- Generate a random integer between 1 and n-1 inclusive.
    a = math.random(n-1)
    -- Test whether a is an element of the set L, and return false if not.
    if not IsInL(n, a, t, h) then
      return false
    end
  end
  -- All generated a were in the set L; thus with high probability, n is prime.
  return true
end

function IsInL(n, a, t, h)
  local b = PowerMod(a, t, n)
  if b == 1 then
    return true
  end
  for j = 0, h-1 do
    if b == n-1 then
      return true
    elseif b == 1 then
      return false
    end
    b = (b^2)%n
  end
  return false
end

function PowerMod(x, y, m)
  -- Computes x^y mod m.
  local z = 1
  while y > 0 do
    if y%2 == 0 then
      x, y, z = (x^2)%m, y//2, z
    else
      x, y, z = (x^2)%m, y//2, (x*z)%m
    end
  end
  return z
end


MillerRabin[n_,k_]:=Module[{d=n-1,s=0,test=True},While[Mod[d,2]==0 ,d/=2 ;s++]
Do[
  a=RandomInteger[{2,n-1}]; x=PowerMod[a,d,n];
  If[x!=1,
   For[ r = 0, r < s, r++, If[x==n-1, Continue[]]; x = Mod[x*x, n]; ];
   If[ x != n-1, test=False ];
  ];
,{k}];
Print[test] ]


/* Miller-Rabin algorithm is builtin, see function primep. Here is another implementation */

/* find highest power of p, p^s, that divide n, and return s and n / p^s */

facpow(n, p) := block(
   [s: 0],
   while mod(n, p) = 0 do (s: s + 1, n: quotient(n, p)),
   [s, n]
)$

/* check whether n is a strong pseudoprime to base a; s and d are given by facpow(n - 1, 2) */

sppp(n, a, s, d) := block(
   [x: power_mod(a, d, n), q: false],
   if x = 1 or x = n - 1 then true else (
      from 2 thru s do (
         x: mod(x * x, n),
         if x = 1 then return(q: false) elseif x = n - 1 then return(q: true)
      ),
      q
   )
)$

/* Miller-Rabin primality test. For n < 341550071728321, the test is deterministic;
   for larger n, the number of bases tested is given by the option variable
   primep_number_of_tests, which is used by Maxima in primep. The bound for deterministic
   test is also the same as in primep. */

miller_rabin(n) := block(
   [v: [2, 3, 5, 7, 11, 13, 17], s, d, q: true, a],
   if n < 19 then member(n, v) else (
      [s, d]: facpow(n - 1, 2),
      if n < 341550071728321 then (    /* see http://oeis.org/A014233 */
         for a in v do (
            if not sppp(n, a, s, d) then return(q: false)
         ),
         q
      ) else (
         thru primep_number_of_tests do (
            a: 2 + random(n - 3),
            if not sppp(n, a, s, d) then return(q: false)
         ),
         q
      )
   )
)$


   :- func n2 = integer.integer.
   :- pragma memo(n2/0).
   n2 = integer.integer(2).


## Nim currently doesn't have a BigInt standard library
## so we translate the version from Go which uses a
## deterministic approach, which is correct for all
## possible values in uint32.

proc isPrime*(n: uint32): bool =
  # bases of 2, 7, 61 are sufficient to cover 2^32
  case n
  of 0, 1: return false
  of 2, 7, 61: return true
  else: discard

  var
    nm1 = n-1
    d = nm1.int
    s = 0
    n = n.uint64

  while d mod 2 == 0:
    d = d shr 1
    s += 1

  for a in [2, 7, 61]:
    var
      x = 1.uint64
      p = a.uint64
      dr = d

    while dr > 0:
      if dr mod 2 == 1:
        x = x * p mod n
      p = p * p mod n
      dr = dr shr 1

    if x == 1 or x.uint32 == nm1:
      continue

    var r = 1
    while true:
      if r >= s:
        return false
      x = x * x mod n
      if x == 1:
        return false
      if x.uint32 == nm1:
        break
      r += 1

  return true

proc isPrime*(n: int32): bool =
  ## Overload for int32
  n >= 0 and n.uint32.isPrime

when isMainModule:
  const primeNumber1000 = 7919 # source: https://en.wikipedia.org/wiki/List_of_prime_numbers
  var
    i = 0u32
    numberPrimes = 0
  while true:
    if isPrime(i):
      if numberPrimes == 999:
        break
      numberPrimes += 1
    i += 1

  assert i == primeNumber1000
  assert isPrime(2u32)
  assert isPrime(31u32)
  assert isPrime(37u32)
  assert isPrime(1123u32)
  assert isPrime(492366587u32)
  assert isPrime(1645333507u32)


(* Translated from the wikipedia pseudo-code *)
let miller_rabin n ~iter:k =
  (* return r and d where n = 2^r*d (from scheme implementation) *)
  let get_rd n =
    let rec loop r d =
      (* not even *)
      if Z.(equal (logand d one) one) then
        (r,d)
      else
        loop Z.(r + one) Z.(div d ~$2)
    in
    loop Z.zero n
  in
  let single_miller n r d =
    (* (random (n - 4)) + 2  *)
    let a = Bigint.to_zarith_bigint
              Bigint.((random ((of_zarith_bigint n) - (of_int 4))) + (of_int 2))
    in
    let x = Z.(powm a d n) in
    if Z.(equal x ~$1) || Z.(equal x (n - ~$1)) then true
    else
      let rec loop i x =
        if Z.(equal ~$i (r - ~$1)) then false
        else
          let x = Z.(powm x ~$2 n) in
          if Z.(equal x (n - ~$1)) then true
          else loop (i + 1) x
      in
      loop 0 x
  in
  let n = Z.abs n in
  if Z.(equal n one) then false
  else if Z.(equal (logand n one) zero) then false
  else if Z.(equal (n mod ~$3) zero) then false
  else
    let r, d = get_rd Z.(n - one) in
    let rec loop i bool =
      if i = k then bool
      else loop (i + 1) (bool && single_miller n r d)
    in
    loop 0 true


use bigint try => 'GMP';

sub is_prime {
    my ($n, $k) = @_;
    return 1 if $n == 2;
    return 0 if $n < 2 or $n % 2 == 0;

    my $d = $n - 1;
    my $s = 0;

    while (!($d % 2)) {
        $d /= 2;
        $s++;
    }

  LOOP: for (1 .. $k) {
        my $a = 2 + int(rand($n - 2));

        my $x = $a->bmodpow($d, $n);
        next if $x == 1 or $x == $n - 1;

        for (1 .. $s - 1) {
            $x = ($x * $x) % $n;
            return 0  if $x == 1;
            next LOOP if $x == $n - 1;
        }
        return 0;
    }
    return 1;
}

print join ", ", grep { is_prime $_, 10 } (1 .. 1000);


with javascript_semantics
function powermod(atom a, atom n, atom m)
-- calculate a^n%mod
    atom p = a, res = 1
    while n do
        if and_bits(n,1) then
            res = mod(res*p,m)
        end if
        p = mod(p*p,m)
        n = floor(n/2)
    end while
    return res
end function

function witness(atom n, atom s, atom d, sequence a)
-- n-1 = 2^s * d with d odd by factoring powers of 2 from n-1
    for i=1 to length(a) do
        atom x = powermod(a[i], d, n), y, w=s
        while w do
            y = mod(x*x,n)
            if y == 1 and x != 1 and x != n-1 then
                return false
            end if
            x = y
            w -= 1
        end while
        if y != 1 then
            return false
        end if
    end for
    return true;
end function

function is_prime_mr(atom n)
    if (mod(n,2)==0 and n!=2)
    or (n<2)
    or (mod(n,3)==0 and n!=3) then
        return false
    elsif n<=3 then
        return true
    end if
    atom d = floor(n/2)
    atom s = 1;
    while and_bits(d,1)=0 do
        d /= 2
        s += 1
    end while

    sequence a
    if n < 1373653 then
        a = {2, 3}
    elsif n < 9080191 then
        a = {31, 73}
    elsif (machine_bits()=32 and n < 94910107)
       or (machine_bits()=64 and n < 4295041217) then
        a = {2, 7, 61}
    else
        puts(1,"limits exceeded\n")
        return 0
    end if
    return witness(n, s, d, a)
end function

sequence tests = {999983,999809,999727,52633,60787,999999,999995,999991}
for i=1 to length(tests) do
    printf(1,"%d is %s\n",{tests[i],{"composite","prime"}[is_prime_mr(tests[i])+1]})
end for


(de longRand (N)
   (use (R D)
      (while (=0 (setq R (abs (rand)))))
      (until (> R N)
         (unless (=0 (setq D (abs (rand))))
            (setq R (* R D)) ) )
      (% R N) ) )

(de **Mod (X Y N)
   (let M 1
      (loop
         (when (bit? 1 Y)
            (setq M (% (* M X) N)) )
         (T (=0 (setq Y (>> 1 Y)))
            M )
         (setq X (% (* X X) N)) ) ) )

(de _prim? (N D S)
   (use (A X R)
      (while (> 2 (setq A (longRand N))))
      (setq R 0  X (**Mod A D N))
      (loop
         (T
            (or
               (and (=0 R) (= 1 X))
               (= X (dec N)) )
            T )
         (T
            (or
               (and (> R 0) (= 1 X))
               (>= (inc 'R) S) )
            NIL )
         (setq X (% (* X X) N)) ) ) )

(de prime? (N K)
   (default K 50)
   (and
      (> N 1)
      (bit? 1 N)
      (let (D (dec N)  S 0)
         (until (bit? 1 D)
            (setq
               D  (>> 1 D)
               S  (inc S) ) )
         (do K
            (NIL (_prim? N D S))
            T ) ) ) )


:- module(primality, [is_prime/2]).

% is_prime/2 returns false if N is composite, true if N probably prime
%    implements a Miller-Rabin primality test and is deterministic for N < 3.415e+14,
%    and is probabilistic for larger N. Adapted from the Erlang version.
is_prime(1, Ret) :- Ret = false, !.          % 1 is non-prime
is_prime(2, Ret) :- Ret = true, !.           % 2 is prime
is_prime(3, Ret) :- Ret = true, !.           % 3 is prime
is_prime(N, Ret) :-
	N > 3, (N mod 2 =:= 0), Ret = false, !.  % even number > 3 is composite
is_prime(N, Ret) :-
	N > 3, (N mod 2 =:= 1),                  % odd number > 3
	N < 341550071728321,
	deterministic_witnesses(N, L),
 	is_mr_prime(N, L, Ret), !.               % deterministic test
is_prime(N, Ret) :-
	random_witnesses(N, 100, [], Out),
	is_mr_prime(N, Out, Ret), !.             % probabilistic test

% returns list of deterministic witnesses
deterministic_witnesses(N, L) :- N < 1373653,
	L = [2, 3].
deterministic_witnesses(N, L) :- N < 9080191,
	L = [31, 73].
deterministic_witnesses(N, L) :- N < 25326001,
	L = [2, 3, 5].
deterministic_witnesses(N, L) :- N < 3215031751,
	L = [2, 3, 5, 7].
deterministic_witnesses(N, L) :- N < 4759123141,
	L = [2, 7, 61].
deterministic_witnesses(N, L) :- N < 1122004669633,
	L = [2, 13, 23, 1662803].
deterministic_witnesses(N, L) :- N < 2152302898747,
	L = [2, 3, 5, 7, 11].
deterministic_witnesses(N, L) :- N < 3474749660383,
	L = [2, 3, 5, 7, 11, 13].
deterministic_witnesses(N, L) :- N < 341550071728321,
	L = [2, 3, 5, 7, 11, 13, 17].

% random_witnesses/4 returns a list of K witnesses selected at random with range 2 -> N-2
random_witnesses(_, 0, T, T).
random_witnesses(N, K, T, Out) :-
		G is N - 2,
		H is 1 + random(G),
		I is K - 1,
    	random_witnesses(N, I, [H | T], Out), !.

% find_ds/2 receives odd integer N and returns [D, S] s.t. N-1 = 2^S * D
find_ds(N, L) :-
	A is N - 1,
    find_ds(A, 0, L), !.

find_ds(D, S, L) :-
	D mod 2 =:= 0,
	P is D // 2,
	Q is S + 1,
	find_ds(P, Q, L), !.
find_ds(D, S, L) :-
	L = [D, S].

is_mr_prime(N, As, Ret) :-
    find_ds(N, L),
    L = [D | T],
    T = [S | _],
    outer_loop(N, As, D, S, Ret), !.

outer_loop(N, As, D, S, Ret) :-
    As = [A | At],
    Base is powm(A, D, N),
    inner_loop(Base, N, 0, S, Result),
	(  Result == false           -> Ret = false
	;  Result == true, At == []  -> Ret = true
	;  outer_loop(N, At, D, S, Ret)
	).

inner_loop(Base, N, Loop, S, Result) :-
    Next_Base is (Base * Base) mod N,
    Next_Loop is Loop + 1,
	( Loop =:= 0, Base =:= 1   -> Result = true
	;             Base =:= N-1 -> Result = true
	; Next_Loop =:= S          -> Result = false
	; inner_loop(Next_Base, N, Next_Loop, S, Result)
	).


Enumeration
  #Composite
  #Probably_prime
EndEnumeration

Procedure Miller_Rabin(n, k)
  Protected d=n-1, s, x, r
  If n=2
    ProcedureReturn #Probably_prime
  ElseIf n%2=0 Or n<2
    ProcedureReturn #Composite
  EndIf
  While d%2=0
    d/2
    s+1
  Wend
  While k>0
    k-1
    x=Int(Pow(2+Random(n-4),d))%n
    If x=1 Or x=n-1: Continue: EndIf
    For r=1 To s-1
      x=(x*x)%n
      If x=1: ProcedureReturn #Composite: EndIf
      If x=n-1: Break: EndIf
    Next
    If x<>n-1: ProcedureReturn #Composite: EndIf
  Wend
  ProcedureReturn #Probably_prime
EndProcedure


import random

def is_Prime(n):
    """
    Miller-Rabin primality test.

    A return value of False means n is certainly not prime. A return value of
    True means n is very likely a prime.
    """
    if n!=int(n):
        return False
    n=int(n)
    #Miller-Rabin test for prime
    if n==0 or n==1 or n==4 or n==6 or n==8 or n==9:
        return False

    if n==2 or n==3 or n==5 or n==7:
        return True
    s = 0
    d = n-1
    while d%2==0:
        d>>=1
        s+=1
    assert(2**s * d == n-1)

    def trial_composite(a):
        if pow(a, d, n) == 1:
            return False
        for i in range(s):
            if pow(a, 2**i * d, n) == n-1:
                return False
        return True

    for i in range(8):#number of trials
        a = random.randrange(2, n)
        if trial_composite(a):
            return False

    return True


#lang racket
(define (miller-rabin-expmod base exp m)
  (define (squaremod-with-check x)
    (define (check-nontrivial-sqrt1 x square)
      (if (and (= square 1)
               (not (= x 1))
               (not (= x (- m 1))))
          0
          square))
    (check-nontrivial-sqrt1 x (remainder (expt x 2) m)))
  (cond ((= exp 0) 1)
        ((even? exp) (squaremod-with-check
                      (miller-rabin-expmod base (/ exp 2) m)))
        (else
         (remainder (* base (miller-rabin-expmod base (- exp 1) m))
                    m))))

(define (miller-rabin-test n)
  (define (try-it a)
    (define (check-it x)
      (and (not (= x 0)) (= x 1)))
    (check-it (miller-rabin-expmod a (- n 1) n)))
  (try-it (+ 1 (random (remainder (- n 1) 4294967087)))))

(define (fast-prime? n times)
  (for/and ((i (in-range times)))
    (miller-rabin-test n)))

(define (prime? n(times 100))
  (fast-prime? n times))

(prime? 4547337172376300111955330758342147474062293202868155909489) ;-> outputs true


# the expmod-function from: http://rosettacode.org/wiki/Modular_exponentiation
sub expmod(Int $a is copy, Int $b is copy, $n) {
	my $c = 1;
	repeat while $b div= 2 {
		($c *= $a) %= $n if $b % 2;
		($a *= $a) %= $n;
	}
	$c;
}

subset PrimeCandidate of Int where { $_ > 2 and $_ % 2 };

my Bool multi sub is_prime(Int $n, Int $k)            { return False; }
my Bool multi sub is_prime(2, Int $k)                 { return True; }
my Bool multi sub is_prime(PrimeCandidate $n, Int $k) {
	my Int $d = $n - 1;
	my Int $s = 0;

	while $d %% 2 {
		$d div= 2;
		$s++;
	}

	for (2 ..^ $n).pick($k) -> $a {
		my $x = expmod($a, $d, $n);

		# one could just write "next if $x == 1 | $n - 1"
		# but this takes much more time in current rakudo/nom
		next if $x == 1 or $x == $n - 1;

		for 1 ..^ $s {
			$x = $x ** 2 mod $n;
			return False if $x == 1;
			last if $x == $n - 1;
		}
		return False if $x !== $n - 1;
	}

	return True;
}

say (1..1000).grep({ is_prime($_, 10) }).join(", ");


/*REXX program puts the  Miller─Rabin  primality test  through its paces.               */
parse arg limit times seed .                     /*obtain optional arguments from the CL*/
if limit=='' | limit==","  then limit= 1000      /*Not specified?  Then use the default.*/
if times=='' | times==","  then times=   10      /*  "      "        "   "   "     "    */
if datatype(seed, 'W')  then call random ,,seed  /*If seed specified, use it for RANDOM.*/
numeric digits max(200, 2*limit)                 /*we're dealing with some ginormous #s.*/
tell= times<0                                    /*display primes  only if times is neg.*/
times= abs(times);         w= length(times)      /*use absolute value of TIMES; get len.*/
call genP  limit                                 /*suspenders now, use a belt later ··· */
@MR= 'Miller─Rabin primality test'               /*define a character literal for  SAY. */
say "There are"     #     'primes ≤'     limit   /*might as well display some stuff.    */
say                                              /* [↓]  (skipping unity); show sep line*/
     do a=2  to times;     say copies('─', 89)   /*(skipping unity)   do range of TIMEs.*/
     p= 0                                        /*the counter of primes for this pass. */
          do z=1  for limit                      /*now, let's get busy and crank primes.*/
          if \M_Rt(z, a)  then iterate           /*Not prime?   Then try another number.*/
          p= p + 1                               /*well, we found another one, by gum!  */
          if tell  then say z   'is prime according to'       @MR       "with K="a
          if !.z   then iterate
          say '[K='a"] "    z   "isn't prime !"  /*oopsy─doopsy  and/or  whoopsy─daisy !*/
          end   /*z*/
     say '        for 1──►'limit", K="right(a,w)',' @MR "found"  p  'primes {out of' #"}."
     end     /*a*/
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
genP: parse arg high;    @.=0;    @.1=2;   @.2=3;    !.[email protected].;   !.2=1;   !.3=1;     #=2
         do [email protected].#+2  by 2  to high               /*just examine odd integers from here. */
           do k=2  while k*k<=j;  if j//@.k==0  then iterate j;   end  /*k*/
         #= # + 1;       @.#= j;        !.j= 1   /*bump prime counter; add prime to the */
         end   /*j*/;      return                /*@. array; define a prime in !. array.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
M_Rt: procedure;  parse arg n,k;  d= n-1;   nL=d /*Miller─Rabin:   A.K.A.  Rabin─Miller.*/
      if n==2           then return 1            /*special case of (the)  even  prime.  */
      if n<2 | n//2==0  then return 0            /*check for too low, or an even number.*/

         do s=-1  while d//2==0;  d= d % 2       /*keep halving  until a zero remainder.*/
         end   /*while*/

                 do k;       ?= random(2, nL)    /* [↓]  perform the DO loop   K  times.*/
                 x= ?**d  //  n                  /*X  can get real gihugeic really fast.*/
                 if x==1 | x==nL  then iterate   /*First or penultimate? Try another pow*/
                   do s;     x= x**2  //  n      /*compute new  X   ≡   X²  modulus  N. */
                   if x==1   then return 0       /*if unity,  it's definitely not prime.*/
                   if x==nL  then leave          /*if  N-1,   then it  could  be prime. */
                   end   /*r*/                   /* [↑]  // is REXX's division remainder*/
                 if x\==nL   then return 0       /*nope, it ain't prime nohows, noway.  */
                 end     /*k*/                   /*maybe it's prime, maybe it ain't ··· */
      return 1                                   /*coulda/woulda/shoulda be prime;  yup.*/


# Project : Miller–Rabin primality test

see "Input a number: " give n
see "Input test: " give k

test =  millerrabin(n,k)
if test = 0
   see "Probably Prime" + nl
else
   see "Composite" + nl
ok

func millerrabin(n, k)
       if n = 2
          millerRabin = 0
          return millerRabin
       ok
       if n % 2 = 0 or n < 2
          millerRabin = 1
          return millerRabin
       ok
       d = n - 1
       s = 0
       while d % 2 = 0
               d = d / 2
               s = s + 1
       end
       while k > 0
               k = k - 1
               base = 2 + floor((random(10)/10)*(n-3))
               x = pow(base, d) % n
               if x != 1 and x != n-1
                  for r=1 to s-1
                      x = (x * x) % n
                      if x = 1
                         millerRabin = 1
                         return millerRabin
                      ok
                      if x = n-1
                         exit
                      ok
                  next
                  if x != n-1
                     millerRabin = 1
                     return millerRabin
                  ok
                ok
     end


def miller_rabin_prime?(n, g)
  d = n - 1
  s = 0
  while d % 2 == 0
    d /= 2
    s += 1
  end
  g.times do
    a = 2 + rand(n - 4)
    x = a.pow(d, n)  # x = (a**d) % n
    next if x == 1 || x == n - 1
    for r in (1..s - 1)
      x = x.pow(2, n) # x = (x**2) % n
      return false if x == 1
      break if x == n - 1
    end
    return false if x != n - 1
  end
  true # probably
end

p primes = (3..1000).step(2).find_all {|i| miller_rabin_prime?(i,10)}


input "Input a number:";n
input "Input test:";k

test =  millerRabin(n,k)
if test = 0 then
  print "Probably Prime"
 else
  print "Composite"
end if
wait

' ----------------------------------------
' Returns
'  Composite     = 1
'  Probably Prime = 0
' ----------------------------------------
 FUNCTION millerRabin(n, k)
  if n = 2 then
    millerRabin = 0 'probablyPrime
    goto [funEnd]
  end if

  if n mod 2 = 0 or n < 2 then
    millerRabin = 1 'composite
    goto [funEnd]
  end if

d = n - 1
while d mod 2 = 0
  d = d / 2
  s = s + 1
wend

while k > 0
  k = k - 1
  base = 2 + int(rnd(1)*(n-3))
  x = (base^d) mod n
  if x <> 1 and x <> n-1 then
    for r=1 To s-1
      x =(x * x) mod n
      if x=1 then
       millerRabin = 1 ' composite
       goto [funEnd]
      end if
      if x = n-1 then exit for
    next r

    if x<>n-1 then
      millerRabin =  1 ' composite
      goto [funEnd]
    end if
  end if
wend
[funEnd]
END FUNCTION


/* Add these lines to the [dependencies] section of your Cargo.toml file:
num = "0.2.0"
rand = "0.6.5"
*/

use num::bigint::BigInt;
use num::bigint::ToBigInt;

// The modular_exponentiation() function takes three identical types
// (which get cast to BigInt), and returns a BigInt:
fn modular_exponentiation<T: ToBigInt>(n: &T, e: &T, m: &T) -> BigInt {
    // Convert n, e, and m to BigInt:
    let n = n.to_bigint().unwrap();
    let e = e.to_bigint().unwrap();
    let m = m.to_bigint().unwrap();

    // Sanity check:  Verify that the exponent is not negative:
    assert!(e >= Zero::zero());

    use num::traits::{Zero, One};

    // As most modular exponentiations do, return 1 if the exponent is 0:
    if e == Zero::zero() {
        return One::one()
    }

    // Now do the modular exponentiation algorithm:
    let mut result: BigInt = One::one();
    let mut base = n % &m;
    let mut exp = e;

    loop {  // Loop until we can return our result.
        if &exp % 2 == One::one() {
            result *= &base;
            result %= &m;
        }

        if exp == One::one() {
            return result
        }

        exp /= 2;
        base *= base.clone();
        base %= &m;
    }
}

// is_prime() checks the passed-in number against many known small primes.
// If that doesn't determine if the number is prime or not, then the number
// will be passed to the is_rabin_miller_prime() function:
fn is_prime<T: ToBigInt>(n: &T) -> bool {
    let n = n.to_bigint().unwrap();
    if n.clone() < 2.to_bigint().unwrap() {
        return false
    }

    let small_primes = vec![2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,
                            47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101,
                            103, 107, 109, 113, 127, 131, 137, 139, 149, 151,
                            157, 163, 167, 173, 179, 181, 191, 193, 197, 199,
                            211, 223, 227, 229, 233, 239, 241, 251, 257, 263,
                            269, 271, 277, 281, 283, 293, 307, 311, 313, 317,
                            331, 337, 347, 349, 353, 359, 367, 373, 379, 383,
                            389, 397, 401, 409, 419, 421, 431, 433, 439, 443,
                            449, 457, 461, 463, 467, 479, 487, 491, 499, 503,
                            509, 521, 523, 541, 547, 557, 563, 569, 571, 577,
                            587, 593, 599, 601, 607, 613, 617, 619, 631, 641,
                            643, 647, 653, 659, 661, 673, 677, 683, 691, 701,
                            709, 719, 727, 733, 739, 743, 751, 757, 761, 769,
                            773, 787, 797, 809, 811, 821, 823, 827, 829, 839,
                            853, 857, 859, 863, 877, 881, 883, 887, 907, 911,
                            919, 929, 937, 941, 947, 953, 967, 971, 977, 983,
                            991, 997, 1009, 1013];

    use num::traits::Zero;  // for Zero::zero()

    // Check to see if our number is a small prime (which means it's prime),
    // or a multiple of a small prime (which means it's not prime):
    for sp in small_primes {
        let sp = sp.to_bigint().unwrap();

        if n.clone() == sp {
            return true
        } else if n.clone() % sp == Zero::zero() {
            return false
        }
    }

    is_rabin_miller_prime(&n, None)
}

// Note:  "use bigint::RandBigInt;"  (which is needed for gen_bigint_range())
//        fails to work in the Rust playground ( https://play.rust-lang.org ).
//        Therefore, I'll create my own here:
fn get_random_bigint(low: &BigInt, high: &BigInt) -> BigInt {
    if low == high {  // base case
        return low.clone()
    }

    let middle = (low.clone() + high) / 2.to_bigint().unwrap();

    let go_low: bool = rand::random();

    if go_low {
        return get_random_bigint(low, &middle)
    } else {
        return get_random_bigint(&middle, high)
    }
}

// k is the number of times for testing (pass in None to use 5 (the default)).
fn is_rabin_miller_prime<T: ToBigInt>(n: &T, k: Option<usize>) -> bool {
    let n = n.to_bigint().unwrap();
    let k = k.unwrap_or(10);  // number of times for testing (defaults to 10)

    use num::traits::{Zero, One};  // for Zero::zero() and One::one()
    let zero: BigInt = Zero::zero();
    let one: BigInt = One::one();
    let two: BigInt = 2.to_bigint().unwrap();

    // The call to is_prime() should have already checked this,
    // but check for two, less than two, and multiples of two:
    if n <= one {
        return false
    } else if n == two {
        return true  // 2 is prime
    } else if n.clone() % &two == Zero::zero() {
        return false  // even number (that's not 2) is not prime
    }

    let mut t: BigInt = zero.clone();
    let n_minus_one: BigInt = n.clone() - &one;
    let mut s = n_minus_one.clone();
    while &s % &two == one {
        s /= &two;
        t += &one;
    }

    // Try k times to test if our number is non-prime:
    'outer: for _ in 0..k {
        let a = get_random_bigint(&two, &n_minus_one);
        let mut v = modular_exponentiation(&a, &s, &n);
        if v == one {
            continue 'outer;
        }
        let mut i: BigInt = zero.clone();
        'inner: while &i < &t {
            v = (v.clone() * &v) % &n;
            if &v == &n_minus_one {
                continue 'outer;
            }
            i += &one;
        }
        return false;
    }
    // If we get here, then we have a degree of certainty
    // that n really is a prime number, so return true:
    true
}


import scala.math.BigInt

object MillerRabinPrimalityTest extends App {
  val (n, certainty )= (BigInt(args(0)), args(1).toInt)
  println(s"$n is ${if (n.isProbablePrime(certainty)) "probably prime" else "composite"}")
}


#!r6rs
(import (rnrs base (6))
        (srfi :27 random-bits))

;; Fast modular exponentiation.
(define (modexpt b e M)
  (cond
    ((zero? e) 1)
    ((even? e) (modexpt (mod (* b b) M) (div e 2) M))
    ((odd? e) (mod (* b (modexpt b (- e 1) M)) M))))

;; Return s, d such that d is odd and 2^s * d = n.
(define (split n)
  (let recur ((s 0) (d n))
    (if (odd? d)
        (values s d)
        (recur (+ s 1) (div d 2)))))

;; Test whether the number a proves that n is composite.
(define (composite-witness? n a)
  (let*-values (((s d) (split (- n 1)))
                ((x) (modexpt a d n)))
    (and (not (= x 1))
         (not (= x (- n 1)))
         (let try ((r (- s 1)))
           (set! x (modexpt x 2 n))
           (or (zero? r)
               (= x 1)
               (and (not (= x (- n 1)))
                    (try (- r 1))))))))

;; Test whether n > 2 is a Miller-Rabin pseudoprime, k trials.
(define (pseudoprime? n k)
  (or (zero? k)
      (let ((a (+ 2 (random-integer (- n 2)))))
        (and (not (composite-witness? n a))
             (pseudoprime? n (- k 1))))))

;; Test whether any integer is prime.
(define (prime? n)
  (and (> n 1)
       (or (= n 2)
           (pseudoprime? n 50))))


$ include "seed7_05.s7i";
  include "bigint.s7i";

const func boolean: millerRabin (in bigInteger: n, in integer: k) is func
  result
    var boolean: probablyPrime is TRUE;
  local
    var bigInteger: d is 0_;
    var integer: r is 0;
    var integer: s is 0;
    var bigInteger: a is 0_;
    var bigInteger: x is 0_;
    var integer: tests is 0;
  begin
    if n < 2_ or (n > 2_ and not odd(n)) then
      probablyPrime := FALSE;
    elsif n > 3_ then
      d := pred(n);
      s := lowestSetBit(d);
      d >>:= s;
      while tests < k and probablyPrime do
        a := rand(2_, pred(n));
        x := modPow(a, d, n);
        if x <> 1_ and x <> pred(n) then
          r := 1;
          while r < s and x <> 1_ and x <> pred(n) do
            x := modPow(x, 2_, n);
            incr(r);
          end while;
          probablyPrime := x = pred(n);
        end if;
        incr(tests);
      end while;
    end if;
  end func;

const proc: main is func
  local
    var bigInteger: number is 0_;
  begin
    for number range 2_ to 1000_ do
      if millerRabin(number, 10) then
        writeln(number);
      end if;
    end for;
  end func;


func miller_rabin(n, k=10) {

    return false if (n <= 1)
    return true  if (n == 2)
    return false if (n.is_even)

    var t = n-1
    var s = t.valuation(2)
    var d = t>>s

    k.times {
        var a = irand(2, t)
        var x = powmod(a, d, n)
        next if (x ~~ [1, t])

        (s-1).times {
            x.powmod!(2, n)
            return false if (x == 1)
            break if (x == t)
        }

        return false if (x != t)
    }

    return true
}

say miller_rabin.grep(^1000).join(', ')


Integer extend [
  millerRabinTest: kl [ |k| k := kl.
    self <= 3
      ifTrue: [ ^true ]
      ifFalse: [
         (self even)
           ifTrue: [ ^false ]
           ifFalse: [ |d s|
              d := self - 1.
              s := 0.
              [ (d rem: 2) == 0 ]
                 whileTrue: [
                   d := d / 2.
                   s := s + 1.
                 ].
              [ k:=k-1. k >= 0 ]
                 whileTrue: [ |a x r|
                    a := Random between: 2 and: (self - 2).
                    x := (a raisedTo: d) rem: self.
                    ( x = 1 )
                      ifFalse: [ |r|
		        r := -1.
                          [ r := r + 1. (r < s) & (x ~= (self - 1)) ]
                          whileTrue: [
                     	    x := (x raisedTo: 2) rem: self
                          ].
                        ( x ~= (self - 1) ) ifTrue: [ ^false ]
                      ]
                 ].
              ^true
           ]
      ]
  ]
].


open LargeInt;

val mr_iterations = Int.toLarge 20;
val rng = Random.rand (557216670, 13504100); (* arbitrary pair to seed RNG *)

fun expmod base 0 m = 1
  | expmod base exp m =
      if exp mod 2 = 0
      then let val rt = expmod base (exp div 2) m;
               val sq = (rt*rt) mod m
           in if sq = 1
                 andalso rt <> 1     (* ignore the two *)
                 andalso rt <> (m-1) (* 'trivial' roots *)
              then 0
              else sq
           end
      else (base*(expmod base (exp-1) m)) mod m;

(* arbitrary precision random number [0,n) *)
fun rand n =
  let val base = Int.toLarge(valOf Int.maxInt)+1;
      fun step r lim =
        if lim < n then step (Int.toLarge(Random.randNat rng) + r*base) (lim*base)
                   else r mod n
  in step 0 1 end;

fun miller_rabin n =
  let fun trial n 0 = true
        | trial n t = let val a = 1+rand(n-1)
                      in (expmod a (n-1) n) = 1
                         andalso trial n (t-1)
                      end
  in trial n mr_iterations end;

fun trylist label lst = (label, ListPair.zip (lst, map miller_rabin lst));

trylist "test the first six Carmichael numbers"
        [561, 1105, 1729, 2465, 2821, 6601];

trylist "test some known primes"
        [7369, 7393, 7411, 27367, 27397, 27407];

(* find ten random 30 digit primes (according to Miller-Rabin) *)
let fun findPrime trials = let val t = trials+1;
                               val n = 2*rand(500000000000000000000000000000)+1
                           in if miller_rabin n
                              then (n,t)
                              else findPrime t end
in List.tabulate (10, fn e => findPrime 0) end;


import BigInt

private let numTrails = 5

func isPrime(_ n: BigInt) -> Bool {
  guard n >= 2 else { fatalError() }
  guard n != 2 else { return true }
  guard n % 2 != 0 else { return false }

  var s = 0
  var d = n - 1

  while true {
    let (quo, rem) = (d / 2, d % 2)

    guard rem != 1 else { break }

    s += 1
    d = quo
  }

  func tryComposite(_ a: BigInt) -> Bool {
    guard a.power(d, modulus: n) != 1 else { return false }

    for i in 0..<s where a.power((2 as BigInt).power(i) * d, modulus: n) == n - 1 {
      return false
    }

    return true
  }

  for _ in 0..<numTrails where tryComposite(BigInt(BigUInt.randomInteger(lessThan: BigUInt(n)))) {
    return false
  }

  return true
}


package require Tcl 8.5

proc miller_rabin {n k} {
    if {$n <= 3} {return true}
    if {$n % 2 == 0} {return false}

    # write n - 1 as 2^s·d with d odd by factoring powers of 2 from n − 1
    set d [expr {$n - 1}]
    set s 0
    while {$d % 2 == 0} {
        set d [expr {$d / 2}]
        incr s
    }

    while {$k > 0} {
        incr k -1
        set a [expr {2 + int(rand()*($n - 4))}]
        set x [expr {($a ** $d) % $n}]
        if {$x == 1 || $x == $n - 1} continue
        for {set r 1} {$r < $s} {incr r} {
            set x [expr {($x ** 2) % $n}]
            if {$x == 1} {return false}
            if {$x == $n - 1} break
        }
	if {$x != $n-1} {return false}
    }
    return true
}

for {set i 1} {$i < 1000} {incr i} {
    if {[miller_rabin $i 10]} {
        puts $i
    }
}


import "/big" for BigInt

var iters = 10
// find all primes < 100
System.print("The following numbers less than 100 are prime:")
System.write("2 ")
for (i in 3..99) {
    if (BigInt.new(i).isProbablePrime(iters)) System.write("%(i) ")
}
System.print("\n")
var bia = [
    BigInt.new("4547337172376300111955330758342147474062293202868155909489"),
    BigInt.new("4547337172376300111955330758342147474062293202868155909393")
]
for (bi in bia) {
    System.print("%(bi) is %(bi.isProbablePrime(iters) ? "probably prime" : "composite")")
}


V patients_csv =
‘PATIENT_ID,LASTNAME
1001,Hopper
4004,Wirth
3003,Kemeny
2002,Gosling
5005,Kurtz’

V visits_csv =
‘PATIENT_ID,VISIT_DATE,SCORE
2002,2020-09-10,6.8
1001,2020-09-17,5.5
4004,2020-09-24,8.4
2002,2020-10-08,
1001,,6.6
3003,2020-11-12,
4004,2020-11-05,7.0
1001,2020-11-19,5.3’

F csv2list(s)
   [[String]] rows
   L(row) s.split("\n")
      rows [+]= row.split(‘,’)
   R rows

V patients = csv2list(patients_csv)
V visits = csv2list(visits_csv)

V result = copy(patients)
result.sort_range(1..)
result[0].append(‘LAST_VISIT’)
V last = Dict(visits[1..], p_vis -> (p_vis[0], p_vis[1]))
L(record) 1 .< result.len
   result[record].append(last.get(result[record][0], ‘’))
result[0] [+]= [‘SCORE_SUM’, ‘SCORE_AVG’]

V n = Dict(patients[1..], p -> (p[0], 0))
V tot = Dict(patients[1..], p -> (p[0], 0.0))

L(record) visits[1..]
   V p = record[0]
   V score = record[2]
   I !score.empty
      n[p]++
      tot[p] += Float(score)

L(record) 1 .< result.len
   V p = result[record][0]
   I n[p] != 0
      result[record] [+]= [‘#3.1’.format(tot[p]), ‘#2.2’.format(tot[p] / n[p])]
   E
      result[record] [+]= [‘’, ‘’]

L(record) result
   print(‘| ’record.map(r -> r.center(10)).join(‘ | ’)‘ |’)


Merge_and_aggregate(patients, visits){
    ID := [], LAST_VISIT := [], SCORE_SUM := [], VISIT := []
    for i, line in StrSplit(patients, "`n", "`r"){
        if (i=1)
            continue
        x := StrSplit(line, ",")
        ID[x.1] := x.2
    }

    for i, line in StrSplit(visits, "`n", "`r"){
        if (i=1)
            continue
        x := StrSplit(line, ",")
        LAST_VISIT[x.1] := x.2 > LAST_VISIT[x.1] ? x.2 : LAST_VISIT[x.1]
        SCORE_SUM[x.1] := (SCORE_SUM[x.1] ? SCORE_SUM[x.1] : 0) + (x.3 ? x.3 : 0)
        if x.3
            VISIT[x.1] := (VISIT[x.1] ? VISIT[x.1] : 0) + 1
    }

    output := "PATIENT_ID`tLASTNAME`tLAST_VISIT`tSCORE_SUM`tSCORE_AVG`n"
    for id, name in ID
        output .= ID "`t" name "`t" LAST_VISIT[id] "`t" SCORE_SUM[id] "`t" SCORE_SUM[id]/VISIT[id] "`n"
    return output
}


# syntax: GAWK -f MERGE_AND_AGGREGATE_DATASETS.AWK RC-PATIENTS.CSV RC-VISITS.CSV
# files may appear in any order
#
# sorting:
#   PROCINFO["sorted_in"] is used by GAWK
#   SORTTYPE is used by Thompson Automation's TAWK
#
{ # printf("%s %s\n",FILENAME,$0) # print input
    split($0,arr,",")
    if (FNR == 1) {
      file = (arr[2] == "LASTNAME") ? "patients" : "visits"
      next
    }
    patient_id_arr[key] = key = arr[1]
    if (file == "patients") {
      lastname_arr[key] = arr[2]
    }
    else if (file == "visits") {
      if (arr[2] > visit_date_arr[key]) {
        visit_date_arr[key] = arr[2]
      }
      if (arr[3] != "") {
        score_arr[key] += arr[3]
        score_count_arr[key]++
      }
    }
}
END {
    print("")
    PROCINFO["sorted_in"] = "@ind_str_asc" ; SORTTYPE = 1
    fmt = "%-10s %-10s %-10s %9s %9s %6s\n"
    printf(fmt,"patient_id","lastname","last_visit","score_sum","score_avg","scores")
    for (i in patient_id_arr) {
      avg = (score_count_arr[i] > 0) ? score_arr[i] / score_count_arr[i] : ""
      printf(fmt,patient_id_arr[i],lastname_arr[i],visit_date_arr[i],score_arr[i],avg,score_count_arr[i]+0)
    }
    exit(0)
}


#include <iostream>
#include <optional>
#include <ranges>
#include <string>
#include <vector>

using namespace std;

struct Patient
{
    string ID;
    string LastName;
};

struct Visit
{
    string PatientID;
    string Date;
    optional<float> Score;
};

int main(void)
{
    auto patients = vector<Patient> {
        {"1001", "Hopper"},
        {"4004", "Wirth"},
        {"3003", "Kemeny"},
        {"2002", "Gosling"},
        {"5005", "Kurtz"}};

    auto visits = vector<Visit> {
        {"2002", "2020-09-10", 6.8},
        {"1001", "2020-09-17", 5.5},
        {"4004", "2020-09-24", 8.4},
        {"2002", "2020-10-08", },
        {"1001", ""          , 6.6},
        {"3003", "2020-11-12", },
        {"4004", "2020-11-05", 7.0},
        {"1001", "2020-11-19", 5.3}};

    // sort the patients by ID
    sort(patients.begin(), patients.end(),
         [](const auto& a, const auto&b){ return a.ID < b.ID;});

    cout << "| PATIENT_ID | LASTNAME | LAST_VISIT | SCORE_SUM | SCORE_AVG |\n";
    for(const auto& patient : patients)
    {
        // loop over all of the patients and determine the fields
        string lastVisit;
        float sum = 0;
        int numScores = 0;

        // use C++20 ranges to filter the visits by patients
        auto patientFilter = [&patient](const Visit &v){return v.PatientID == patient.ID;};
        for(const auto& visit : visits | views::filter( patientFilter ))
        {
            if(visit.Score)
            {
                sum += *visit.Score;
                numScores++;
            }
            lastVisit = max(lastVisit, visit.Date);
        }

        // format the output
        cout << "|       " << patient.ID << " | ";
        cout.width(8); cout << patient.LastName << " | ";
        cout.width(10); cout << lastVisit << " | ";
        if(numScores > 0)
        {
            cout.width(9); cout << sum << " | ";
            cout.width(9); cout << (sum / float(numScores));
        }
        else cout << "          |          ";
        cout << " |\n";
    }
}


using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Runtime.Serialization;

public static class MergeAndAggregateDatasets
{
    public static void Main()
    {
        string patientsCsv = @"
PATIENT_ID,LASTNAME
1001,Hopper
4004,Wirth
3003,Kemeny
2002,Gosling
5005,Kurtz";

        string visitsCsv = @"
PATIENT_ID,VISIT_DATE,SCORE
2002,2020-09-10,6.8
1001,2020-09-17,5.5
4004,2020-09-24,8.4
2002,2020-10-08,
1001,,6.6
3003,2020-11-12,
4004,2020-11-05,7.0
1001,2020-11-19,5.3";

        string format = "yyyy-MM-dd";
        var formatProvider = new DateTimeFormat(format).FormatProvider;

        var patients = ParseCsv(
            patientsCsv.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries),
            line => (PatientId: int.Parse(line[0]), LastName: line[1]));

        var visits = ParseCsv(
            visitsCsv.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries),
            line => (
                PatientId: int.Parse(line[0]),
                VisitDate: DateTime.TryParse(line[1], formatProvider, DateTimeStyles.None, out var date) ? date : default(DateTime?),
                Score: double.TryParse(line[2], out double score) ? score : default(double?)
            )
        );

        var results =
            patients.GroupJoin(visits,
                p => p.PatientId,
                v => v.PatientId,
                (p, vs) => (
                    p.PatientId,
                    p.LastName,
                    LastVisit: vs.Max(v => v.VisitDate),
                    ScoreSum: vs.Sum(v => v.Score),
                    ScoreAvg: vs.Average(v => v.Score)
                )
            ).OrderBy(r => r.PatientId);

        Console.WriteLine("| PATIENT_ID | LASTNAME | LAST_VISIT | SCORE_SUM | SCORE_AVG |");
        foreach (var r in results) {
            Console.WriteLine($"| {r.PatientId,-10} | {r.LastName,-8} | {r.LastVisit?.ToString(format) ?? "",-10} | {r.ScoreSum,9} | {r.ScoreAvg,9} |");
        }
    }

    private static IEnumerable<T> ParseCsv<T>(string[] contents, Func<string[], T> constructor)
    {
        for (int i = 1; i < contents.Length; i++) {
            var line = contents[i].Split(',');
            yield return constructor(line);
        }
    }

}


// datetime.cpp
#include <ctime>
#include <cstdint>
extern "C" {
  int64_t from date(const char* string) {
    struct tm tmInfo = {0};
    strptime(string, "%Y-%m-%d", &tmInfo);
    return mktime(&tmInfo); // localtime
  }
}


// Merge and aggregate datasets. Nigel Galloway: January 6th., 2021
let rFile(fName)=seq{use n=System.IO.File.OpenText(fName)
                     n.ReadLine() |> ignore
                     while not n.EndOfStream do yield n.ReadLine().Split [|','|]}
let N=rFile("file1.txt") |> Seq.sort
let G=rFile("file2.txt") |> Seq.groupBy(fun n->n.[0]) |> Map.ofSeq
let fN n i g e l=printfn "| %-10s | %-8s | %10s |  %-9s | %-9s |" n i g e l
let fG n g=let z=G.[n]|>Seq.sumBy(fun n->try float n.[2] with :? System.FormatException->0.0)
           fN n g (G.[n]|>Seq.sort|>Seq.last).[1] (if z=0.0 then "" else string z) (if z=0.0 then "" else string(z/(float(Seq.length G.[n]))))


package main

import (
    "fmt"
    "math"
    "sort"
)

type Patient struct {
    id       int
    lastName string
}

// maps an id to a lastname
var patientDir = make(map[int]string)

// maintains a sorted list of ids
var patientIds []int

func patientNew(id int, lastName string) Patient {
    patientDir[id] = lastName
    patientIds = append(patientIds, id)
    sort.Ints(patientIds)
    return Patient{id, lastName}
}

type DS struct {
    dates  []string
    scores []float64
}

type Visit struct {
    id    int
    date  string
    score float64
}

// maps an id to lists of dates and scores
var visitDir = make(map[int]DS)

func visitNew(id int, date string, score float64) Visit {
    if date == "" {
        date = "0000-00-00"
    }
    v, ok := visitDir[id]
    if ok {
        v.dates = append(v.dates, date)
        v.scores = append(v.scores, score)
        visitDir[id] = DS{v.dates, v.scores}
    } else {
        visitDir[id] = DS{[]string{date}, []float64{score}}
    }
    return Visit{id, date, score}
}

type Merge struct{ id int }

func (m Merge) lastName() string  { return patientDir[m.id] }
func (m Merge) dates() []string   { return visitDir[m.id].dates }
func (m Merge) scores() []float64 { return visitDir[m.id].scores }

func (m Merge) lastVisit() string {
    dates := m.dates()
    dates2 := make([]string, len(dates))
    copy(dates2, dates)
    sort.Strings(dates2)
    return dates2[len(dates2)-1]
}

func (m Merge) scoreSum() float64 {
    sum := 0.0
    for _, score := range m.scores() {
        if score != -1 {
            sum += score
        }
    }
    return sum
}

func (m Merge) scoreAvg() float64 {
    count := 0
    for _, score := range m.scores() {
        if score != -1 {
            count++
        }
    }
    return m.scoreSum() / float64(count)
}

func mergePrint(merges []Merge) {
    fmt.Println("| PATIENT_ID | LASTNAME | LAST_VISIT | SCORE_SUM | SCORE_AVG |")
    f := "| %d       | %-7s  | %s | %4s      | %4s      |\n"
    for _, m := range merges {
        _, ok := visitDir[m.id]
        if ok {
            lv := m.lastVisit()
            if lv == "0000-00-00" {
                lv = "          "
            }
            scoreSum := m.scoreSum()
            ss := fmt.Sprintf("%4.1f", scoreSum)
            if scoreSum == 0 {
                ss = "    "
            }
            scoreAvg := m.scoreAvg()
            sa := "    "
            if !math.IsNaN(scoreAvg) {
                sa = fmt.Sprintf("%4.2f", scoreAvg)
            }
            fmt.Printf(f, m.id, m.lastName(), lv, ss, sa)
        } else {
            fmt.Printf(f, m.id, m.lastName(), "          ", "    ", "    ")
        }
    }
}

func main() {
    patientNew(1001, "Hopper")
    patientNew(4004, "Wirth")
    patientNew(3003, "Kemeny")
    patientNew(2002, "Gosling")
    patientNew(5005, "Kurtz")

    visitNew(2002, "2020-09-10", 6.8)
    visitNew(1001, "2020-09-17", 5.5)
    visitNew(4004, "2020-09-24", 8.4)
    visitNew(2002, "2020-10-08", -1) // -1 signifies no score
    visitNew(1001, "", 6.6)          // "" signifies no date
    visitNew(3003, "2020-11-12", -1)
    visitNew(4004, "2020-11-05", 7.0)
    visitNew(1001, "2020-11-19", 5.3)

    merges := make([]Merge, len(patientIds))
    for i, id := range patientIds {
        merges[i] = Merge{id}
    }
    mergePrint(merges)
}


import Data.List
import Data.Maybe
import System.IO (readFile)
import Text.Read (readMaybe)
import Control.Applicative ((<|>))

------------------------------------------------------------

newtype DB = DB { entries :: [Patient] }
  deriving Show

instance Semigroup DB where
  DB a <> DB b = normalize $ a <> b

instance Monoid DB where
  mempty = DB []

normalize :: [Patient] -> DB
normalize = DB
            . map mconcat
            . groupBy (\x y -> pid x == pid y)
            . sortOn pid

------------------------------------------------------------

data Patient = Patient { pid :: String
                       , name :: Maybe String
                       , visits :: [String]
                       , scores :: [Float] }
  deriving Show

instance Semigroup Patient where
  Patient p1 n1 v1 s1 <> Patient p2 n2 v2 s2 =
    Patient (fromJust $ Just p1 <|> Just p2)
            (n1 <|> n2)
            (v1 <|> v2)
            (s1 <|> s2)

instance Monoid Patient where
  mempty = Patient mempty mempty mempty mempty

------------------------------------------------------------

readDB :: String  -> DB
readDB = normalize
         . mapMaybe readPatient
         . readCSV

readPatient r = do
  i <- lookup "PATIENT_ID" r
  let n = lookup "LASTNAME" r
  let d = lookup "VISIT_DATE" r >>= readDate
  let s = lookup "SCORE" r >>= readMaybe
  return $ Patient i n (maybeToList d) (maybeToList s)
  where
    readDate [] = Nothing
    readDate d = Just d

readCSV :: String -> [(String, String)]
readCSV txt = zip header <$> body
  where
    header:body = splitBy ',' <$> lines txt
    splitBy ch = unfoldr go
      where
        go [] = Nothing
        go s  = Just $ drop 1 <$> span (/= ch) s