How to prove an iterative loop with computations in frama-c wp? - c

I have my test code (to study the WP loop invariants) which adds two long integers with each digit's representation in an array cell:
int main(int argc, const char * argv[]) {
char a[32], b[32];//size can be very big
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
scanf("%s %s", a, b);
unsigned int size1 = strlen(a);
unsigned int size2 = strlen(b);
//code to reverse a string. currently proved
reverse(a, size1);
reverse(b, size2);
for (unsigned int i = 0; i < size1; i++) a[i]-='0'; //move from chars to integers
for (unsigned int j = 0; j < size2; j++) b[j]-='0';
unsigned int maxsize = size1;
if (size2 > maxsize) maxsize = size2;
int over = 0;
//actual computation code
/*#
loop invariant maxsize == \max(size1, size2);
loop invariant bound: 0 <= k <= maxsize;
loop invariant ov: \forall integer i; 0 < i < k ==> \at(a[i], Here) == (\at(a[i], Pre) + b[i]+ Over((char *)a, (char *)b, i)) % 10;
loop assigns k, a[0..maxsize-1],over;
loop variant maxsize - k;
*/
for (unsigned int k = 0; k < maxsize; k++)
{
char sum=a[k] + b[k] + over;
//over=overflow is for 9+9 = 18, result=8, over=1
a[k] = sum % 10;
over = sum / 10;
}
if (over != 0) a[maxsize++] = over;
//...
return 0;
}
I want to specify only the last loop invariant. I have already tried some pieces of ACSL code with \at(a[i], LoopCurrent). I received Unknown status or Timeout. Finally, I finished with an axiomatic recursive solution without any success.
I have no ideas now what else should I try to verify this. Help?
UPDATE:
Created a function for actual calculations. Improved axioms. Still got Timeout status. Ran with Frama-C latest release from opam with default settings (timeout=10, prover Alt-Ergo).
/*#
#predicate
Unchanged{K,L}(char* a, integer first, integer last) = \forall integer i; first <= i < last ==> \at(a[i],K) == \at(a[i],L);
axiomatic ReminderAxiomatic
{
logic integer Reminder {l} (integer x, integer y);
axiom ReminderEmpty: \forall integer x, integer y; x < y ==> Reminder(x, y) == x;
axiom ReminderNext: \forall integer x, integer y; x>=y ==> Reminder(x, y) == Reminder(x-y, y)+0;
}
axiomatic DivAxiomatic
{
logic integer Div {l} (integer x, integer y);
axiom DivEmpty: \forall integer x, integer y; x < y ==> Div(x, y) == 0 ;
axiom DivNext: \forall integer x, integer y; x >= y ==> Div(x, y) == Div(x - y, y) + 1 ;
}
axiomatic OverAxiomatic
{
logic integer Over {L}(char *a, char * b, integer step) reads a[0..step-1], b[0..step-1];
axiom OverEmpty: \forall char *a, char * b, integer step; step <= 0 ==> Over(a, b, step) == 0;
axiom OverNext: \forall char *a, char * b, integer step; step > 0 && a[step-1]<10 && a[step-1]>=0 && b[step-1]<10 && b[step-1]>=0
==> Over(a, b, step) == Div((int) a[step-1]+(int)b[step-1]+(int)Over(a,b,step-1), 10);
}
*/
/*#
requires 0 <= maxsize < 10;
requires \valid (a+(0..maxsize-1));
requires \valid (b+(0..maxsize-1));
requires \valid (res+(0..maxsize));
requires \forall integer i; 0 <= i < maxsize ==> 0 <= (int)a[i] < 10;
requires \forall integer i; 0 <= i < maxsize ==> 0 <= (int)b[i] < 10;
*/
void summ(char *a, char *b, char *res, unsigned int maxsize) {
char over = 0;
/*#
loop invariant bound: 0 <= k <=maxsize;
loop invariant step: \forall integer i; 0 <= i < k ==> res[i] == (char) Reminder((int)a[i]+ (int)b[i]+ (int)Over((char *)a, (char *)b, i) , 10);
loop invariant unch: Unchanged{Here,LoopEntry}((char *)res, k, maxsize);
loop assigns k, over, res[0..maxsize-1];
loop variant maxsize-k;
*/
for (unsigned int k = 0; k < maxsize; k++)
{
char sum = a[k] + b[k] + over;
res[k] = sum % 10;
over = sum / 10;
}
//
if (over != 0) res[maxsize++] = over;
}

First of all, it would be much better if your question contained a MCVE, which in the present case include the C function you're currently working on (instead of only its body), and the ACSL annotations you've written, at their exact place in the code. The command line used to launch Frama-C wouldn't hurt either, as well as the list of annotations for which you have trouble.
Apart from that, here are a few things that might be related to your problem (again, without an exact description, it's difficult to tell for sure).
the loop assigns is wrong: you're assigning over in the loop, but it is not mentioned there.
I'm unsure whether \max is well supported by WP.
modulo and integer division are two operations automated provers tend to struggle with. You might need a few additional assertions and/or axioms to help them.
your loop invariant does not say anything about the values of a[i] for k <= i< maxsize. Since loop assigns indicates that all cells of a might have been modified, you have to add an invariant telling that the ones with higher indices have not been touched so far.
I'm not completely sure about your usage of \at(a[i],Pre): Pre indicates the beginning of the current function. Thus, if scanf and reverse are in the same function as the loop (again, a MCVE would have clarified this), this is not true. You might want to speak about \at(a[i],Loop_entry) to refer to the value of the cell in the state in which the loop is entered for the first time.
UPDATE
I'm afraid WP will not be able to completely prove your annotations, but I managed to obtain a version in which only a single lemma, that is basically an expanded version of the reads clause for the Over function is left unproved (and I believe that there is no way to prove it under WP's actual representation of C memory). Note that it implies playing with the TIP feature of WP. Code and scripts are provided below, but I'll start by commenting on your original version:
there is no need for Div and Reminder. If anything, they will confuse the prover. You can stick with xxx/10 and xxx%10. In fact, my remark on division and modulo was a bit too cautious. In the present case, everything seems to be fine at this level.
Similarly, Unchanged could be inlined, but it shouldn't hurt to keep it that way.
I have used unsigned char instead of char, as it avoids some spurious conversions due to integer promotions, and removed any cast in the logic. You normally don't have to introduce such casts in ACSL annotations, except perhaps to indicate that some computation stays within an appropriate range (as in \let x = y + z; x == (int) x; ). Such casts are translated into function calls in the proof obligation, and again it can confuse the provers.
an invariant was missing to indicate that over does indeed contain the potential carry from the previous step (again, a good hint that you're missing an invariant is that a location mentioned in loop assigns does not appear in any loop invariant).
Finally, there is a small subtlety: if you don't indicate somehow that over can only be 0 or 1, there's nothing that prevent the addition to overflow the unsigned char (making it impossible to prove that a C computation with unsigned char and its ACSL counterpart with unbounded integers give the same result). Due to the recursive nature of the Over function, this can be established by a so-called lemma function in which the mathematical induction is carried out by a simple for loop with appropriate invariants
In addition, I've added explicitely as invariant that a and b are left untouched. This is normally implied by the loop assigns, but having these explicit hypotheses makes it easier during the scripts.
To sum up, here is the final code:
/*#
axiomatic Carry {
logic integer Over {L}(unsigned char* a, unsigned char* b, integer step)
reads a[0 .. step - 1], b[0 .. step - 1];
axiom null_step: \forall unsigned char* a, *b, integer step;
step <= 0 ==> Over(a,b,step) == 0;
axiom prev_step: \forall unsigned char* a, *b, integer step;
step > 0 ==>
Over(a,b,step) ==
(a[step-1] + b[step - 1] + Over(a,b,step-1)) / 10;
lemma OverFootPrint{L1,L2}:
\forall unsigned char* a, unsigned char*b, integer step;
(\forall integer i; 0<=i<step ==> \at(a[i],L1) == \at(a[i],L2)) &&
(\forall integer i; 0<=i<step ==> \at(b[i],L1) == \at(b[i],L2)) ==>
Over{L1}(a,b,step) == Over{L2}(a,b,step);
}
*/
/*#
requires \valid(a+(0 .. step-1));
requires \valid(b+(0 .. step - 1));
requires \forall integer i; 0<=i<step ==> 0<=a[i]<10 && 0<=b[i]<10;
assigns \nothing;
ensures 0<= Over(a,b,step) <= 1;
*/
void lemma_function(unsigned char* a, unsigned char* b, unsigned int step) {
/*#
loop invariant 0<=i<=step;
loop invariant \forall integer k; 0<=k<=i ==> 0 <= Over(a, b, k) <= 1;
loop assigns i;
*/
for (int i = 0; i < step; i++);
}
/*#
requires 0 <= maxsize < 10;
requires \valid (a+(0..maxsize-1));
requires \valid (b+(0..maxsize-1));
requires \valid (res+(0..maxsize));
requires \separated (a+(0..maxsize-1),res+(0..maxsize));
requires \separated (b+(0..maxsize-1),res+(0..maxsize));
requires \forall integer i; 0 <= i < maxsize ==> 0 <= a[i] < 10;
requires \forall integer i; 0 <= i < maxsize ==> 0 <= b[i] < 10;
*/
void summ(unsigned char* a, unsigned char*b, unsigned char* res,
unsigned int maxsize) {
unsigned char over = 0;
/*#
loop invariant bound: 0 <= k <=maxsize;
loop invariant step: \forall integer i; 0 <= i < k ==> res[i] == (a[i]+ b[i]+ Over(a,b,i)) % 10;
loop invariant over: over == Over(a,b,k);
loop invariant a_unchanged: \forall integer i; 0 <= i < maxsize ==>
\at(a[i],LoopEntry) == a[i];
loop invariant b_unchanged: \forall integer i; 0 <= i < maxsize ==>
\at(b[i],LoopEntry) == b[i];
loop invariant unch: \forall integer i; k<=i<=maxsize ==> \at(res[i],LoopEntry) == res[i];
loop assigns k, over, res[0..maxsize-1];
loop variant maxsize-k;
*/
for (unsigned int k = 0; k < maxsize; k++)
{
unsigned char sum = a[k] + b[k] + over;
res[k] = sum % 10;
over = sum / 10;
lemma_function(a,b,k);
}
//
if (over != 0) res[maxsize++] = over;
}
The two TIP scripts are available here. To use them, put them in a directory scripts/typed next to the code (say file.c) and use this command line:
frama-c[-gui] -wp -wp-prover alt-ergo,script -wp-session scripts file.c
You can change the name of the scripts directory if you wish (it must match the argument of -wp-session), but typed and the filenames of the scripts must be as given since WP will use them to detect which proof obligation they are supposed to prove. In GUI mode, you can have a look at the script, but it is probably difficult to understand and explaining each step will not fit in a SO's answer.

Related

Non divisible subset-Hackerrank solution in C

I am new to programming and C is the only language I know. Read a few answers for the same question written in other programming languages. I have written some code for the same but I only get a few test cases correct (4 to be precise). How do I edit my code to get accepted?
I have tried comparing one element of the array with the rest and then I remove the element (which is being compared with the initial) if their sum is divisible by k and then this continues until there are two elements in the array where their sum is divisible by k. Here is the link to the question:
https://www.hackerrank.com/challenges/non-divisible-subset/problem
#include<stdio.h>
#include<stdlib.h>
void remove_element(int array[],int position,long int *n){
int i;
for(i=position;i<=(*n)-1;i++){
array[i]=array[i+1];
}
*n=*n-1;
}
int main(){
int k;
long int n;
scanf("%ld",&n);
scanf("%d",&k);
int *array=malloc(n*sizeof(int));
int i,j;
for(i=0;i<n;i++)
scanf("%d",&array[i]);
for(i=n-1;i>=0;i--){
int counter=0;
for(j=n-1;j>=0;j--){
if((i!=j)&&(array[i]+array[j])%k==0)
{
remove_element(array,j,&n);
j--;
continue;
}
else if((i!=j)&&(array[i]+array[j])%k!=0){
counter++;
}
}
if(counter==n-1){
printf("%ld",n);
break;
}
}
return 0;
}
I only get about 4 test cases right from 20 test cases.
What Gerhardh in his comment hinted at is that
for(i=position;i<=(*n)-1;i++){
array[i]=array[i+1];
}
reads from array[*n] when i = *n-1, overrunning the array. Change that to
for (i=position; i<*n-1; i++)
array[i]=array[i+1];
Additionally, you have
remove_element(array,j,&n);
j--;
- but j will be decremented when continuing the for loop, so decrementing it here is one time too many, while adjustment of i is necessary, since remove_element() shifted array[i] one position to the left, so change j-- to i--.
Furthermore, the condition
if(counter==n-1){
printf("%ld",n);
break;
}
makes just no sense; remove that block and place printf("%ld\n", n); before the return 0;.
To solve this efficiently, you have to realize several things:
Two positive integer numbers a and b are divisible by k (also positive integer number) if ((a%k) + (b%k))%k = 0. That means, that either ((a%k) + (b%k)) = 0 (1) or ((a%k) + (b%k)) = k (2).
Case (1) ((a%k) + (b%k)) = 0 is possible only if both a and b are multiples of k or a%k=0 and b%k=0. For case (2) , there are at most k/2 possible pairs. So, our task is to pick elements that don't fall in case 1 or 2.
To do this, map each number in your array to its corresponding remainder by modulo k. For this, create a new array remainders in which an index stands for a remainder, and a value stands for numbers having such remainder.
Go over the new array remainders and handle 3 cases.
4.1 If remainders[0] > 0, then we can still pick only one element from the original (if we pick more, then sum of their remainders 0, so they are divisible by k!!!).
4.2 if k is even and remainders[k/2] > 0, then we can also pick only one element (otherwise their sum is k!!!).
4.3 What about the other numbers? Well, for any remainder rem > 0 make sure to pick max(remainders[rem], remainders[k - rem]). You can't pick both since rem + k - rem = k, so numbers from such groups can be divisible by k.
Now, the code:
int nonDivisibleSubset(int k, int s_count, int* s) {
static int remainders[101];
for (int i = 0; i < s_count; i++) {
int rem = s[i] % k;
remainders[rem]++;
}
int maxSize = 0;
bool isKOdd = k & 1;
int halfK = k / 2;
for (int rem = 0; rem <= halfK; rem++) {
if (rem == 0) {
maxSize += remainders[rem] > 0;
continue;
}
if (!isKOdd && (rem == halfK)) {
maxSize++;
continue;
}
int otherRem = k - rem;
if (remainders[rem] > remainders[otherRem]) {
maxSize += remainders[rem];
} else {
maxSize += remainders[otherRem];
}
}
return maxSize;
}

Frama-C order function

I am trying to prove the correctness of my sorting function 'order' with Frama-C with the ACSL language. I have an additional 'swap' function to permute two values of my array 't'.
EDIT :
I updated my code.
/*#
requires \valid (t+ (0..(l-1)));
requires l > 0;
requires i<l && j<l && i>=0 && j>=0;
assigns t[i], t[j];
ensures t[j] == \old(t[i]);
ensures t[i] == \old(t[j]);
*/
void swap(int *t, int l, int i,int j){
int tmp;
tmp = t[i];
t[i] = t[j];
t[j] = tmp;
return;
}
/*#
requires \valid (t+ (0..(l-1)));
requires l > 0;
ensures \forall integer k; (0 <= k < l-1) ==> t[k] <= t[k+1];
*/
void order(int *t, int l) {
int i;
int j;
/*#
loop assigns i, t[0 .. l-1];
loop invariant 0<=i<l && i>=0;
loop invariant \forall integer k; (0 <= k<=i) ==> t[k] <= t[k+1];
loop variant l-i;
*/
for (i=0;i<l;i++) {
/*#
loop assigns j, t[0 .. l-1];
loop invariant i<=j<l && i>=0 && j>=0;
loop invariant \forall integer k; (0 <= k <= j) ==> (t[k] <= t[k+1]);
loop variant l-j;
*/
for (j=i; j<l; j++) {
if (t[i] > t[j]){
/*# assert t[i] > t[j] && i<l && j<l && i>=0 && j>=0 ; */
swap(t, l, i, j);
/*# assert t[i] < t[j] && i<l && j<l && i>=0 && j>=0 ; */
}
}
}
}
Thanks for your help!
As always when using WP, it is crucial that all functions called by the function under proof are equipped with a contract with assigns clauses. Furthemore, all loops of said function under proof must have a loop assigns clause. If this is not the case, WP will conclude that any part of the memory state might be modified by the call (resp. the loop), so that it won't be able to say anything meaningful after the corresponding instruction.
Thus, at the very minimum, you should add/replace the existing clause by:
in the contract of swap, a clause assigns t[i], t[j];
in the loop annotation of the outer loop, a clause loop assigns i, t[0 .. l-1];
in the loop annotation of the inner loop, a clause loop assigns j, t[i .. l-1];
As as side note regarding loop assigns:
they must describe all the potential modifications from the first entry into the loop up to the current step (hence t[i], t[j] is not sufficient, as there might have been other swaps occuring before the current j).
the index of the loop (here i and j) must be part of the loop assigns, although it is very easy to overlook it and wonder why WP is not happy.
Note that there might be others issues with your annotations, but these are the most obvious ones, and having appropriate assigns clauses is probably the single most important thing to have before attempting to prove deeper functional properties.

ACSL - Can't prove function [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I'm trying to prove this function, but in vain. I'm also using another function, but I proved it.
Could anyone help me?
I'm using Frama-C Sodium version with Alt-ergo 3 as prover.
Given a not-empty string x. An integer number p such that
0 < p ≤|x| is meant to be "a period of x" if
x[i] = x[i + p]
for i = 0, 1, ... , |x| − p − 1.
Note that, for each not-empty string, the length of the string
is a period of itself. In this way, every not-empty string
has got at least one period. So is well formed the concept of minimum
period of string x, denoted by per(x):
per(x) = min { p | p is period of x }.
Write a C function
unsigned per(const char x[], unsigned l)
that, given a string x of length l, returns per(x).
Here is the code and the specifications I have written so far:
/*#
requires l > 0;
requires p >= 0;
behavior zero:
assumes p == l;
ensures \result == 1;
behavior one:
assumes l != p && (l%p) == 0;
assumes \forall int i; 0 <= i < l-p-1 ==> x[i] == x[i+p];
ensures \result == 1;
behavior two:
assumes l != p && (l%p) == 0;
assumes !(\forall int i; 0 <= i < l-p-1 ==> x[i] == x[i+p]);
ensures \result == 0;
behavior three:
assumes p != l && l%p != 0;
ensures \result == 0;
complete behaviors;
disjoint behaviors;
*/
unsigned has_period(const char x[], unsigned int p, unsigned l) {
if (p == l) return 1;
if ((l % p) != 0) return 0;
/*#
loop assigns i;
loop invariant \forall int j; 0 <= j < i ==> (x[j] == x[j+p]);
loop invariant i <= l-p-1;
loop invariant i >= 0;
*/
for (int i = 0 ; i < l-p-1 ; ++i) {
if (x[i] != x[i + p])
return 0;
}
return 1;
}
/*
predicate has_period(char* x, unsigned int p, unsigned l) =
\forall int i; i < (l-p-1) ==> x[i] == x[i+p];
*/
/*#
requires l > 0;
requires \valid(x+(0..l-1));
ensures 1 <= \result <= l;
ensures \forall unsigned int i; i < (l-\result-1) ==> x[i] == x[i+\result];
ensures \forall unsigned int p; 1 <= p < \result ==> !(\forall int i; i < (l-p-1) ==> x[i] == x[i+p]);
*/
unsigned per(const char x[], unsigned l) {
int p = 1;
/*#
loop assigns p;
loop invariant 1 <= p <= l;
loop invariant \forall unsigned j; 1 <= j < p ==> !(\forall int i; i < (l-j-1) ==> x[i] == x[i+j] || (l%p) == 0);
loop invariant p >= 0;
*/
while(p < l && !has_period(x,p,l))
++p;
return p;
}
It would have helped if you had told us what your specific issue was, instead of a generic "it doesn't work", but here are some points:
Your contracts are lacking assigns clause. These are not optional when using WP, especially for functions like has_period that are called within your development. WP needs those clauses to know which locations might have changed during the call, and by taking the complement, which locations have stayed the same.
You have given a nice semi-formal definition of what a periodic string is. You should use that to define an ACSL predicate periodic (taking the same arguments as your C function has_period), and write your specifications according to this predicate. This will simplify your annotations a lot. In particular has_period does not need 4 behaviors: if periodic holds it must return 1, if periodic does not hold, it must return 0.
Using -wp-rte leads to a bunch of unproved obligations. Depending on your assignment, you might want to strengthen your specifications, especially regarding the validity of the location pointed to by x.

find all Carmichael numbers in a given interval [a,b) - C

I am working in a math software with different features one of them to be to find all Carmichael numbers in a given interval [a,b)
This is my code, but I don't know if I have done it correctly or not cause I can't test it since the smallest Carmichael number is 560 which is too big for my pc to process.
#include <stdio.h>
int main() {
unsigned int begin, end;
printf("Write an int (begin):\n");
scanf("%d", &begin);
printf("Write an int (end):\n");
scanf("%d", &end);
int i;
for( int i=begin; i<end; i++ ) {
long unsigned int a_nr = i-1;
int a[a_nr];
for( int j=0; j<a_nr; j++ ) {
a[j] = j;
}
unsigned long c_nr[a_nr];
for( int k=0; k<a_nr; k++ ) {
unsigned long current_c_nr;
int mod;
for( int l=0; l<i; l++ ) {
current_c_nr= current_c_nr * a[k];
}
mod = current_c_nr%i;
if( mod==a[k] && mod!=a[k] ) {
c_nr[k] = i;
}
}
}
return 0;
}
If it is not correct, where is the mistake?
Thank you
P.S Overflow should be prevented.
When you say "This is my code, but I don't know if I have done it correctly or not cause I can't test it since the smallest Carmichael number is 560 which is too big for my pc to process" then the conclusion is -- you haven't done it correctly. You should be able to process 561 (560 must be a typo) in a small fraction of a second. Even if your algorithm is in principle correct, if it can't handle the smallest Carmichael number then it is useless.
n is Carmichael if and only if it is composite and, for all a with 1 < a < n which are relatively prime to n, the congruence a^(n-1) = 1 (mod n) holds. To use this definition directly, you need:
1) An efficient way to test if a and n are relatively prime
2) An efficient way to compute a^(n-1) (mod n)
For the first -- use the Euclidean algorithm for greatest common divisors. It is most efficiently computed in a loop, but can also be defined via the simple recurrence gcd(a,b) = gcd(b,a%b) with basis gcd(a,0) = a. In C this is just:
unsigned int gcd(unsigned int a, unsigned int b){
return b == 0? a : gcd(b, a%b);
}
For the second point -- almost the worst possible thing you can do when computing a^k (mod n) is to first compute a^k via repeated multiplication and to then mod the result by n. Instead -- use exponentiation by squaring, taking the remainder (mod n) at intermediate stages. It is a divide-and-conquer algorithm based on the observation that e.g. a^10 = (a^5)^2 and a^11 = (a^5)^2 * a. A simple C implementation is:
unsigned int modexp(unsigned int a, unsigned int p, unsigned int n){
unsigned long long b;
switch(p){
case 0:
return 1;
case 1:
return a%n;
default:
b = modexp(a,p/2,n);
b = (b*b) % n;
if(p%2 == 1) b = (b*a) % n;
return b;
}
}
Note the use of unsigned long long to guard against overflow in the calculation of b*b.
To test if n is Carmichael, you might as well first test if n is even and return 0 in that case. Otherwise, step through numbers, a, in the range 2 to n-1. First check if gcd(a,n) == 1 Note that if n is composite then you must have at least one a before you reach the square root of n with gcd(a,n) > 1). Keep a Boolean flag which keeps track of whether or not such an a has been encountered and if you exceed the square root without finding such an a, return 0. For those a with gcd(a,n) == 1, compute the modular exponentiation a^(n-1) (mod n). If this is ever different from 1, return 0. If your loop finishes checking all a below n without returning 0, then the number is Carmichael, so return 1. An implementation is:
int is_carmichael(unsigned int n){
int a,s;
int factor_found = 0;
if (n%2 == 0) return 0;
//else:
s = sqrt(n);
a = 2;
while(a < n){
if(a > s && !factor_found){
return 0;
}
if(gcd(a,n) > 1){
factor_found = 1;
}
else{
if(modexp(a,n-1,n) != 1){
return 0;
}
}
a++;
}
return 1; //anything that survives to here is a carmichael
}
A simple driver program:
int main(void){
unsigned int n;
for(n = 2; n < 100000; n ++){
if(is_carmichael(n)) printf("%u\n",n);
}
return 0;
}
output:
C:\Programs>gcc carmichael.c
C:\Programs>a
561
1105
1729
2465
2821
6601
8911
10585
15841
29341
41041
46657
52633
62745
63973
75361
This only takes about 2 seconds to run and matches the initial part of this list.
This is probably a somewhat practical method for checking if numbers up to a million or so are Carmichael numbers. For larger numbers, you should probably get yourself a good factoring algorithm and use Korseldt's criterion as described in the Wikipedia entry on Carmichael numbers.

uint as indices

EDIT: Originally I had transcribed i++ not i--
The code now is as it was, and the code in the code block compiles and works.
Why, if unsigned int i; is used instead of int i; in the code snippet below, does using the function result in a segfault?
void insertion_sort_int_array(int * const Ints, unsigned int const len) {
unsigned int pos;
int key;
int i;
for (pos = 1; pos < len; ++pos) {
key = Ints[pos];
for (i = (pos - 1); (i >= 0) && Ints[i] > key; i--) {
Ints[i + 1] = Ints[i];
}
Ints[i + 1] = key;
}
}
THe posted code will fail in either case (possibly with a segfault, possibly only corrupting memory).
The inner loop starts at pos-1 and scans upwards in memory until some random condition is met - it does not check if it has passed the end of the array, so will run merrily on until it crashes or the end condition happens to be met by the (undefined) contents of the memory it is corrupting.
You probably meant to scan downwards in memory (using i-- in the loop), in which case it would fail because the loop will reach 0. Subtracting 1 from 0 gives you a very large positive number in an unsigned, so the loop will never end (i>=0 is always true) and it will access some memory somewhere in the region of Pluto.
insertionSort(array A)
begin
for x := 1 to length[A]-1 do
begin
value := A[x];
i := x - 1;
while i >= 0 and A[i] > value do
begin
A[i + 1] := A[i];
i := i - 1;
end;
A[i + 1] := value;
end;
end;
The only difference between the standard insertion sort algorithm and your code is that you're incrementing i instead of decrementing. That's your problem. I bet that in the code you're actually compiling and running, you have i-- instead of i++ in the inner loop. That's why the unsigned i makes a difference - it cannot be negative, so the inner loop will never end. Did you copy the code wrong when you posted?
EDIT:
Well, now that you changed the posted code, it all makes sense, right? An unsigned i will simply underflow to INT_MAX when you decrement it past 0, which will cause you to access memory outside of the array bounds.
What keeps i+1 within the bounds of your array 'ints'? It looks like badly formed data in your array will cause you to index into areas of memory which you shouldn't be in.
Why, if unsigned int i; is used
instead of int i; in the code snippet
below, does using the function result
in a segfault?
Because for unsigned int i, i >= 0 is always true, so your for loop is unlikely to terminate when you want.
You should always be extremely careful when looping backwards (from high to low) if your counter is unsigned.
i will [wraparound] causing access beyond the array limits.
Importing limits and comparing to UINT_MAX instead of the previous (i >= 0) fixes the issue:
#include <limits.h>
void insertion_sort_int_array(int * const Integers, unsigned int const N)
{
unsigned int o;
int target;
unsigned int i;
for (o = 1; o < N; o++) {
target = Integers[o];
for (i = (o - 1); (i != UINT_MAX) && (Ints[i] > target); i--) {
Integers[i + 1] = Integers[i];
}
Integers[i + 1] = key;
}
}

Resources