# include # include # include # include # include # include # include "subset.h" /******************************************************************************/ int asm_enum ( int n ) /******************************************************************************/ /* Purpose: asm_enum() returns the number of alternating sign matrices of a given order. Discussion: N ASM_NUM 0 1 1 1 2 2 3 7 4 42 5 429 6 7436 7 218348 A direct formula is ASM_NUM ( N ) = product ( 0 <= I <= N-1 ) ( 3 * I + 1 )! / ( N + I )! Licensing: This code is distributed under the MIT license. Modified: 02 May 2008 Author: John Burkardt Input: int N, the order of the matrices. Output: int ASM_ENUM, the number of alternating sign matrices of order N. */ { int *a; int asm_num; int *b; int *c; int i; int nn; int value; value = 0; if ( n + 1 <= 0 ) { return value; } /* Row 1 */ if ( n + 1 == 1 ) { value = 1; return value; } /* Row 2 */ if ( n + 1 == 2 ) { value = 1; return value; } a = ( int * ) malloc ( ( n + 1 ) * sizeof ( int ) ); b = ( int * ) malloc ( ( n + 1 ) * sizeof ( int ) ); c = ( int * ) malloc ( ( n + 1 ) * sizeof ( int ) ); b[0] = 2; c[0] = 2; a[0] = 1; a[1] = 1; /* Row 3 and on. */ for ( nn = 3; nn <= n; nn++ ) { b[nn-2] = nn; for ( i = nn - 2; 2 <= i; i-- ) { b[i-1] = b[i-1] + b[i-2]; } b[0] = 2; c[nn-2] = 2; for ( i = nn - 2; 2 <= i; i--) { c[i-1] = c[i-1] + c[i-2]; } c[0] = nn; for ( i = 2; i <= nn-1; i++ ) { a[0] = a[0] + a[i-1]; } for ( i = 2; i <= nn; i++ ) { a[i-1] = a[i-2] * c[i-2] / b[i-2]; } } asm_num = 0; for ( i = 0; i < n; i++ ) { asm_num = asm_num + a[i]; } free ( a ); free ( b ); free ( c ); return asm_num; } /******************************************************************************/ void asm_triangle ( int n, int a[] ) /******************************************************************************/ /* Purpose: asm_triangle() returns a row of the alternating sign matrix triangle. Discussion: The first seven rows of the triangle are as follows: 1 2 3 4 5 6 7 0 1 1 1 1 2 2 3 2 3 7 14 14 7 4 42 105 135 105 42 5 429 1287 2002 2002 1287 429 6 7436 26026 47320 56784 47320 26026 7436 For a given N, the value of A(J) represents entry A(I,J) of the triangular matrix, and gives the number of alternating sign matrices of order N in which the (unique) 1 in row 1 occurs in column J. Thus, of alternating sign matrices of order 3, there are 2 with a leading 1 in column 1: 1 0 0 1 0 0 0 1 0 0 0 1 0 0 1 0 1 0 3 with a leading 1 in column 2, and 0 1 0 0 1 0 0 1 0 1 0 0 0 0 1 1-1 1 0 0 1 1 0 0 0 1 0 2 with a leading 1 in column 3: 0 0 1 0 0 1 1 0 0 0 1 0 0 1 0 1 0 0 Licensing: This code is distributed under the MIT license. Modified: 07 May 2003 Author: John Burkardt Input: int N, the desired row. Output: int A[N+1], the entries of the row. */ { int *b; int *c; int i; int nn; if ( n + 1 <= 0 ) { return; } /* Row 1 */ a[0] = 1; if ( n + 1 == 1 ) { return; } /* Row 2 */ a[0] = 1; a[1] = 1; if ( n + 1 == 2 ) { return; } /* Row 3 and on. */ b = ( int * ) malloc ( ( n + 1 ) * sizeof ( int ) ); c = ( int * ) malloc ( ( n + 1 ) * sizeof ( int ) ); b[0] = 2; c[0] = 2; for ( nn = 3; nn <= n + 1; nn++ ) { b[nn-2] = nn; for ( i = nn - 2; 2 <= i; i-- ) { b[i-1] = b[i-1] + b[i-2]; } b[0] = 2; c[nn-2] = 2; for ( i = nn-2; 2 <= i; i-- ) { c[i-1] = c[i-1] + c[i-2]; } c[0] = nn; for ( i = 2; i <= nn-1; i++ ) { a[0] = a[0] + a[i-1]; } for ( i = 2; i <= nn; i++ ) { a[i-1] = a[i-2] * c[i-2] / b[i-2]; } } free ( b ); free ( c ); return; } /******************************************************************************/ void bell ( int n, int b[] ) /******************************************************************************/ /* Purpose: bell() returns the Bell numbers from 0 to N. Discussion: The Bell number B(N) is the number of restricted growth functions on N. Note that the Stirling numbers of the second kind, S^m_n, count the number of partitions of N objects into M classes, and so it is true that B(N) = S^1_N + S^2_N + ... + S^N_N. Definition: The Bell number B(N) is defined as the number of partitions (of any size) of a set of N distinguishable objects. A partition of a set is a division of the objects of the set into subsets. Examples: There are 15 partitions of a set of 4 objects: (1234), (123)(4), (124)(3), (12)(34), (12)(3)(4), (134)(2), (13)(24), (13)(2)(4), (14)(23), (1)(234), (1)(23)(4), (14)(2)(3), (1)(24)(3), (1)(2)(34), (1)(2)(3)(4) and so B(4) = 15. First values: N B(N) 0 1 1 1 2 2 3 5 4 15 5 52 6 203 7 877 8 4140 9 21147 10 115975 Recursion: B(I) = sum ( 1 <= J <= I ) Binomial ( I-1, J-1 ) * B(I-J) Licensing: This code is distributed under the MIT license. Modified: 03 May 2008 Author: John Burkardt Input: int N, the number of Bell numbers desired. Output: int B[N+1], the Bell numbers from 0 to N. */ { int i; int j; b[0] = 1; for ( i = 1; i <= n; i++ ) { b[i] = 0; for ( j = 1; j <= i; j++ ) { b[i] = b[i] + b[i-j] * i4_choose ( i-1, j-1 ); } } return; } /******************************************************************************/ void bell_values ( int *n_data, int *n, int *c ) /******************************************************************************/ /* Purpose: bell_values() returns some values of the Bell numbers. Discussion: The Bell number B(N) is the number of restricted growth functions on N. Note that the Stirling numbers of the second kind, S^m_n, count the number of partitions of N objects into M classes, and so it is true that B(N) = S^1_N + S^2_N + ... + S^N_N. The Bell numbers were named for Eric Temple Bell. In Mathematica, the function can be evaluated by Sum[StirlingS2[n,m],{m,1,n}] The Bell number B(N) is defined as the number of partitions (of any size) of a set of N distinguishable objects. A partition of a set is a division of the objects of the set into subsets. Example: There are 15 partitions of a set of 4 objects: (1234), (123) (4), (124) (3), (12) (34), (12) (3) (4), (134) (2), (13) (24), (13) (2) (4), (14) (23), (1) (234), (1) (23) (4), (14) (2) (3), (1) (24) (3), (1) (2) (34), (1) (2) (3) (4). and so B(4) = 15. First values: N B(N) 0 1 1 1 2 2 3 5 4 15 5 52 6 203 7 877 8 4140 9 21147 10 115975 Recursion: B(I) = sum ( 1 <= J <=I ) Binomial ( I-1, J-1 ) * B(I-J) Modified: 06 February 2003 Author: John Burkardt Reference: Milton Abramowitz, Irene Stegun, Handbook of Mathematical Functions, National Bureau of Standards, 1964, ISBN: 0-486-61272-4, LC: QA47.A34. Stephen Wolfram, The Mathematica Book, Fourth Edition, Cambridge University Press, 1999, ISBN: 0-521-64314-7, LC: QA76.95.W65. Input: int *N_DATA. The user sets N_DATA to 0 before the first call. Output: int *N_DATA. On each call, the routine increments N_DATA by 1, and returns the corresponding data; when there is no more data, the output value of N_DATA will be 0 again. int *N, the order of the Bell number. int *C, the value of the Bell number. */ { # define N_MAX 11 int c_vec[N_MAX] = { 1, 1, 2, 5, 15, 52, 203, 877, 4140, 21147, 115975 }; int n_vec[N_MAX] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; if ( *n_data < 0 ) { *n_data = 0; } *n_data = *n_data + 1; if ( N_MAX < *n_data ) { *n_data = 0; *n = 0; *c = 0; } else { *n = n_vec[*n_data-1]; *c = c_vec[*n_data-1]; } return; # undef N_MAX } /******************************************************************************/ int catalan_number ( int n ) /******************************************************************************/ /* Purpose: catalan_number() computes the N-th Catalan number. First values: C(0) 1 C(1) 1 C(2) 2 C(3) 5 C(4) 14 C(5) 42 C(6) 132 C(7) 429 C(8) 1430 C(9) 4862 C(10) 16796 Licensing: This code is distributed under the MIT license. Modified: 23 April 2024 Author: John Burkardt Input: int N, the index of the Catalan number. Output: int C: the value of the Catalan number. */ { int c; int i; if ( n < 0 ) { return 0; } c = 1; /* The extra parentheses ensure that the integer division is done AFTER the integer multiplication. */ for ( i = 1; i <= n; i++ ) { c = ( c * 2 * ( 2 * i - 1 ) ) / ( i + 1 ); } return c; } /******************************************************************************/ void catalan_numbers ( int n, int c[] ) /******************************************************************************/ /* Purpose: catalan_numbers() computes the Catalan numbers, from C(0) to C(N). Discussion: The Catalan number C(N) counts: 1) the number of binary trees on N vertices; 2) the number of ordered trees on N+1 vertices; 3) the number of full binary trees on 2N+1 vertices; 4) the number of well formed sequences of 2N parentheses; 5) the number of ways 2N ballots can be counted, in order, with N positive and N negative, so that the running sum is never negative; 6) the number of standard tableaus in a 2 by N rectangular Ferrers diagram; 7) the number of monotone functions from [1..N} to [1..N} which satisfy f(i) <= i for all i; 8) the number of ways to triangulate a polygon with N+2 vertices. First values: C(0) 1 C(1) 1 C(2) 2 C(3) 5 C(4) 14 C(5) 42 C(6) 132 C(7) 429 C(8) 1430 C(9) 4862 C(10) 16796 Formula: C(N) = (2*N)! / ( (N+1) * (N!) * (N!) ) = 1 / (N+1) * COMB ( 2N, N ) = 1 / (2N+1) * COMB ( 2N+1, N+1). Recursion: C(N) = 2 * (2*N-1) * C(N-1) / (N+1) C(N) = sum ( 1 <= I <= N-1 ) C(I) * C(N-I) Example: N = 3 ()()() ()(()) (()()) (())() ((())) Licensing: This code is distributed under the MIT license. Modified: 08 May 2003 Author: John Burkardt Reference: Dennis Stanton, Dennis White, Constructive Combinatorics, Springer, 1986, ISBN: 0387963472, LC: QA164.S79. Input: int N, the number of Catalan numbers desired. Output: int C[N+1], the Catalan numbers from C(0) to C(N). */ { int i; if ( n < 0 ) { return; } c[0] = 1; /* The extra parentheses ensure that the integer division is done AFTER the integer multiplication. */ for ( i = 1; i <= n; i++ ) { c[i] = ( c[i-1] * 2 * ( 2 * i - 1 ) ) / ( i + 1 ); } return; } /******************************************************************************/ void catalan_row_next ( int next, int n, int irow[] ) /******************************************************************************/ /* Purpose: catalan_row() computes row N of Catalan's triangle. Example: I\J 0 1 2 3 4 5 6 0 1 1 1 1 2 1 2 2 3 1 3 5 5 4 1 4 9 14 14 5 1 5 14 28 42 42 6 1 6 20 48 90 132 132 Recursion: C(0,0) = 1 C(I,0) = 1 C(I,J) = 0 for I < J C(I,J) = C(I,J-1) + C(I-1,J) C(I,I) is the I-th Catalan number. Licensing: This code is distributed under the MIT license. Modified: 08 May 2003 Author: John Burkardt Parameters: Input, int NEXT, indicates whether this is a call for the 'next' row of the triangle. NEXT = FALSE (0), this is a startup call. Row N is desired, but presumably this is a first call, or row N-1 was not computed on the previous call. NEXT = TRUE (1), this is not the first call, and row N-1 was computed on the previous call. In this case, much work can be saved by using the information from the previous values of IROW to build the next values. Input, int N, the index of the row of the triangle desired. Input/output, int IROW[N+1], the row of coefficients. If NEXT = FALSE, then IROW is not required to be set on input. If NEXT = TRUE, then IROW must be set on input to the value of row N-1. */ { # define TRUE 1 # define FALSE 0 int i; int j; if ( n < 0 ) { return; } if ( !( next == TRUE )) { irow[0] = 1; for ( i = 1; i <= n; i++ ) { irow[i] = 0; } for ( i = 1; i <= n; i++ ) { irow[0] = 1; for ( j = 1; j <= i-1; j++ ) { irow[j] = irow[j] + irow[j-1]; } irow[i] = irow[i-1]; } } else { irow[0] = 1; for ( j = 1; j <= n-1; j++ ) { irow[j] = irow[j] + irow[j-1]; } if ( 1 <= n ) { irow[n] = irow[n-1]; } } return; } /******************************************************************************/ void catalan_values ( int *n_data, int *n, int *c ) /******************************************************************************/ /* Purpose: catalan_values() returns some values of the Catalan numbers. Discussion: In Mathematica, the function can be evaluated by: Binomial[2*n,n] / ( n + 1 ) First values: C(0) 1 C(1) 1 C(2) 2 C(3) 5 C(4) 14 C(5) 42 C(6) 132 C(7) 429 C(8) 1430 C(9) 4862 C(10) 16796 Formula: C(N) = (2*N)! / ( (N+1) * (N!) * (N!) ) = 1 / (N+1) * COMB ( 2N, N ) = 1 / (2N+1) * COMB ( 2N+1, N+1). Recursion: C(N) = 2 * (2*N-1) * C(N-1) / (N+1) C(N) = sum ( 1 <= I <= N-1 ) C(I) * C(N-I) Discussion: The Catalan number C(N) counts: 1) the number of binary trees on N vertices; 2) the number of ordered trees on N+1 vertices; 3) the number of full binary trees on 2N+1 vertices; 4) the number of well formed sequences of 2N parentheses; 5) the number of ways 2N ballots can be counted, in order, with N positive and N negative, so that the running sum is never negative; 6) the number of standard tableaus in a 2 by N rectangular Ferrers diagram; 7) the number of monotone functions from [1..N} to [1..N} which satisfy f(i) <= i for all i; 8) the number of ways to triangulate a polygon with N+2 vertices. Example: N = 3 ()()() ()(()) (()()) (())() ((())) Modified: 03 February 2003 Author: John Burkardt Reference: Milton Abramowitz, Irene Stegun, Handbook of Mathematical Functions, National Bureau of Standards, 1964, ISBN: 0-486-61272-4, LC: QA47.A34. Stephen Wolfram, The Mathematica Book, Fourth Edition, Cambridge University Press, 1999, ISBN: 0-521-64314-7, LC: QA76.95.W65. Input: int *N_DATA. The user sets N_DATA to 0 before the first call. Output: int *N_DATA. On each call, the routine increments N_DATA by 1, and returns the corresponding data; when there is no more data, the output value of N_DATA will be 0 again. int *N, the order of the Catalan number. int *C, the value of the Catalan number. */ { # define N_MAX 11 int c_vec[N_MAX] = { 1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796 }; int n_vec[N_MAX] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; if ( *n_data < 0 ) { *n_data = 0; } *n_data = *n_data + 1; if ( N_MAX < *n_data ) { *n_data = 0; *n = 0; *c = 0; } else { *n = n_vec[*n_data-1]; *c = c_vec[*n_data-1]; } return; # undef N_MAX } /******************************************************************************/ void cfrac_to_rat ( int n, int a[], int p[], int q[] ) /******************************************************************************/ /* Purpose: cfrac_to_rat() converts a monic continued fraction to an ordinary fraction. Discussion: The routine is given the monic or "simple" continued fraction with integer coefficients: A(1) + 1 / ( A(2) + 1 / ( A(3) ... + 1 / A(N) ) ) and returns the N successive approximants P(I)/Q(I) to the value of the rational number represented by the continued fraction, with the value exactly equal to the final ratio P(N)/Q(N). Licensing: This code is distributed under the MIT license. Modified: 31 May 2008 Author: FORTRAN77 original version by John Hart, Ward Cheney, Charles Lawson, Hans Maehly, Charles Mesztenyi, John Rice, Henry Thatcher, Christoph Witzgall. This version by John Burkardt. Reference: John Hart, Ward Cheney, Charles Lawson, Hans Maehly, Charles Mesztenyi, John Rice, Henry Thatcher, Christoph Witzgall, Computer Approximations, Wiley, 1968. Input: int N: the number of continued fraction coefficients. int A[N]: the continued fraction coefficients. Output: int P[N], Q[N]: the N successive approximations to the value of the continued fraction. */ { int i; for ( i = 0; i < n; i++ ) { if ( i == 0 ) { p[i] = a[i] * 1 + 0; q[i] = a[i] * 0 + 1; } else if ( i == 1 ) { p[i] = a[i] * p[i-1] + 1; q[i] = a[i] * q[i-1] + 0; } else { p[i] = a[i] * p[i-1] + p[i-2]; q[i] = a[i] * q[i-1] + q[i-2]; } } return; } /******************************************************************************/ void cfrac_to_rfrac ( int m, double g[], double h[], double p[], double q[] ) /******************************************************************************/ /* Purpose: cfrac_to_rfrac() converts a polynomial fraction from continued to rational form. Discussion: The routine accepts a continued polynomial fraction: G(1) / ( H(1) + G(2) * X / ( H(2) + G(3) * X / ( H(3) + ... G(M) * X / ( H(M) )...) ) ) and returns the equivalent rational polynomial fraction: P(1) + P(2) * X + ... + P(L1) * X**(L1) ------------------------------------------------------- Q(1) + Q(2) * X + ... + Q(L2) * X**(L2-1) where L1 = (M+1)/2 L2 = (M+2)/2. Licensing: This code is distributed under the MIT license. Modified: 31 May 2008 Author: FORTRAN77 original version by John Hart, Ward Cheney, Charles Lawson, Hans Maehly, Charles Mesztenyi, John Rice, Henry Thatcher, Christoph Witzgall. This version by John Burkardt. Reference: John Hart, Ward Cheney, Charles Lawson, Hans Maehly, Charles Mesztenyi, John Rice, Henry Thatcher, Christoph Witzgall, Computer Approximations, Wiley, 1968. Parameters: Input, int M, the number of continued fraction polynomial coefficients. Input, double G[M], H[M], the continued polynomial fraction coefficients. Output, double P[(M+1)/2], Q[(M+2)/2], the rational polynomial fraction coefficients. */ { double *a; int i; int j; if ( m == 1 ) { p[0] = g[0]; q[0] = h[0]; return; } a = ( double * ) malloc ( m*((m+2)/2) * sizeof ( double ) ); for ( i = 0; i < m; i++ ) { for ( j = 0; j < (m+2)/2; j++ ) { a[i+j*m] = 0.0; } } /* Solve for P's */ a[0+0*m] = g[0]; a[1+0*m] = g[0] * h[1]; for ( i = 2; i < m; i++ ) { a[i+0*m] = h[i] * a[i-1+0*m]; for ( j = 1; j < (i+2)/2; j++ ) { a[i+j*m] = h[i] * a[i-1+j*m] + g[i] * a[i-2+(j-1)*m]; } } for ( j = 0; j < (m+1)/2; j++ ) { p[j] = a[m-1+j*m]; } /* Solve for Q's. */ a[0+0*m] = h[0]; a[1+0*m] = h[0] * h[1]; a[1+1*m] = g[1]; for ( i = 2; i < m; i++ ) { a[i+0*m] = h[i] * a[i-1+0*m]; for ( j = 1; j < (i+3)/2; j++ ) { a[i+j*m] = h[i] * a[i-1+j*m] + g[i] * a[i-2+(j-1)*m]; } } for ( j = 0; j < (m+2)/2; j++ ) { q[j] = a[m-1+j*m]; } free ( a ); return; } /******************************************************************************/ char ch_cap ( char ch ) /******************************************************************************/ /* Purpose: ch_cap() capitalizes a single character. Discussion: This routine should be equivalent to the library "toupper" function. Licensing: This code is distributed under the MIT license. Modified: 19 July 1998 Author: John Burkardt Parameters: Input, char CH, the character to capitalize. Output, char CH_CAP, the capitalized character. */ { if ( 97 <= ch && ch <= 122 ) { ch = ch - 32; } return ch; } /******************************************************************************/ void change_greedy ( int total, int coin_num, int coin_value[], int *change_num, int change[] ) /******************************************************************************/ /* Purpose: change_greedy() makes change for a given total using the biggest coins first. Discussion: The algorithm is simply to use as many of the largest coin first, then the next largest, and so on. It is assumed that there is always a coin of value 1. The algorithm will otherwise fail! Example: Total = 17 COIN_NUM = 3 COIN_VALUE = (/ 1, 5, 10 /) # CHANGE COIN_VALUE(CHANGE) 4 3 2 1 1 10 5 1 1 Licensing: This code is distributed under the MIT license. Modified: 28 May 2003 Author: John Burkardt Parameters: Input, int TOTAL, the total for which change is to be made. Input, int COIN_NUM, the number of types of coins. Input, int COIN_VALUE[COIN_NUM], the value of each coin. The values should be in ascending order, and if they are not, they will be sorted. Output, int *CHANGE_NUM, the number of coins given in change. Output, int CHANGE[TOTAL], the indices of the coins will be in entries 1 through CHANGE_NUM. */ { int j; *change_num = 0; /* Find the largest coin smaller than the total. */ j = coin_num - 1; while ( 0 <= j ) { if ( coin_value[j] <= total ) { break; } j = j - 1; } if ( j < 0 ) { return; } /* Subtract the current coin from the total. Once that coin is too big, use the next coin. */ while ( 0 < total ) { if ( coin_value[j] <= total ) { total = total - coin_value[j]; change[*change_num] = j; *change_num = *change_num + 1; } else { j = j - 1; if ( j < 0 ) { break; } } } return; } /******************************************************************************/ void change_next ( int total, int coin_num, int coin_value[], int *change_num, int change[], int *done ) /******************************************************************************/ /* Purpose: change_next() computes the next set of change for a given sum. Example: Total = 17 COIN_NUM = 3 COIN_VALUE = { 1, 5, 10 } # CHANGE COIN_VALUE(CHANGE) 1 4 3 2 1 1 10 5 1 1 2 8 3 1 1 1 1 1 1 1 10 1 1 1 1 1 1 1 3 5 2 2 2 1 1 5 5 5 1 1 4 9 2 2 1 1 1 1 1 1 1 5 5 1 1 1 1 1 1 1 5 13 2 1 1 1 1 1 1 1 1 1 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 6 17 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 Licensing: This code is distributed under the MIT license. Modified: 21 June 2004 Author: John Burkardt Parameters: Input, int TOTAL, the total for which change is to be made. Input, int COIN_NUM, the number of types of coins. Input, int COIN_VALUE[COIN_NUM], the value of each coin. The values must be in ascending order. Input/output, int *CHANGE_NUM, the number of coins given in change for this form of the change. Input/output, int CHANGE[CHANGE_NUM], the indices of the coins. The user must dimension this array to have dimension TOTAL! Input/output, int *DONE. The user sets DONE = .TRUE. on first call to tell the routine this is the beginning of a computation. The program resets DONE to .FALSE. and it stays that way until the last possible change combination is made, at which point the program sets DONE to TRUE again. */ { int change_num2; int coin_num2; int i; int last; int total2; if ( *done ) { /* Make sure the coin values are sorted into ascending order. */ if ( !i4vec_ascends ( coin_num, coin_value ) ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "change_next(): Fatal error!\n" ); fprintf ( stderr, " COIN_VALUE array is not in ascending order.\n" ); exit ( 1 ); } /* Start with the greedy change. */ change_greedy ( total, coin_num, coin_value, change_num, change ); /* In a few cases, like change for 4 cents, we're done after the first call. */ if ( *change_num == total ) { *done = 1; } else { *done = 0; } return; } /* Find the last location in the input change which is NOT a penny. */ last = -1; for ( i = *change_num-1; 0 <= i; i-- ) { if ( change[i] != 0 ) { last = i; break; } } /* If that location is still -1, an error was made. */ if ( last == -1 ) { *done = 1; return; } /* Sum the entries from that point to the end. */ total2 = 0; for ( i = last; i <= *change_num-1; i++ ) { total2 = total2 + coin_value [ change[i] ]; } /* Make greedy change for the partial sum using coins smaller than that one. */ coin_num2 = change[last]; change_greedy ( total2, coin_num2, coin_value, &change_num2, change+last ); *change_num = last + change_num2; return; } /******************************************************************************/ int chinese_check ( int n, int m[] ) /******************************************************************************/ /* Purpose: chinese_check() checks the Chinese remainder moduluses. Discussion: For a Chinese remainder representation, the moduluses M(I) must be positive and pairwise prime. Also, in case this is not obvious, no more than one of the moduluses may be 1. Licensing: This code is distributed under the MIT license. Modified: 25 May 2015 Author: John Burkardt Parameters: Input, int N, the number of moduluses. Input, int M[N], the moduluses. These should be positive and pairwise prime. Output, int CHINESE_CHECK, is TRUE if an error was detected. */ { int i; int j; /* Do not allow nonpositive entries. */ for ( i = 0; i < n; i++ ) { if ( m[i] <= 0 ) { return 1; } } /* Allow one entry to be 1, but not two entries. */ for ( i = 0; i < n; i++ ) { for ( j = i+1; j < n; j++ ) { if ( m[i] == 1 && m[j] == 1 ) { return 2; } } } /* Now check pairwise primeness. */ if ( !i4vec_pairwise_prime ( n, m ) ) { return 3; } return 0; } /******************************************************************************/ int chinese_to_i4 ( int n, int m[], int r[] ) /******************************************************************************/ /* Purpose: chinese_to_i4() converts a set of Chinese remainders to an equivalent integer. Discussion: Given a set of N pairwise prime, positive moduluses M(I), and a corresponding set of remainders R(I), this routine finds an integer J such that, for all I, J = R(I) mod M(I) Licensing: This code is distributed under the MIT license. Modified: 27 June 2008 Author: John Burkardt Parameters: Input, int N, the number of moduluses. Input, int M[N], the moduluses. These should be positive and pairwise prime. Input, int R[N], the Chinese remainder representation of the integer. Output, int CHINESE_TO_I4, the corresponding integer. */ { int a; int *b; int big_m; int c; int error; int i; int j; error = chinese_check ( n, m ); if ( error ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "chinese_to_i4(): Fatal error!\n" ); fprintf ( stderr, " The moduluses are not legal.\n" ); exit ( 1 ); } b = ( int * ) malloc ( n * sizeof ( int ) ); /* Set BIG_M. */ big_m = 1; for ( i = 0; i < n; i++ ) { big_m = big_m * m[i]; } /* Solve BIG_M / M(I) * B(I) = 1, mod M(I) */ for ( i = 0; i < n; i++ ) { a = big_m / m[i]; c = 1; b[i] = congruence ( a, m[i], c, &error ); } /* Set J = sum ( 1 <= I <= N ) ( R(I) * B(I) * BIG_M / M(I) ) mod M */ j = 0; for ( i = 0; i < n; i++ ) { j = ( j + r[i] * b[i] * ( big_m / m[i] ) ) % big_m; } free ( b ); return j; } /******************************************************************************/ void comb_next ( int n, int k, int a[], int *done ) /******************************************************************************/ /* Purpose: comb_next() computes combinations of K things out of N. Discussion: The combinations are computed one at a time, in lexicographical order. 10 April 2009: Thanks to "edA-qa mort-ora-y" for supplying a correction to this code! Licensing: This code is distributed under the MIT license. Modified: 10 April 2009 Author: John Burkardt Reference: Charles Mifsud, Combination in Lexicographic Order, ACM algorithm 154, Communications of the ACM, March 1963. Parameters: Input, int N, the total number of things. Input, int K, the number of things in each combination. Input/output, int A[K], contains the list of elements in the current combination. Input/output, int DONE. Set DONE to TRUE (1) before the first call, and then use the output value from the previous call on subsequent calls. The output value will be FALSE (0) as long as there are more combinations to compute, and TRUE (1) when the list is exhausted. */ { int i; int j; if ( *done ) { if ( k <= 0 ) { return; } i4vec_indicator0 ( k, a ); *done = 0; } else { if ( a[k-1] < n ) { a[k-1] = a[k-1] + 1; return; } for ( i = k; 2 <= i; i-- ) { if ( a[i-2] < n-k+i-1 ) { a[i-2] = a[i-2] + 1; for ( j = i; j <= k; j++ ) { a[j-1] = a[i-2] + j - ( i-1 ); } return; } } *done = 1; } return; } /******************************************************************************/ void comb_row_next ( int n, int row[] ) /******************************************************************************/ /* Purpose: comb_row_next() computes the next row of Pascal's triangle. Discussion: Row N contains the N+1 combinatorial coefficients C(N,0), C(N,1), C(N,2), ... C(N,N) The sum of the elements of row N is equal to 2^N. The formula is: C(N,K) = N! / ( K! * (N-K)! ) First terms: N K:0 1 2 3 4 5 6 7 8 9 10 0 1 1 1 1 2 1 2 1 3 1 3 3 1 4 1 4 6 4 1 5 1 5 10 10 5 1 6 1 6 15 20 15 6 1 7 1 7 21 35 35 21 7 1 8 1 8 28 56 70 56 28 8 1 9 1 9 36 84 126 126 84 36 9 1 10 1 10 45 120 210 252 210 120 45 10 1 Recursion: C(N,K) = C(N-1,K-1)+C(N-1,K) Special values: C(N,0) = C(N,N) = 1 C(N,1) = C(N,N-1) = N C(N,N-2) = sum ( 1 <= I <= N ) N Licensing: This code is distributed under the MIT license. Modified: 23 December 2014 Author: John Burkardt Parameters: Input, int N, the row of the triangle desired. The triangle begins with row 0. Input/output, int ROW[N+1]. On input, row N-1 is contained in entries 0 through N-1. On output, row N is contained in entries 0 through N. */ { int i; if ( n < 0 ) { return; } row[n] = 1; for ( i = n - 1; 1 <= i; i-- ) { row[i] = row[i] + row[i-1]; } row[0] = 1; return; } /******************************************************************************/ void comb_unrank ( int m, int n, int rank, int a[] ) /******************************************************************************/ /* Purpose: comb_unrank() returns the RANK-th combination of N things out of M. Discussion: The combinations are ordered lexically. Lexical order can be illustrated for the general case of N and M as follows: 1: 1, 2, 3, ..., N-2, N-1, N 2: 1, 2, 3, ..., N-2, N-1, N+1 3: 1, 2, 3, ..., N-2, N-1, N+2 ... M-N+1: 1, 2, 3, ..., N-2, N-1, M M-N+2: 1, 2, 3, ..., N-2, N, N+1 M-N+3: 1, 2, 3, ..., N-2, N, N+2 ... LAST-2: M-N, M-N+1, M-N+3, ..., M-2, M-1, M LAST-1: M-N, M-N+2, M-N+3, ..., M-2, M-1, M LAST: M-N+1, M-N+2, M-N+3, ..., M-2, M-1, M There are a total of M!/(N!*(M-N)!) combinations of M things taken N at a time. Licensing: This code is distributed under the MIT license. Modified: 27 June 2008 Author: John Burkardt Reference: B P Buckles, M Lybanon, Algorithm 515, Generation of a Vector from the Lexicographical Index, ACM Transactions on Mathematical Software, Volume 3, Number 2, pages 180-182, June 1977. Parameters: Input, int M, the size of the set. Input, int N, the number of things in the combination. N must be greater than 0, and no greater than M. Input, int RANK, the lexicographical index of combination sought. RANK must be at least 1, and no greater than M!/(N!*(M-N)!). Output, int A[N], array containing the combination set. */ { int i; int j; int k; /* Initialize lower bound index at zero. */ k = 0; /* Loop to select elements in ascending order. */ for ( i = 1; i <= n-1; i++ ) { /* Set lower bound element number for next element value. */ a[i-1] = 0; if ( 1 < i ) { a[i-1] = a[i-2]; } /* Check each element value. */ for ( ; ; ) { a[i-1] = a[i-1] + 1; j = i4_choose ( m-a[i-1], n-i ); k = k + j; if ( rank <= k ) { break; } } k = k - j; } a[n-1] = a[n-2] + rank - k; return; } /******************************************************************************/ int comp_enum ( int n, int k ) /******************************************************************************/ /* Purpose: comp_enum() returns the number of compositions of the integer N into K parts. Discussion: A composition of the integer N into K parts is an ordered sequence of K nonnegative integers which sum to N. The compositions (1,2,1) and (1,1,2) are considered to be distinct. The 28 compositions of 6 into three parts are: 6 0 0, 5 1 0, 5 0 1, 4 2 0, 4 1 1, 4 0 2, 3 3 0, 3 2 1, 3 1 2, 3 0 3, 2 4 0, 2 3 1, 2 2 2, 2 1 3, 2 0 4, 1 5 0, 1 4 1, 1 3 2, 1 2 3, 1 1 4, 1 0 5, 0 6 0, 0 5 1, 0 4 2, 0 3 3, 0 2 4, 0 1 5, 0 0 6. The formula for the number of compositions of N into K parts is Number = ( N + K - 1 )! / ( N! * ( K - 1 )! ) Describe the composition using N '1's and K-1 dividing lines '|'. The number of distinct permutations of these symbols is the number of compositions. This is equal to the number of permutations of N+K-1 things, with N identical of one kind and K-1 identical of another. Thus, for the above example, we have: Number = ( 6 + 3 - 1 )! / ( 6! * (3-1)! ) = 28 Licensing: This code is distributed under the MIT license. Modified: 05 December 2013 Author: John Burkardt Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the integer whose compositions are desired. Input, int K, the number of parts in the composition. Output, int COMP_ENUM, the number of compositions of N into K parts. */ { int number; number = i4_choose ( n + k - 1, n ); return number; } /******************************************************************************/ void comp_next ( int n, int k, int a[], int *more, int *h, int *t ) /******************************************************************************/ /* Purpose: comp_next() computes the compositions of the integer N into K parts. Discussion: A composition of the integer N into K parts is an ordered sequence of K nonnegative integers which sum to N. The compositions (1,2,1) and (1,1,2) are considered to be distinct. The routine computes one composition on each call until there are no more. For instance, one composition of 6 into 3 parts is 3+2+1, another would be 6+0+0. On the first call to this routine, set MORE = FALSE. The routine will compute the first element in the sequence of compositions, and return it, as well as setting MORE = TRUE. If more compositions are desired, call again, and again. Each time, the routine will return with a new composition. However, when the LAST composition in the sequence is computed and returned, the routine will reset MORE to FALSE, signaling that the end of the sequence has been reached. This routine originally used a STATIC statement to maintain the variables H and T. I have decided (based on an wasting an entire morning trying to track down a problem) that it is safer to pass these variables as arguments, even though the user should never alter them. This allows this routine to safely shuffle between several ongoing calculations. There are 28 compositions of 6 into three parts. This routine will produce those compositions in the following order: I A - --------- 1 6 0 0 2 5 1 0 3 4 2 0 4 3 3 0 5 2 4 0 6 1 5 0 7 0 6 0 8 5 0 1 9 4 1 1 10 3 2 1 11 2 3 1 12 1 4 1 13 0 5 1 14 4 0 2 15 3 1 2 16 2 2 2 17 1 3 2 18 0 4 2 19 3 0 3 20 2 1 3 21 1 2 3 22 0 3 3 23 2 0 4 24 1 1 4 25 0 2 4 26 1 0 5 27 0 1 5 28 0 0 6 Licensing: This code is distributed under the MIT license. Modified: 02 July 2008 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the integer whose compositions are desired. Input, int K, the number of parts in the composition. Input/output, int A[K], the parts of the composition. Input/output, int *MORE. Set MORE = FALSE on first call. It will be reset to TRUE on return with a new composition. Each new call returns another composition until MORE is set to FALSE when the last composition has been computed and returned. Input/output, int *H, *T, two internal parameters needed for the computation. The user should allocate space for these in the calling program, include them in the calling sequence, but never alter them! */ { int i; if ( !( *more ) ) { *t = n; *h = 0; a[0] = n; for ( i = 1; i < k; i++ ) { a[i] = 0; } } else { if ( 1 < *t ) { *h = 0; } *h = *h + 1; *t = a[*h-1]; a[*h-1] = 0; a[0] = *t - 1; a[*h] = a[*h] + 1; } *more = ( a[k-1] != n ); return; } /******************************************************************************/ void comp_next_grlex ( int kc, int xc[] ) /******************************************************************************/ /* Purpose: comp_next_grlex() returns the next composition in grlex order. Discussion: Example: KC = 3 # XC(1) XC(2) XC(3) Degree +------------------------ 1 | 0 0 0 0 | 2 | 0 0 1 1 3 | 0 1 0 1 4 | 1 0 0 1 | 5 | 0 0 2 2 6 | 0 1 1 2 7 | 0 2 0 2 8 | 1 0 1 2 9 | 1 1 0 2 10 | 2 0 0 2 | 11 | 0 0 3 3 12 | 0 1 2 3 13 | 0 2 1 3 14 | 0 3 0 3 15 | 1 0 2 3 16 | 1 1 1 3 17 | 1 2 0 3 18 | 2 0 1 3 19 | 2 1 0 3 20 | 3 0 0 3 Licensing: This code is distributed under the MIT license. Modified: 11 December 2013 Author: John Burkardt Parameters: Input, int KC, the number of parts of the composition. 1 <= KC. Input/output, int XC[KC], the current composition. Each entry of XC must be nonnegative. On return, XC has been replaced by the next composition in the grlex order. */ { int i; int im1; int j; int t; /* Ensure that 1 <= KC. */ if ( kc < 1 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "comp_next_grlex(): Fatal error!\n" ); fprintf ( stderr, " KC < 1\n" ); exit ( 1 ); } /* Ensure that 0 <= XC(I). */ for ( i = 0; i < kc; i++ ) { if ( xc[i] < 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "comp_next_grlex(): Fatal error!\n" ); fprintf ( stderr, " XC[I] < 0\n" ); exit ( 1 ); } } /* Find I, the index of the rightmost nonzero entry of X. */ i = 0; for ( j = kc; 1 <= j; j-- ) { if ( 0 < xc[j-1] ) { i = j; break; } } /* set T = X(I) set XC(I) to zero, increase XC(I-1) by 1, increment XC(KC) by T-1. */ if ( i == 0 ) { xc[kc-1] = 1; return; } else if ( i == 1 ) { t = xc[0] + 1; im1 = kc; } else if ( 1 < i ) { t = xc[i-1]; im1 = i - 1; } xc[i-1] = 0; xc[im1-1] = xc[im1-1] + 1; xc[kc-1] = xc[kc-1] + t - 1; return; } /******************************************************************************/ void comp_random ( int n, int k, int *seed, int a[] ) /******************************************************************************/ /* Purpose: comp_random() selects a random composition of the integer N into K parts. Licensing: This code is distributed under the MIT license. Modified: 20 May 2015 Author: FORTRAN77 original version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the integer to be decomposed. Input, int K, the number of parts in the composition. Input/output, int *SEED, a seed for the random number generator. Output, int A[K], the parts of the composition. */ { int *b; int i; int l; int m; b = ( int * ) malloc ( ( k - 1 ) * sizeof ( int ) ); ksub_random2 ( n + k - 1, k - 1, seed, b ); for ( i = 0; i < k - 1; i++ ) { a[i] = b[i]; } a[k-1] = n + k; free ( b ); l = 0; for ( i = 0; i < k; i++ ) { m = a[i]; a[i] = a[i] - l - 1; l = m; } return; } /******************************************************************************/ int *comp_random_grlex ( int kc, int rank1, int rank2, int *seed, int *rank ) /******************************************************************************/ /* Purpose: comp_random_grlex(): random composition with degree less than or equal to NC. Licensing: This code is distributed under the MIT license. Modified: 09 September 2014 Author: John Burkardt Parameters: Input, int KC, the number of parts in the composition. Input, int RANK1, RANK2, the minimum and maximum ranks. 1 <= RANK1 <= RANK2. Input/output, int *SEED, the random number seed. Output, int *RANK, the rank of the composition. Output, int COMP_RANDOM_GRLEX[KC], the random composition. */ { int *xc; /* Ensure that 1 <= KC. */ if ( kc < 1 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "comp_random_grlex(): Fatal error!\n" ); fprintf ( stderr, " KC < 1\n" ); exit ( 1 ); } /* Ensure that 1 <= RANK1. */ if ( rank1 < 1 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "comp_random_grlex(): Fatal error!\n" ); fprintf ( stderr, " RANK1 < 1\n" ); exit ( 1 ); } /* Ensure that RANK1 <= RANK2. */ if ( rank2 < rank1 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "comp_random_grlex(): Fatal error!\n" ); fprintf ( stderr, " RANK2 < RANK1\n" ); exit ( 1 ); } /* Choose RANK between RANK1 and RANK2. */ *rank = i4_uniform_ab ( rank1, rank2, seed ); /* Recover the composition of given RANK. */ xc = comp_unrank_grlex ( kc, *rank ); return xc; } /******************************************************************************/ int comp_rank_grlex ( int kc, int xc[] ) /******************************************************************************/ /* Purpose: comp_rank_grlex() computes the graded lexicographic rank of a composition. Discussion: The graded lexicographic ordering is used, over all KC-compositions for NC = 0, 1, 2, ... For example, if KC = 3, the ranking begins: Rank Sum 1 2 3 ---- --- -- -- -- 1 0 0 0 0 2 1 0 0 1 3 1 0 1 0 4 1 1 0 1 5 2 0 0 2 6 2 0 1 1 7 2 0 2 0 8 2 1 0 1 9 2 1 1 0 10 2 2 0 0 11 3 0 0 3 12 3 0 1 2 13 3 0 2 1 14 3 0 3 0 15 3 1 0 2 16 3 1 1 1 17 3 1 2 0 18 3 2 0 1 19 3 2 1 0 20 3 3 0 0 21 4 0 0 4 .. .. .. .. .. Licensing: This code is distributed under the MIT license. Modified: 11 December 2013 Author: John Burkardt Parameters: Input, int KC, the number of parts in the composition. 1 <= KC. Input, int XC[KC], the composition. For each 1 <= I <= KC, we have 0 <= XC(I). Output, int COMP_RANK_GRLEX, the rank of the composition. */ { int i; int j; int ks; int n; int nc; int ns; int rank; int tim1; int *xs; /* Ensure that 1 <= KC. */ if ( kc < 1 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "comp_rank_grlex(): Fatal error!\n" ); fprintf ( stderr, " KC < 1\n" ); exit ( 1 ); } /* Ensure that 0 <= XC(I). */ for ( i = 0; i < kc; i++ ) { if ( xc[i] < 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "comp_rank_grlex(): Fatal error!\n" ); fprintf ( stderr, " XC[I] < 0\n" ); exit ( 1 ); } } /* NC = sum ( XC ) */ nc = i4vec_sum ( kc, xc ); /* Convert to KSUBSET format. */ ns = nc + kc - 1; ks = kc - 1; xs = ( int * ) malloc ( ks * sizeof ( int ) ); xs[0] = xc[0] + 1; for ( i = 2; i < kc; i++ ) { xs[i-1] = xs[i-2] + xc[i-1] + 1; } /* Compute the rank. */ rank = 1; for ( i = 1; i <= ks; i++ ) { if ( i == 1 ) { tim1 = 0; } else { tim1 = xs[i-2]; } if ( tim1 + 1 <= xs[i-1] - 1 ) { for ( j = tim1 + 1; j <= xs[i-1] - 1; j++ ) { rank = rank + i4_choose ( ns - j, ks - i ); } } } for ( n = 0; n < nc; n++ ) { rank = rank + i4_choose ( n + kc - 1, n ); } free ( xs ); return rank; } /******************************************************************************/ void comp_to_ksub ( int nc, int kc, int ac[], int *ns, int *ks, int as[] ) /******************************************************************************/ /* Purpose: comp_to_ksub() converts a composition to a K-subset. Discussion: There is a bijection between K subsets and compositions. Because we allow a composition to have entries that are 0, we need to implicitly add 1 to each entry before establishing the bijection. Let AC be a composition of NC into KC parts. Then let NS = NC + KC - 1 KS = KC - 1 and define AS(I) = sum ( AC(1:I) + 1 ), for I = 1 : KS. Then AS is a KS subset of the integers 1 through NS. Licensing: This code is distributed under the MIT license. Modified: 04 December 2013 Parameters: Input, int NC, the composition sum. Input, int KC, the number of parts of the composition. Input, int AC[KC], the parts of the composition. Output, int *NS, the size of the set. Output, int *KS, the size of the subset. Output, int AS[KS], the entries of the K-subset, in increasing order. */ { int i; *ns = nc + kc - 1; *ks = kc - 1; as[0] = ac[0] + 1; for ( i = 1; i < kc - 1; i++ ) { as[i] = as[i-1] + ac[i] + 1; } return; } /******************************************************************************/ int *comp_unrank_grlex ( int kc, int rank ) /******************************************************************************/ /* Purpose: comp_unrank_grlex() computes the composition of given grlex rank. Licensing: This code is distributed under the MIT license. Modified: 11 December 2013 Author: John Burkardt Parameters: Input, int KC, the number of parts of the composition. 1 <= KC. Input, int RANK, the rank of the composition. 1 <= RANK. Output, int COMP_UNRANK_GRLEX[KC], the composition XC of the given rank. For each I, 0 <= XC[I] <= NC, and sum ( 1 <= I <= KC ) XC[I] = NC. */ { int i; int j; int ks; int nc; int ns; int r; int rank1; int rank2; int *xc; int *xs; /* Ensure that 1 <= KC. */ if ( kc < 1 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "comp_unrank_grlex(): Fatal error!\n" ); fprintf ( stderr, " KC < 1\n" ); exit ( 1 ); } /* Ensure that 1 <= RANK. */ if ( rank < 1 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "comp_unrank_grlex(): Fatal error!\n" ); fprintf ( stderr, " RANK < 1\n" ); exit ( 1 ); } /* Determine the appropriate value of NC. Do this by adding up the number of compositions of sum 0, 1, 2, ..., without exceeding RANK. Moreover, RANK - this sum essentially gives you the rank of the composition within the set of compositions of sum NC. And that's the number you need in order to do the unranking. */ rank1 = 1; nc = -1; for ( ; ; ) { nc = nc + 1; r = i4_choose ( nc + kc - 1, nc ); if ( rank < rank1 + r ) { break; } rank1 = rank1 + r; } rank2 = rank - rank1; /* Convert to KSUBSET format. Apology: an unranking algorithm was available for KSUBSETS, but not immediately for compositions. One day we will come back and simplify all this. */ ks = kc - 1; ns = nc + kc - 1; xs = ( int * ) malloc ( ks * sizeof ( int ) ); j = 1; for ( i = 1; i <= ks; i++ ) { r = i4_choose ( ns - j, ks - i ); while ( r <= rank2 && 0 < r ) { rank2 = rank2 - r; j = j + 1; r = i4_choose ( ns - j, ks - i ); } xs[i-1] = j; j = j + 1; } /* Convert from KSUBSET format to COMP format. */ xc = ( int * ) malloc ( kc * sizeof ( int ) ); xc[0] = xs[0] - 1; for ( i = 2; i < kc; i++ ) { xc[i-1] = xs[i-1] - xs[i-2] - 1; } xc[kc-1] = ns - xs[ks-1]; free ( xs ); return xc; } /******************************************************************************/ int compnz_enum ( int n, int k ) /******************************************************************************/ /* Purpose: compnz_enum() returns the number of nonzero compositions of the N into K parts. Discussion: A composition of the integer N into K nonzero parts is an ordered sequence of K positive integers which sum to N. The compositions (1,2,1) and (1,1,2) are considered to be distinct. The 10 compositions of 6 into three nonzero parts are: 4 1 1, 3 2 1, 3 1 2, 2 3 1, 2 2 2, 2 1 3, 1 4 1, 1 3 2, 1 2 3, 1 1 4. The formula for the number of compositions of N into K nonzero parts is Number = ( N - 1 )! / ( ( N - K )! * ( K - 1 )! ) (Describe the composition using N-K '1's and K-1 dividing lines '|'. The number of distinct permutations of these symbols is the number of compositions into nonzero parts. This is equal to the number of permutations of N-1 things, with N-K identical of one kind and K-1 identical of another.) Thus, for the above example, we have: Number = ( 6 - 1 )! / ( ( 6 - 3 )! * ( 3 - 1 )! ) = 10 Licensing: This code is distributed under the MIT license. Modified: 05 December 2013 Author: John Burkardt Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the integer whose compositions are desired. Input, int K, the number of parts in the composition. Output, int COMP_ENUM, the number of compositions of N into K nonzero parts. */ { int number; number = i4_choose ( n - 1, n - k ); return number; } /******************************************************************************/ void compnz_next ( int n, int k, int a[], int *more, int *h, int *t ) /******************************************************************************/ /* Purpose: compnz_next() computes the compositions of the integer N into K nonzero parts. Discussion: A composition of the integer N into K nonzero parts is an ordered sequence of K positive integers which sum to N. The compositions (1,2,1) and (1,1,2) are considered to be distinct. The routine computes one composition on each call until there are no more. For instance, one composition of 6 into 3 parts is 3+2+1, another would be 4+1+1 but 5+1+0 is not allowed since it includes a zero part. On the first call to this routine, set MORE = FALSE. The routine will compute the first element in the sequence of compositions, and return it, as well as setting MORE = TRUE. If more compositions are desired, call again, and again. Each time, the routine will return with a new composition. However, when the LAST composition in the sequence is computed and returned, the routine will reset MORE to FALSE, signaling that the end of the sequence has been reached. Example: The 10 compositions of 6 into three nonzero parts are: 4 1 1, 3 2 1, 3 1 2, 2 3 1, 2 2 2, 2 1 3, 1 4 1, 1 3 2, 1 2 3, 1 1 4. Licensing: This code is distributed under the MIT license. Modified: 22 May 2015 Author: John Burkardt Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the integer whose compositions are desired. Input, int K, the number of parts in the composition. K must be no greater than N. Input/output, int A[K], the parts of the composition. Input/output, int *MORE. Set MORE = FALSE on first call. It will be reset to TRUE on return with a new composition. Each new call returns another composition until MORE is set to FALSE when the last composition has been computed and returned. Input/output, int *H, *T, two internal parameters needed for the computation. The user should allocate space for these in the calling program, include them in the calling sequence, but never alter them! */ { int i; /* We use the trick of computing ordinary compositions of (N-K) into K parts, and adding 1 to each part. */ if ( n < k ) { *more = 0; for ( i = 0; i < k; i++ ) { a[i] = -1; } return; } /* The first computation. */ if ( !( *more ) ) { *t = n - k; *h = 0; a[0] = n - k; for ( i = 1; i < k; i++ ) { a[i] = 0; } } else { for ( i = 0; i < k; i++ ) { a[i] = a[i] - 1; } if ( 1 < *t ) { *h = 0; } *h = *h + 1; *t = a[*h-1]; a[*h-1] = 0; a[0] = *t - 1; a[*h] = a[*h] + 1; } *more = ( a[k-1] != ( n - k ) ); for ( i = 0; i < k; i++ ) { a[i] = a[i] + 1; } return; } /******************************************************************************/ void compnz_random ( int n, int k, int *seed, int a[] ) /******************************************************************************/ /* Purpose: compnz_random() selects a random composition of the integer N into K nonzero parts. Licensing: This code is distributed under the MIT license. Modified: 01 December 2005 Author: John Burkardt Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the integer to be decomposed. Input, int K, the number of parts in the composition. K must be no greater than N. Input/output, int *SEED, a seed for the random number generator. Output, int A[K], the parts of the composition. */ { int i; int l; int m; if ( n < k ) { for ( i = 0; i < k; i++ ) { a[i] = -1; } return; } if ( 1 < k ) { ksub_random ( n - 1, k - 1, seed, a ); } a[k-1] = n; l = 0; for ( i = 0; i < k; i++ ) { m = a[i]; a[i] = a[i] - l - 1; l = m; } for ( i = 0; i < k; i++ ) { a[i] = a[i] + 1; } return; } /******************************************************************************/ void compnz_to_ksub ( int nc, int kc, int ac[], int *ns, int *ks, int as[] ) /******************************************************************************/ /* Purpose: compnz_to_ksub() converts a nonzero composition to a K-subset. Discussion: There is a bijection between K subsets and compositions. Let AC be a composition of NC into KC parts. Then let NS = NC - 1 KS = KC - 1 and define AS(I) = sum ( AC(1:I) ), for I = 1 : KS. Then AS is a KS subset of the integers 1 through NS. Licensing: This code is distributed under the MIT license. Modified: 24 May 2014 Author: John Burkardt Parameters: Input, int NC, the composition sum. Input, int KC, the number of parts of the composition. Input, int AC[KC], the parts of the composition. Output, int *NS, the size of the set. Output, int *KS, the size of the subset. Output, int AS[KS], the entries of the K-subset, in increasing order. */ { int i; *ns = nc - 1; *ks = kc - 1; as[0] = ac[0]; for ( i = 1; i < kc - 1; i++ ) { as[i] = as[i-1] + ac[i]; } return; } /******************************************************************************/ int congruence ( int a, int b, int c, int *error ) /******************************************************************************/ /* Purpose: congruence() solves a congruence of the form A * X = C ( mod B ). Discussion: A, B and C are given integers. The equation is solvable if and only if the greatest common divisor of A and B also divides C. Licensing: This code is distributed under the MIT license. Modified: 15 November 2004 Author: John Burkardt Reference: Eric Weisstein, editor, CRC Concise Encylopedia of Mathematics, CRC Press, 1998, page 446. Parameters: Input, int A, B, C, the coefficients of the Diophantine equation. Output, int *ERROR, error flag, is 1 if an error occurred.. Output, int CONGRUENCE, the solution of the Diophantine equation. X will be between 0 and B-1. */ { # define N_MAX 100 int a_copy; int a_mag; int a_sign; int b_copy; int b_mag; int c_copy; int g; int k; int n; int q[N_MAX]; int swap; int x; int y; int z; /* Defaults for output parameters. */ *error = 0; x = 0; y = 0; /* Special cases. */ if ( a == 0 && b == 0 && c == 0 ) { x = 0; return x; } else if ( a == 0 && b == 0 && c != 0 ) { *error = 1; x = 0; return x; } else if ( a == 0 && b != 0 && c == 0 ) { x = 0; return x; } else if ( a == 0 && b != 0 && c != 0 ) { x = 0; if ( ( c % b ) != 0 ) { *error = 2; } return x; } else if ( a != 0 && b == 0 && c == 0 ) { x = 0; return x; } else if ( a != 0 && b == 0 && c != 0 ) { x = c / a; if ( ( c % a ) != 0 ) { *error = 3; return x; } return x; } else if ( a != 0 && b != 0 && c == 0 ) { /* g = i4_gcd ( a, b ); */ /* x = b / g; */ x = 0; return x; } /* Now handle the "general" case: A, B and C are nonzero. Step 1: Compute the GCD of A and B, which must also divide C. */ g = i4_gcd ( a, b ); if ( ( c % g ) != 0 ) { *error = 4; return x; } a_copy = a / g; b_copy = b / g; c_copy = c / g; /* Step 2: Split A and B into sign and magnitude. */ a_mag = abs ( a_copy ); a_sign = i4_sign ( a_copy ); b_mag = abs ( b_copy ); /* Another special case, A_MAG = 1 or B_MAG = 1. */ if ( a_mag == 1 ) { x = a_sign * c_copy; return x; } else if ( b_mag == 1 ) { x = 0; return x; } /* Step 3: Produce the Euclidean remainder sequence. */ if ( b_mag <= a_mag ) { swap = 0; q[0] = a_mag; q[1] = b_mag; } else { swap = 1; q[0] = b_mag; q[1] = a_mag; } n = 3; for ( ; ; ) { q[n-1] = ( q[n-3] % q[n-2] ); if ( q[n-1] == 1 ) { break; } n = n + 1; if ( N_MAX < n ) { *error = 1; fprintf ( stderr, "\n" ); fprintf ( stderr, "congruence(): Fatal error!\n" ); fprintf ( stderr, " Exceeded number of iterations.\n" ); exit ( 1 ); } } /* Step 4: Now go backwards to solve X * A_MAG + Y * B_MAG = 1. */ y = 0; for ( k = n; 2 <= k; k-- ) { x = y; y = ( 1 - x * q[k-2] ) / q[k-1]; } /* Step 5: Undo the swapping. */ if ( swap == 1 ) { z = x; x = y; y = z; } /* Step 6: Now apply signs to X and Y so that X * A + Y * B = 1. */ x = x * a_sign; /* Step 7: Multiply by C, so that X * A + Y * B = C. */ x = x * c_copy; /* Step 8: Now force 0 <= X < B. */ x = x % b; /* Step 9: Force positivity. */ if ( x < 0 ) { x = x + b; } return x; # undef N_MAX } /******************************************************************************/ void count_pose_random ( int *seed, int blocks[], int *goal ) /******************************************************************************/ /* Purpose: count_pose_random() poses a problem for the game "The Count is Good" Discussion: The French television show "The Count is Good" has a game that goes as follows: A number is chosen at random between 100 and 999. This is the GOAL. Six numbers are randomly chosen from the set 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 25, 50, 75, 100. These numbers are the BLOCKS. The player must construct a formula, using some or all of the blocks, (but not more than once), and the operations of addition, subtraction, multiplication and division. Parentheses should be used to remove all ambiguity. However, it is forbidden to use subtraction in a way that produces a negative result, and all division must come out exactly, with no remainder. This routine poses a sample problem from the show. The point is, to determine how to write a program that can solve such a problem. Licensing: This code is distributed under the MIT license. Modified: 19 June 2003 Author: John Burkardt Reference: Raymond Seroul, Programming for Mathematicians, Springer Verlag, 2000, page 355-357. Parameters: Input/output, int *SEED, a seed for the random number generator. Output, int BLOCKS[6], the six numbers available for the formula. Output, int *GOAL, the goal number. */ { int i; int ind[6]; const int stuff[14] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 25, 50, 75, 100 }; *goal = i4_uniform_ab ( 100, 999, seed ); ksub_random ( 14, 6, seed, ind ); for ( i = 0; i < 6; i++ ) { blocks[i] = stuff[ind[i]-1]; } return; } /******************************************************************************/ void debruijn ( int m, int n, int string[] ) /******************************************************************************/ /* Purpose: debruijn() constructs a de Bruijn sequence. Discussion: Suppose we have an alphabet of M letters, and we are interested in all possible strings of length N. If M = 2 and N = 3, then we are interested in the M^N strings: 000 001 010 011 100 101 110 111 Now, instead of making a list like this, we prefer, if possible, to write a string of letters, such that every consecutive sequence of N letters is one of the strings, and every string occurs once, if we allow wraparound. For the above example, a suitable sequence would be the 8 characters: 00011101(00... where we have suggested the wraparound feature by repeating the first two characters at the end. Such a sequence is called a de Bruijn sequence. It can easily be constructed by considering a directed graph, whose nodes are all M^(N-1) strings of length N-1. A node I has a directed edge to node J (labeled with character K) if the string at node J can be constructed by beheading the string at node I and adding character K. In this setting, a de Bruijn sequence is simply an Eulerian circuit of the directed graph, with the edge labels being the entries of the sequence. In general, there are many distinct de Bruijn sequences for the same parameter M and N. This program will only find one of them. Licensing: This code is distributed under the MIT license. Modified: 25 March 2009 Author: John Burkardt Parameters: Input, int M, the number of letters in the alphabet. Input, int N, the number of letters in a codeword. Output, int STRING[M^N], a deBruijn string. */ { int i; int iedge; int *inode; int *ivec; int j; int *jnode; int *jvec; int k; int *knode; int nedge; int nnode; int success; int *trail; /* Construct the adjacency information. */ nnode = i4_power ( m, n-1 ); nedge = i4_power ( m, n ); inode = ( int * ) malloc ( nedge * sizeof ( int ) ); ivec = ( int * ) malloc ( ( n - 1 ) * sizeof ( int ) ); jnode = ( int * ) malloc ( nedge * sizeof ( int ) ); jvec = ( int * ) malloc ( ( n - 1 ) * sizeof ( int ) ); knode = ( int * ) malloc ( nedge * sizeof ( int ) ); iedge = 0; for ( i = 1; i <= nnode; i++ ) { index_unrank0 ( n-1, m, i, ivec ); for ( k = 1; k <= m; k++ ) { /* Shift N-2 entries of IVEC down. */ for ( j = 0; j < n-2; j++ ) { jvec[j] = ivec[j+1]; } jvec[n-2] = k; j = index_rank0 ( n-1, m, jvec ); inode[iedge] = i; jnode[iedge] = j; knode[iedge] = k; iedge = iedge + 1; } } free ( ivec ); free ( jvec ); /* Determine a circuit. */ trail = ( int * ) malloc ( nedge * sizeof ( int ) ); digraph_arc_euler ( nnode, nedge, inode, jnode, &success, trail ); /* The string is constructed from the labels of the edges in the circuit. */ for ( i = 0; i < nedge; i++ ) { string[i] = knode[trail[i]-1]; } free ( inode ); free ( jnode ); free ( knode ); free ( trail ); return; } /******************************************************************************/ void dec_add ( int mantissa1, int exponent1, int mantissa2, int exponent2, int dec_digit, int *mantissa, int *exponent ) /******************************************************************************/ /* Purpose: dec_add() adds two decimal quantities. Discussion: A decimal value is represented as MANTISSA * 10^EXPONENT. The routine computes MANTISSA * 10^EXPONENT = MANTISSA1 * 10^EXPONENT1 + MANTISSA2 * 10^EXPONENT2 using DEC_DIGIT arithmetic. Licensing: This code is distributed under the MIT license. Modified: 22 March 2009 Author: John Burkardt Parameters: Input, int MANTISSA1, EXPONENT1, the first number to be added. Input, int MANTISSA2, EXPONENT2, the second number to be added. Input, int DEC_DIGIT, the number of decimal digits. Output, int *MANTISSA, *EXPONENT, the sum. */ { if ( mantissa1 == 0 ) { *mantissa = mantissa2; *exponent = exponent2; dec_round ( *mantissa, *exponent, dec_digit, mantissa, exponent ); return; } else if ( mantissa2 == 0 ) { *mantissa = mantissa1; *exponent = exponent1; dec_round ( *mantissa, *exponent, dec_digit, mantissa, exponent ); return; } /* Line up the exponents. */ if ( exponent1 < exponent2 ) { mantissa2 = mantissa2 * i4_power ( 10, exponent2 - exponent1 ); exponent2 = exponent1; *mantissa = mantissa1 + mantissa2; *exponent = exponent1; } else if ( exponent1 == exponent2 ) { *mantissa = mantissa1 + mantissa2; *exponent = exponent1; } else if ( exponent2 < exponent1 ) { mantissa1 = mantissa1 * i4_power ( 10, exponent1 - exponent2 ); exponent1 = exponent2; *mantissa = mantissa1 + mantissa2; *exponent = exponent2; } /* Clean up the result. */ dec_round ( *mantissa, *exponent, dec_digit, mantissa, exponent ); return; } /******************************************************************************/ void dec_div ( int mantissa1, int exponent1, int mantissa2, int exponent2, int dec_digit, int *mantissa, int *exponent, int *error ) /******************************************************************************/ /* Purpose: dec_div() divides two decimal values. Discussion: A decimal value is represented as MANTISSA * 10^EXPONENT. The routine computes MANTISSA * 10^EXPONENT = (MANTISSA1 * 10^EXPONENT1) / (MANTISSA2 * 10^EXPONENT2) = (MANTISSA1/MANTISSA2) * 10^(EXPONENT1-EXPONENT2) while avoiding integer overflow. Licensing: This code is distributed under the MIT license. Modified: 22 March 2009 Author: John Burkardt Parameters: Input, int MANTISSA1, EXPONENT1, the numerator. Input, int MANTISSA2, EXPONENT2, the denominator. Input, int DEC_DIGIT, the number of decimal digits. Output, int MANTISSA, EXPONENT, the result. Output, int *ERROR is true if an error occurred. */ { double dval; int exponent3; int mantissa3; *error = 0; /* First special case, top fraction is 0. */ if ( mantissa1 == 0 ) { *mantissa = 0; *exponent = 0; return; } /* First error, bottom of fraction is 0. */ if ( mantissa2 == 0 ) { *error = 1; *mantissa = 0; *exponent = 0; return; } /* Second special case, result is 1. */ if ( mantissa1 == mantissa2 && exponent1 == exponent2 ) { *mantissa = 1; *exponent = 0; return; } /* Third special case, result is power of 10. */ if ( mantissa1 == mantissa2 ) { *mantissa = 1; *exponent = exponent1 - exponent2; return; } /* Fourth special case: MANTISSA1/MANTISSA2 is exact. */ if ( ( mantissa1 / mantissa2 ) * mantissa2 == mantissa1 ) { *mantissa = mantissa1 / mantissa2; *exponent = exponent1 - exponent2; return; } /* General case. */ dval = ( double ) mantissa1 / ( double ) mantissa2; r8_to_dec ( dval, dec_digit, &mantissa3, &exponent3 ); *mantissa = mantissa3; *exponent = exponent3 + exponent1 - exponent2; return; } /******************************************************************************/ void dec_mul ( int mantissa1, int exponent1, int mantissa2, int exponent2, int dec_digit, int *mantissa, int *exponent ) /******************************************************************************/ /* Purpose: dec_mul() multiplies two decimals. Discussion: A decimal value is represented as MANTISSA * 10^EXPONENT. The routine computes MANTISSA * 10^EXPONENT = (MANTISSA1 * 10^EXPONENT1) * (MANTISSA2 * 10^EXPONENT2) = (MANTISSA1*MANTISSA2) * 10^(EXPONENT1+EXPONENT2) while avoiding integer overflow. Licensing: This code is distributed under the MIT license. Modified: 13 January 2014 Author: John Burkardt Parameters: Input, int MANTISSA1, EXPONENT1, the first multiplier. Input, int MANTISSA2, EXPONENT2, the second multiplier. Input, int DEC_DIGIT, the number of decimal digits. Output, int *MANTISSA, *EXPONENT, the product. */ { double dval; int exponent3; int mantissa3; double temp; /* The result is zero if either MANTISSA1 or MANTISSA2 is zero. */ if ( mantissa1 == 0 || mantissa2 == 0 ) { *mantissa = 0; *exponent = 0; return; } /* The result is simple if either MANTISSA1 or MANTISSA2 is one. */ if ( abs ( mantissa1 ) == 1 || abs ( mantissa2 ) == 1 ) { *mantissa = mantissa1 * mantissa2; *exponent = exponent1 + exponent2; return; } temp = log ( ( double ) abs ( mantissa1 ) ) + log ( ( double ) abs ( mantissa2 ) ); if ( temp < log ( ( double ) i4_huge ( ) ) ) { *mantissa = mantissa1 * mantissa2; *exponent = exponent1 + exponent2; } else { dval = ( double ) mantissa1 * ( double ) mantissa2; r8_to_dec ( dval, dec_digit, &mantissa3, &exponent3 ); *mantissa = mantissa3; *exponent = exponent3 + ( exponent1 + exponent2 ); } dec_round ( *mantissa, *exponent, dec_digit, mantissa, exponent ); return; } /******************************************************************************/ void dec_round ( int mantissa1, int exponent1, int dec_digit, int *mantissa2, int *exponent2 ) /******************************************************************************/ /* Purpose: dec_round() rounds a decimal fraction to a given number of digits. Discussion: A decimal value is represented as MANTISSA * 10^EXPONENT. The routine takes an arbitrary decimal value and makes sure that MANTISSA has no more than DEC_DIGIT digits. Licensing: This code is distributed under the MIT license. Modified: 22 March 2009 Author: John Burkardt Parameters: Input, int MANTISSA1, *EXPONENT1, the coefficient and exponent of a decimal fraction to be rounded. Input, int DEC_DIGIT, the number of decimal digits. Output, int *MANTISSA2, *EXPONENT2, the rounded coefficient and exponent of a decimal fraction. MANTISSA2 has no more than DEC_DIGIT decimal digits. */ { int i; int limit; int sgn; *mantissa2 = mantissa1; *exponent2 = exponent1; /* Watch out for the special case of 0. */ if ( *mantissa2 == 0 ) { *exponent2 = 0; return; } /* Record the sign of MANTISSA. */ sgn = 1; if ( *mantissa2 < 0 ) { *mantissa2 = - ( *mantissa2 ); sgn = - sgn; } /* If MANTISSA is too big, knock it down. */ limit = 1; for ( i = 1; i <= dec_digit; i++ ) { limit = limit * 10; } while ( limit <= abs ( *mantissa2 ) ) { *mantissa2 = ( *mantissa2 + 5 ) / 10; *exponent2 = *exponent2 + 1; } /* Absorb trailing 0's into the exponent. */ if ( 0 < *mantissa2 ) { while ( ( *mantissa2 / 10 ) * 10 == *mantissa2 ) { *mantissa2 = *mantissa2 / 10; *exponent2 = *exponent2 + 1; } } *mantissa2 = sgn * ( *mantissa2 ); return; } /******************************************************************************/ double dec_to_r8 ( int mantissa, int exponent ) /******************************************************************************/ /* Purpose: dec_to_r8() converts a decimal value to an R8. Discussion: A decimal value is represented as MANTISSA * 10^EXPONENT. Licensing: This code is distributed under the MIT license. Modified: 21 March 2009 Author: John Burkardt Parameters: Input, int MANTISSA, EXPONENT, the coefficient and exponent of the decimal value. Output, double DEC_TO_R8, the real value of the decimal. */ { double value; value = mantissa * pow ( 10.0, exponent ); return value; } /******************************************************************************/ void dec_to_rat ( int mantissa, int exponent, int *rat_top, int *rat_bot ) /******************************************************************************/ /* Purpose: dec_to_rat() converts a decimal to a rational representation. Discussion: A decimal value is represented as MANTISSA * 10^EXPONENT. A rational value is represented by RAT_TOP / RAT_BOT. Licensing: This code is distributed under the MIT license. Modified: 25 March 2009 Author: John Burkardt Parameters: Input, int MANTISSA, EXPONENT, the decimal number. Output, int *RAT_TOP, *RAT_BOT, the rational value. */ { int gcd; int i; if ( exponent == 0 ) { *rat_top = mantissa; *rat_bot = 1; } else if ( 0 < exponent ) { *rat_top = mantissa; for ( i = 1; i <= exponent; i++ ) { *rat_top = *rat_top * 10; } *rat_bot = 1; } else { *rat_top = mantissa; *rat_bot = 1; for ( i = 1; i <= -exponent; i++ ) { *rat_bot = *rat_bot * 10; } gcd = i4_gcd ( *rat_top, *rat_bot ); *rat_top = *rat_top / gcd; *rat_bot = *rat_bot / gcd; } return; } /******************************************************************************/ char *dec_to_s ( int mantissa, int exponent ) /******************************************************************************/ /* Purpose: dec_to_s() converts a decimal number to a string. Discussion: This is a draft version that is NOT WORKING YET. Example: Mantissa Exponent Representation: 523 -1 5.23 134 2 13400 0 10 0 123456 3 123456000 123456 2 12345600 123456 1 1234560 123456 0 123456 123456 -1 12345.6 123456 -2 1234.56 123456 -3 123.456 123456 -4 12.3456 123456 -5 1.23456 123456 -6 0.123456 123456 -7 0.0123456 123456 -8 0.00123456 123456 -9 0.000123456 Licensing: This code is distributed under the MIT license. Modified: 25 March 2009 Author: John Burkardt Parameters: Input, int MANTISSA, EXPONENT, integers which represent the decimal. Output, char *S, the representation of the value. */ { int digit; int i; int mantissa_exponent; int mantissa_exponent_copy; int mantissa_10; int pos; char *s; int s_length; s_length = dec_width ( mantissa, exponent ) + 1; s = ( char * ) malloc ( s_length * sizeof ( char ) ); for ( i = 0; i < s_length - 1; i++ ) { s[i] = '0'; } s[s_length-1] = '\0'; if ( mantissa == 0 ) { return s; } pos = 0; if ( mantissa < 0 ) { s[pos] = '-'; pos = pos + 1; mantissa = -mantissa; } mantissa_exponent = i4_log_10 ( mantissa ) + 1; mantissa_10 = i4_power ( 10, mantissa_exponent - 1 ); /* Are the next characters "0."? */ if ( mantissa_exponent + exponent <= 0 ) { s[pos] = '0'; pos = pos + 1; s[pos] = '.'; pos = pos + 1; for ( i = mantissa_exponent + exponent; i < 0; i++ ) { s[pos] = '0'; pos = pos + 1; } } /* Print the digits of the mantissa. */ mantissa_exponent_copy = mantissa_exponent; for ( i = 0; i < mantissa_exponent; i++ ) { digit = mantissa / mantissa_10; mantissa = mantissa % mantissa_10; s[pos] = digit_to_ch ( digit ); pos = pos + 1; mantissa_10 = mantissa_10 / 10; mantissa_exponent_copy = mantissa_exponent_copy - 1; if ( exponent < 0 ) { if ( mantissa_exponent_copy + exponent == 0 ) { s[pos] = '.'; pos = pos + 1; } } } /* Print any trailing zeros. */ if ( 0 < exponent ) { for ( i = exponent; 0 < i; i-- ) { s[pos] = '0'; pos = pos + 1; } } return s; } /******************************************************************************/ int dec_width ( int mantissa, int exponent ) /******************************************************************************/ /* Purpose: dec_width() returns the "width" of a decimal number. Discussion: A decimal value is represented as MANTISSA * 10^EXPONENT. The "width" of a decimal number is the number of characters required to print it. Example: Mantissa Exponent Width Representation: 523 -1 4 5.23 134 2 5 13400 0 10 1 0 123456 3 9 123456000 123456 2 8 12345600 123456 1 7 1234560 123456 0 6 123456 123456 -1 7 12345.6 123456 -2 7 1234.56 123456 -3 7 123.456 123456 -4 7 12.3456 123456 -5 7 1.23456 123456 -6 8 0.123456 123456 -7 9 0.0123456 123456 -8 10 0.00123456 123456 -9 11 0.000123456 Licensing: This code is distributed under the MIT license. Modified: 25 March 2009 Author: John Burkardt Parameters: Input, int MANTISSA, EXPONENT, the decimal number. Output, int DEC_WIDTH, the "width" of the decimal number. */ { int mantissa_abs; int ten_pow; int value; /* Special case of 0. */ value = 1; if ( mantissa == 0 ) { return value; } /* Determine a power of 10 that is strictly bigger than MANTISSA. The exponent of that power of 10 is our first estimate for the number of places. */ ten_pow = 10; mantissa_abs = abs ( mantissa ); while ( ten_pow <= mantissa_abs ) { value = value + 1; ten_pow = ten_pow * 10; } /* If the exponent is nonnegative, that just adds more places. */ if ( 0 <= exponent ) { value = value + exponent; } /* If the exponent is a little negative, then we are essentially just inserting a decimal point, and moving it around. */ else if ( -value < exponent ) { value = value + 1; } /* A very negative value of B means we have a leading 0 and decimal, and B trailing places. */ else if ( exponent <= -value ) { value = 2 - exponent; } /* Take care of sign of MANTISSA. */ if ( mantissa < 0 ) { value = value + 1; } return value; } /******************************************************************************/ void decmat_det ( int n, int atop[], int abot[], int dec_digit, int *dtop, int *dbot ) /******************************************************************************/ /* Purpose: decmat_det() finds the determinant of an N by N matrix of decimal entries. Discussion: The brute force method is used. The routine should only be used for small matrices, since this calculation requires the summation of N! products of N numbers. Licensing: This code is distributed under the MIT license. Modified: 30 October 2014 Author: John Burkardt Parameters: Input, int N, the number of rows and columns of A. Input, int ATOP[N*N], ABOT[N*N], the decimal representation of the matrix. Input, int DEC_DIGIT, the number of decimal digits. Output, int *DTOP, *DBOT, the decimal determinant of the matrix. */ { int even; int i; int *iarray; int ibot; int ibot1; int ibot2; int itop; int itop1; int itop2; int more; *dtop = 0; *dbot = 1; iarray = ( int * ) malloc ( n * sizeof ( int ) ); /* Compute the next permutation. */ more = 0; for ( ; ; ) { perm0_next ( n, iarray, &more, &even ); /* The sign of this term depends on the sign of the permutation. */ if ( even ) { itop = 1; } else { itop = -1; } ibot = 0; /* Choose one item from each row, as specified by the permutation, and multiply them. */ for ( i = 0; i < n; i++ ) { itop1 = itop; ibot1 = ibot; itop2 = atop[i+iarray[i]*n]; ibot2 = abot[i+iarray[i]*n]; dec_mul ( itop1, ibot1, itop2, ibot2, dec_digit, &itop, &ibot ); } /* Add this term to the total. */ dec_add ( itop, ibot, *dtop, *dbot, dec_digit, dtop, dbot ); if ( !more ) { break; } } free ( iarray ); return; } /******************************************************************************/ void decmat_print ( int m, int n, int a[], int b[], char *title ) /******************************************************************************/ /* Purpose: decmat_print() prints out decimal vectors and matrices. Licensing: This code is distributed under the MIT license. Modified: 25 March 2009 Author: John Burkardt Parameters: Input, int M, N, the number of rows and columns in the matrix. Input, int A[M*N], B[M*N], the decimal matrix. Input, char *TITLE, a label for the object being printed. */ { int exponent; int i; int j; int jmax; int jmin; int kmax; int mantissa; int ncolum = 80; int npline; char *s; /* Figure out how wide we must make each column. */ kmax = 0; for ( i = 0; i < m; i++ ) { for ( j = 0; j < n; j++ ) { kmax = i4_max ( kmax, dec_width ( a[i+j*m], b[i+j*m] ) ); } } kmax = kmax + 2; npline = ncolum / kmax; /* Now do the printing. */ for ( jmin = 0; jmin < n; jmin = jmin + npline ) { jmax = i4_min ( jmin+npline-1, n-1 ); printf ( "\n" ); printf ( "%s\n", title ); printf ( "\n" ); if ( 0 < jmin || jmax < n-1 ) { printf ( "Columns %d to %d\n", jmin, jmax ); printf ( "\n" ); } for ( i = 0; i < m; i++ ) { for ( j = jmin; j <= jmax; j++ ) { mantissa = a[i+j*m]; exponent = b[i+j*m]; s = dec_to_s ( mantissa, exponent ); printf ( "%s ", s ); free ( s ); } printf ( "\n" ); } } return; } /******************************************************************************/ int derange_enum ( int n ) /******************************************************************************/ /* Purpose: derange_enum() returns the number of derangements of N objects. Discussion: A derangement of N objects is a permutation which leaves no object unchanged. A derangement of N objects is a permutation with no fixed points. If we symbolize the permutation operation by "P", then for a derangment, P(I) is never equal to I. The number of derangements of N objects is sometimes called the subfactorial function, or the derangement number D(N). D(N) is the number of ways of placing N non-attacking rooks on an N by N chessboard with one diagonal deleted. Limit ( N -> Infinity ) D(N)/N! = 1 / e. The number of permutations with exactly K items in the right place is COMB(N,K) * D(N-K). The formula: D(N) = N! * ( 1 - 1/1! + 1/2! - 1/3! ... 1/N! ) based on the inclusion/exclusion law. Recursion: D(0) = 1 D(1) = 0 D(2) = 1 D(N) = (N-1) * ( D(N-1) + D(N-2) ) or D(0) = 1 D(1) = 0 D(N) = N * D(N-1) + (-1)^N First values: N D(N) 0 1 1 0 2 1 3 2 4 9 5 44 6 265 7 1854 8 14833 9 133496 10 1334961 Licensing: This code is distributed under the MIT license. Modified: 28 May 2003 Author: John Burkardt Parameters: Input, int N, the number of objects to be permuted. Output, int DERANGE_ENUM, the number of derangements of N objects. */ { int i; int value; int value1; int value2; if ( n < 0 ) { value = 0; } else if ( n == 0 ) { value = 1; } else if ( n == 1 ) { value = 0; } else if ( n == 2 ) { value = 1; } else { value1 = 0; value = 1; for ( i = 3; i <= n; i++ ) { value2 = value1; value1 = value; value = ( i - 1 ) * ( value1 + value2 ); } } return value; } /******************************************************************************/ void derange_enum2 ( int n, int d[] ) /******************************************************************************/ /* Purpose: derange_enum2() returns the number of derangements of 0 through N objects. Discussion: A derangement of N objects is a permutation which leaves no object unchanged. A derangement of N objects is a permutation with no fixed points. If we symbolize the permutation operation by "P", then for a derangment, P(I) is never equal to I. The number of derangements of N objects is sometimes called the subfactorial function, or the derangement number D(N). D(N) is the number of ways of placing N non-attacking rooks on an N by N chessboard with one diagonal deleted. Limit ( N -> Infinity ) D(N)/N! = 1 / e. The number of permutations with exactly K items in the right place is COMB(N,K) * D(N-K). The formula is: D(N) = N! * ( 1 - 1/1! + 1/2! - 1/3! ... 1/N! ) based on the inclusion/exclusion law. Recursion: D(0) = 1 D(1) = 0 D(2) = 1 D(N) = (N-1) * ( D(N-1) + D(N-2) ) or D(0) = 1 D(1) = 0 D(N) = N * D(N-1) + (-1)^N Example: N D(N) 0 1 1 0 2 1 3 2 4 9 5 44 6 265 7 1854 8 14833 9 133496 10 1334961 Licensing: This code is distributed under the MIT license. Modified: 25 March 2009 Author: John Burkardt Parameters: Input, int N, the maximum number of objects to be permuted. Output, int D[N+1]; D(I) is the number of derangements of I objects. */ { int i; d[0] = 1; d[1] = 0; for ( i = 2; i <= n; i++ ) { d[i] = ( i - 1 ) * ( d[i-1] + d[i-2] ); } return; } /******************************************************************************/ int derange_enum3 ( int n ) /******************************************************************************/ /* Purpose: derange_enum3() returns the number of derangements of 0 through N objects. Discussion: A derangement of N objects is a permutation which leaves no object unchanged. A derangement of N objects is a permutation with no fixed points. If we symbolize the permutation operation by "P", then for a derangment, P(I) is never equal to I. The number of derangements of N objects is sometimes called the subfactorial function, or the derangement number D(N). D(N) is the number of ways of placing N non-attacking rooks on an N by N chessboard with one diagonal deleted. Limit ( N -> Infinity ) D(N)/N! = 1 / e. The number of permutations with exactly K items in the right place is COMB(N,K) * D(N-K). The formula is: D(N) = N! * ( 1 - 1/1! + 1/2! - 1/3! ... 1/N! ) based on the inclusion/exclusion law. D(N) = nint ( N! / E ) Recursion: D(0) = 1 D(1) = 0 D(2) = 1 D(N) = (N-1) * ( D(N-1) + D(N-2) ) or D(0) = 1 D(1) = 0 D(N) = N * D(N-1) + (-1)^N Example: N D(N) 0 1 1 0 2 1 3 2 4 9 5 44 6 265 7 1854 8 14833 9 133496 10 1334961 Licensing: This code is distributed under the MIT license. Modified: 25 March 2009 Author: John Burkardt Parameters: Input, int N, the maximum number of objects to be permuted. Output, int DERANGE_ENUM3, the number of derangements of N objects. */ { # define E 2.718281828459045 int value; if ( n < 0 ) { value = -1; } else if ( n == 0 ) { value = 1; } else if ( n == 1 ) { value = 0; } else { value = ( int ) ( 0.5 + ( r8_factorial ( n ) / E ) ); } return value; # undef E } /******************************************************************************/ void derange0_back_candidate ( int n, int a[], int k, int *nstack, int stack[], int ncan[] ) /******************************************************************************/ /* Purpose: derange0_back_candidate() finds possible K-th entries of a derangement. Discussion: A derangement of N objects is a permutation of (0,...,N-1) which leaves no object unchanged. A derangement of N objects is a permutation with no fixed points. If we symbolize the permutation operation by "P", then for a derangment, P(I) is never equal to I. The number of derangements of N objects is sometimes called the subfactorial function, or the derangement number D(N). Licensing: This code is distributed under the MIT license. Modified: 19 June 2015 Author: John Burkardt Parameters: Input, int N, the order of the derangement. Input, int A[N]. The first K-1 entries of A record the currently set values of the derangement. Input, int K, the entry of the derangement for which candidates are to be found. Input/output, int *NSTACK, the length of the stack. Input/output, int STACK[(N*(N+1))/2]. On output, we have added the candidates for entry K to the end of the stack. Input/output, int NCAN[N], the number of candidates for each level. */ { int ican; int *ifree; int nfree; /* Consider all the integers from 1 through N that have not been used yet. */ nfree = n - k + 1; ifree = ( int * ) malloc ( n * sizeof ( int ) ); perm0_free ( k - 1, a, nfree, ifree ); /* Everything but K is a legitimate candidate for the K-th entry. */ ncan[k-1] = 0; for ( ican = 0; ican < nfree; ican++ ) { if ( ifree[ican] != k - 1 ) { ncan[k-1] = ncan[k-1] + 1; stack[*nstack] = ifree[ican]; *nstack = *nstack + 1; } } free ( ifree ); return; } /******************************************************************************/ void derange0_back_next ( int n, int a[], int *more ) /******************************************************************************/ /* Purpose: derange0_back_next() returns the next derangement of N items. Discussion: A derangement of N objects is a permutation of (0,...,N-1) which leaves no object unchanged. A derangement of N objects is a permutation with no fixed points. If we symbolize the permutation operation by "P", then for a derangment, P(I) is never equal to I. The number of derangements of N objects is sometimes called the subfactorial function, or the derangement number D(N). This routine uses backtracking. Licensing: This code is distributed under the MIT license. Modified: 25 March 2009 Author: John Burkardt Parameters: Input, int N, the number of items to be deranged. N should be 2 or more. Input/output, int A[N]. On the first call, the input value of A is not important. On return with MORE = TRUE, A contains the next derangement. On subsequent input, A should not be changed. Input/output, int *MORE. On first call, set MORE to FALSE and do not alter it after. On return, MORE is TRUE if another derangement is being returned in A, and FALSE if no more derangements could be found. */ { int i; static int indx = -1; static int k = -1; static int *ncan = NULL; static int *stack = NULL; static int stack_max = -1; static int stack_num = -1; if ( !( *more ) ) { if ( n < 2 ) { *more = 0; return; } indx = 0; k = 0; stack_max = ( n * ( n + 1 ) ) / 2; stack_num = 0; if ( stack ) { free ( stack ); } stack = ( int * ) malloc ( stack_max * sizeof ( int ) ); for ( i = 0; i < stack_max; i++ ) { stack[i] = 0; } if ( ncan ) { free ( ncan ); } ncan = ( int * ) malloc ( n * sizeof ( int ) ); for ( i = 0; i < n; i++ ) { ncan[i] = 0; } *more = 1; } for ( ; ; ) { i4vec_backtrack ( n, stack_max, a, &indx, &k, &stack_num, stack, ncan ); if ( indx == 1 ) { break; } else if ( indx == 2 ) { derange0_back_candidate ( n, a, k, &stack_num, stack, ncan ); } else { *more = 0; free ( ncan ); ncan = NULL; free ( stack ); stack = NULL; break; } } return; } /******************************************************************************/ int derange0_check ( int n, int a[] ) /******************************************************************************/ /* Purpose: derange0_check() is TRUE if a permutation is a derangement of (0,...,N-1). Discussion: A derangement of N objects is a permutation which leaves no object unchanged. A derangement of N objects is a permutation with no fixed points. If we symbolize the permutation operation by "P", then for a derangment, P(I) is never equal to I. The number of derangements of N objects is sometimes called the subfactorial function, or the derangement number D(N). Licensing: This code is distributed under the MIT license. Modified: 02 June 2015 Author: John Burkardt Parameters: Input, int N, the number of objects permuted. Input, int A[N], a permutation of (0,...,N-1). Output, int DERANGE0_CHECK is TRUE if there was an error. */ { int check; int i; int j; /* Values must be between 0 and N-1. */ for ( i = 0; i < n; i++ ) { if ( a[i] < 0 || n - 1 < a[i] ) { check = 0; return check; } } /* Every value must be represented. */ for ( j = 0; j < n; j++ ) { check = 0; for ( i = 0; i < n; i++ ) { if ( a[i] == j ) { check = 1; break; } } if ( ! check ) { return check; } } /* Values must be deranged. */ for ( i = 0; i < n; i++ ) { if ( a[i] == i ) { check = 0; return check; } } check = 1; return check; } /******************************************************************************/ void derange0_weed_next ( int n, int a[], int *more, int *maxder, int *numder ) /******************************************************************************/ /* Purpose: derange0_weed_next() computes derangements of (0,...,N-1). Discussion: A derangement of N objects is a permutation which leaves no object unchanged. A derangement of N objects is a permutation with no fixed points. If we symbolize the permutation operation by "P", then for a derangment, P(I) is never equal to I. The number of derangements of N objects is sometimes called the subfactorial function, or the derangement number D(N). This routine simply generates all permutations, one at a time, and weeds out those that are not derangements. Example: Here are the derangements when N = 4: 1032 1230 1302 2031 2301 2310 3012 3201 3210 Licensing: This code is distributed under the MIT license. Modified: 08 June 2015 Author: John Burkardt Parameters: Input, int N, the number of objects being permuted. Input/output, int A[N]. On first call, the input contents of A are unimportant. But on the second and later calls, the input value of A should be the output value returned on the previous call. On output, A contains the next derangement. Input/output, int *MORE. Set MORE = FALSE before the first call. MORE will be reset to TRUE and a derangement will be returned. Each new call produces a new derangement until MORE is returned FALSE. Input/output, int *MAXDER, *NUMDER, two parameters used by the program for bookkeeping. The user should declare these variables, and pass the output values from one call to the next, but should not alter them. */ { int check; /* Initialization on call with MORE = FALSE. */ if ( !( *more ) ) { *maxder = derange_enum ( n ); *numder = 0; } /* Watch out for cases where there are no derangements. */ if ( *maxder == 0 ) { *more = 0; return; } /* Get the next permutation. */ for ( ; ; ) { perm0_lex_next ( n, a, more ); /* See if it is a derangment. */ check = derange0_check ( n, a ); if ( check ) { break; } } *numder = *numder + 1; if ( *maxder <= *numder ) { *more = 0; } return; } /******************************************************************************/ char digit_to_ch ( int digit ) /******************************************************************************/ /* Purpose: digit_to_ch() returns the character representation of a decimal digit. Example: DIGIT C ----- --- 0 '0' 1 '1' ... ... 9 '9' 17 '*' Licensing: This code is distributed under the MIT license. Modified: 28 May 2003 Author: John Burkardt Parameters: Input, int DIGIT, the digit value between 0 and 9. Output, char DIGIT_TO_CH, the corresponding character, or '*' if DIGIT was illegal. */ { if ( 0 <= digit && digit <= 9 ) { return ( digit + 48 ); } else { return '*'; } } /******************************************************************************/ void digraph_arc_euler ( int nnode, int nedge, int inode[], int jnode[], int *success, int trail[] ) /******************************************************************************/ /* Purpose: digraph_arc_euler() returns an Euler circuit in a digraph. Discussion: An Euler circuit of a digraph is a path which starts and ends at the same node and uses each directed edge exactly once. A digraph is eulerian if it has an Euler circuit. The problem is to decide whether a given digraph is eulerian and to find an Euler circuit if the answer is affirmative. Method: A digraph has an Euler circuit if and only if the number of incoming edges is equal to the number of outgoing edges at each node. This characterization gives a straightforward procedure to decide whether a digraph is eulerian. Furthermore, an Euler circuit in an eulerian digraph G of NEDGE edges can be determined by the following method: STEP 1: Choose any node U as the starting node, and traverse any edge ( U, V ) incident to node U, and than traverse any unused edge incident to node U. Repeat this process of traversing unused edges until the starting node U is reached. Let P be the resulting walk consisting of all used edges. If all edges of G are in P, than stop. STEP 2: Choose any unused edge ( X, Y) in G such that X is in P and Y is not in P. Use node X as the starting node and find another walk Q using all unused edges as in step 1. STEP 3: Walk P and walk Q share a common node X, they can be merged to form a walk R by starting at any node S of P and to traverse P until node X is reached; than, detour and traverse all edges of Q until node X is reached and continue to traverse the edges of P until the starting node S is reached. Set P = R. STEP 4: Repeat steps 2 and 3 until all edges are used. The running time of the algorithm is O ( NEDGE ). The digraph is assumed to be connected. Licensing: This code is distributed under the MIT license. Modified: 01 April 2009 Author: Original FORTRAN77 version by Hang Tong Lau. This version by John Burkardt. Reference: Hang Tong Lau, Algorithms on Graphs, Tab Books, 1989. Parameters: Input, int NNODE, the number of nodes. Input, int NEDGE, the number of edges. Input, int INODE[NEDGE], JNODE(NEDGE); the I-th edge starts at node INODE(I) and ends at node JNODE(I). Output, int *SUCCESS, is TRUE if an Euler circuit was found. Output, int TRAIL[NEDGE]. TRAIL[I] is the edge number of the I-th edge in the Euler circuit. */ { int *candid; int *endnod; int i; int istak; int j; int k; int l; int len; int lensol; int lenstk; int *stack; /* Check if the digraph is eulerian. */ for ( i = 0; i < nedge; i++ ) { trail[i] = 0; } endnod = ( int * ) malloc ( nedge * sizeof ( int ) ); for ( i = 0; i < nedge; i++ ) { endnod[i] = 0; } for ( i = 1; i <= nedge; i++ ) { j = inode[i-1]; trail[j-1] = trail[j-1] + 1; j = jnode[i-1]; endnod[j-1] = endnod[j-1] + 1; } for ( i = 1; i <= nnode; i++ ) { if ( trail[i-1] != endnod[i-1] ) { *success = 0; free ( endnod ); return; } } /* The digraph is eulerian; find an Euler circuit. */ *success = 1; lensol = 1; lenstk = 0; candid = ( int * ) malloc ( nedge * sizeof ( int ) ); stack = ( int * ) malloc ( 2 * nedge * sizeof ( int ) ); /* Find the next edge. */ for ( ; ; ) { if ( lensol == 1 ) { endnod[0] = inode[0]; stack[0] = 1; stack[1] = 1; lenstk = 2; } else { l = lensol - 1; if ( lensol != 2 ) { endnod[l-1] = inode[trail[l-1]-1] + jnode[trail[l-1]-1] - endnod[l-2]; } k = endnod[l-1]; for ( i = 1; i <= nedge; i++ ) { candid[i-1] = ( k == jnode[i-1] ); } for ( i = 1; i <= l; i++ ) { candid[trail[i-1]-1] = 0; } len = lenstk; for ( i = 1; i <= nedge; i++ ) { if ( candid[i-1] ) { len = len + 1; stack[len-1] = i; } } stack[len] = len - lenstk; lenstk = len + 1; } for ( ; ; ) { istak = stack[lenstk-1]; lenstk = lenstk - 1; if ( istak != 0 ) { break; } lensol = lensol - 1; if ( lensol == 0 ) { i4vec_reverse ( nedge, trail ); free ( candid ); free ( endnod ); free ( stack ); return; } } trail[lensol-1] = stack[lenstk-1]; stack[lenstk-1] = istak - 1; if ( lensol == nedge ) { break; } lensol = lensol + 1; } i4vec_reverse ( nedge, trail ); free ( candid ); free ( endnod ); free ( stack ); return; } /******************************************************************************/ void digraph_arc_print ( int nedge, int inode[], int jnode[], char *title ) /******************************************************************************/ /* Purpose: digraph_arc_print() prints out a digraph from an edge list. Licensing: This code is distributed under the MIT license. Modified: 01 April 2009 Author: John Burkardt Parameters: Input, int NEDGE, the number of edges. Input, int INODE[NEDGE], JNODE[NEDGE], the beginning and end nodes of the edges. Input, char *TITLE, a title. */ { int i; if ( s_len_trim ( title ) != 0 ) { printf ( "\n" ); printf ( "%s\n", title ); } printf ( "\n" ); for ( i = 0; i < nedge; i++ ) { printf ( "%6d %6d %6d\n", i+1, inode[i], jnode[i] ); } return; } /******************************************************************************/ void diophantine ( int a, int b, int c, int *error, int *x, int *y ) /******************************************************************************/ /* Purpose: diophantine() solves a Diophantine equation A * X + B * Y = C. Discussion: Given integers A, B and C, produce X and Y so that A * X + B * Y = C. In general, the equation is solvable if and only if the greatest common divisor of A and B also divides C. A solution (X,Y) of the Diophantine equation also gives the solution X to the congruence equation: A * X = C mod ( B ). Generally, if there is one nontrivial solution, there are an infinite number of solutions to a Diophantine problem. If (X0,Y0) is a solution, then so is ( X0+T*B/D, Y0-T*A/D ) where T is any integer, and D is the greatest common divisor of A and B. Licensing: This code is distributed under the MIT license. Modified: 01 April 2009 Author: John Burkardt Reference: Eric Weisstein, editor, CRC Concise Encylopedia of Mathematics, CRC Press, 1998, page 446. Parameters: Input, int A, B, C, the coefficients of the Diophantine equation. Output, int *ERROR, is TRUE if an error occurred. Output, int *X, *Y, the solution of the Diophantine equation. Note that the algorithm will attempt to return a solution with smallest Euclidean norm. */ { # define N_MAX 100 int a_copy; int a_mag; int a_sign; int b_copy; int b_mag; int b_sign; int c_copy; int g; int k; int n; int q[N_MAX]; int swap; /* Defaults for output parameters. */ *error = 0; *x = 0; *y = 0; /* Special cases. */ if ( a == 0 && b == 0 && c == 0 ) { *x = 0; *y = 0; return; } else if ( a == 0 && b == 0 && c != 0 ) { *error = 1; *x = 0; *y = 0; return; } else if ( a == 0 && b != 0 && c == 0 ) { *x = 0; *y = 0; return; } else if ( a == 0 && b != 0 && c != 0 ) { *x = 0; *y = c / b; if ( ( c % b ) != 0 ) { *error = 1; } return; } else if ( a != 0 && b == 0 && c == 0 ) { *x = 0; *y = 0; return; } else if ( a != 0 && b == 0 && c != 0 ) { *x = c / a; *y = 0; if ( ( c % a ) != 0 ) { *error = 1; } return; } else if ( a != 0 && b != 0 && c == 0 ) { g = i4_gcd ( a, b ); *x = b / g; *y = - a / g; return; } /* Now handle the "general" case: A, B and C are nonzero. Step 1: Compute the GCD of A and B, which must also divide C. */ g = i4_gcd ( a, b ); if ( ( c % g ) != 0 ) { *error = 1; return; } a_copy = a / g; b_copy = b / g; c_copy = c / g; /* Step 2: Split A and B into sign and magnitude. */ a_mag = abs ( a_copy ); a_sign = i4_sign ( a_copy ); b_mag = abs ( b_copy ); b_sign = i4_sign ( b_copy ); /* Another special case, A_MAG = 1 or B_MAG = 1. */ if ( a_mag == 1 ) { *x = a_sign * c_copy; *y = 0; return; } else if ( b_mag == 1 ) { *x = 0; *y = b_sign * c_copy; return; } /* Step 3: Produce the Euclidean remainder sequence. */ if ( b_mag <= a_mag ) { swap = 0; q[0] = a_mag; q[1] = b_mag; } else { swap = 1; q[0] = b_mag; q[1] = a_mag; } n = 3; for ( ; ; ) { q[n-1] = q[n-3] % q[n-2]; if ( q[n-1] == 1 ) { break; } n = n + 1; if ( N_MAX < n ) { *error = 1; fprintf ( stderr, "\n" ); fprintf ( stderr, "diophantine(): Fatal error!\n" ); fprintf ( stderr, " Exceeded number of iterations.\n" ); exit ( 1 ); } } /* Step 4: Now go backwards to solve X * A_MAG + Y * B_MAG = 1. */ *y = 0; for ( k = n; 2 <= k; k-- ) { *x = *y; *y = ( 1 - *x * q[k-2] ) / q[k-1]; } /* Step 5: Undo the swapping. */ if ( swap ) { i4_swap ( x, y ); } /* Step 6: Now apply signs to X and Y so that X * A + Y * B = 1. */ *x = *x * a_sign; *y = *y * b_sign; /* Step 7: Multiply by C, so that X * A + Y * B = C. */ *x = *x * c_copy; *y = *y * c_copy; /* Step 8: Given a solution (X,Y), try to find the solution of minimal magnitude. */ diophantine_solution_minimize ( a_copy, b_copy, x, y ); return; # undef N_MAX } /******************************************************************************/ void diophantine_solution_minimize ( int a, int b, int *x, int *y ) /******************************************************************************/ /* Purpose: diophantine_solution_minimize() seeks a minimal solution of a Diophantine equation. Discussion: Given a solution (X,Y) of a Diophantine equation: A * X + B * Y = C. then there are an infinite family of solutions of the form ( X(i), Y(i) ) = ( X + i * B, Y - i * A ) An integral solution of minimal Euclidean norm can be found by tentatively moving along the vectors (B,-A) and (-B,A) one step at a time. When large integer values are input, the real arithmetic used is essential. Licensing: This code is distributed under the MIT license. Modified: 01 April 2009 Author: John Burkardt Reference: Eric Weisstein, editor, CRC Concise Encylopedia of Mathematics, CRC Press, 1998, page 446. Parameters: Input, int A, B, the coefficients of the Diophantine equation. A and B are assumed to be relatively prime. Input/output, int *X, *Y, on input, a solution of the Diophantine equation. On output, a solution of minimal Euclidean norm. */ { double fa; double fb; double fx; double fy; double norm; double norm_new; double t; int xnew; int ynew; /* Compute the minimum for T real, and then look nearby. */ fa = ( double ) a; fb = ( double ) b; fx = ( double ) ( *x ); fy = ( double ) ( *y ); t = ( - fb * fx + fa * fy ) / ( fa * fa + fb * fb ); *x = *x + r8_nint ( t ) * b; *y = *y - r8_nint ( t ) * a; /* Now look nearby. */ norm = ( fx * fx + fy * fy ); for ( ; ; ) { xnew = *x + b; ynew = *y - a; fx = ( double ) xnew; fy = ( double ) ynew; norm_new = ( fx * fx + fy * fy ); if ( norm <= norm_new ) { break; } *x = xnew; *y = ynew; norm = norm_new; } for ( ; ; ) { xnew = *x - b; ynew = *y + a; fx = ( double ) xnew; fy = ( double ) ynew; norm_new = ( fx * fx + fy * fy ); if ( norm <= norm_new ) { break; } *x = xnew; *y = ynew; norm = norm_new; } return; } /******************************************************************************/ void dvec_add ( int n, int dvec1[], int dvec2[], int dvec3[] ) /******************************************************************************/ /* Purpose: dvec_add() adds two (signed) decimal vectors. Discussion: A DVEC is an integer vector of decimal digits, intended to represent an integer. DVEC(1) is the units digit, DVEC(N-1) is the coefficient of 10^(N-2), and DVEC(N) contains sign information. It is 0 if the number is positive, and 9 if the number is negative. Example: N = 4 DVEC1 + DVEC2 = DVEC3 ( 0 0 1 7 ) + ( 0 1 0 4 ) = ( 0 0 1 2 1 ) 17 + 104 = 121 Licensing: This code is distributed under the MIT license. Modified: 25 March 2009 Author: John Burkardt Parameters: Input, int N, the length of the vectors. Input, int DVEC1[N], DVEC2[N], the vectors to be added. Output, int DVEC3[N], the sum of the two input vectors. */ { int base = 10; int i; for ( i = 0; i < n; i++ ) { dvec3[i] = dvec1[i] + dvec2[i]; } for ( i = 0; i < n; i++ ) { while ( base <= dvec3[i] ) { dvec3[i] = dvec3[i] - base; if ( i < n - 1 ) { dvec3[i+1] = dvec3[i+1] + 1; } else { printf ( "dvec_add - Overflow!\n" ); return; } } } return; } /******************************************************************************/ void dvec_complementx ( int n, int dvec1[], int dvec2[] ) /******************************************************************************/ /* Purpose: dvec_complementx() computes the ten's complement of a decimal vector. Discussion: A DVEC is an integer vector of decimal digits, intended to represent an integer. DVEC(1) is the units digit, DVEC(N-1) is the coefficient of 10^(N-2), and DVEC(N) contains sign information. It is 0 if the number is positive, and 9 if the number is negative. Licensing: This code is distributed under the MIT license. Modified: 25 March 2009 Author: John Burkardt Parameters: Input, int N, the length of the vectors. Input, int DVEC1[N], the vector to be complemented. Output, int DVEC2[N], the complemented vector. */ { int base = 10; int *dvec3; int *dvec4; int i; dvec3 = ( int * ) malloc ( n * sizeof ( int ) ); dvec4 = ( int * ) malloc ( n * sizeof ( int ) ); for ( i = 0; i < n; i++ ) { dvec3[i] = ( base - 1 ) - dvec1[i]; } dvec4[0] = 1; for ( i = 1; i < n; i++ ) { dvec4[i] = 0; } dvec_add ( n, dvec3, dvec4, dvec2 ); free ( dvec3 ); free ( dvec4 ); return; } /******************************************************************************/ void dvec_mul ( int n, int dvec1[], int dvec2[], int dvec3[] ) /******************************************************************************/ /* Purpose: dvec_mul() computes the product of two decimal vectors. Discussion: A DVEC is an integer vector of decimal digits, intended to represent an integer. DVEC(1) is the units digit, DVEC(N-1) is the coefficient of 10^(N-2), and DVEC(N) contains sign information. It is 0 if the number is positive, and 9 if the number is negative. Since the user may want to make calls like dvec_mul ( n, dvec1, dvec1, dvec3 ) or even dvec_mul ( n, dvec1, dvec1, dvec1 ) we need to copy the arguments, work on them, and then copy out the result. Licensing: This code is distributed under the MIT license. Modified: 25 March 2009 Author: John Burkardt Parameters: Input, int N, the length of the vectors. Input, int DVEC1[N], DVEC2[N], the vectors to be multiplied. Output, int DVEC3[N], the product of the two input vectors. */ { int base = 10; int carry; int *dveca; int *dvecb; int *dvecc; int i; int j; int product_sign; dveca = ( int * ) malloc ( n * sizeof ( int ) ); dvecb = ( int * ) malloc ( n * sizeof ( int ) ); dvecc = ( int * ) malloc ( n * sizeof ( int ) ); /* Copy the input. */ for ( i = 0; i < n; i++ ) { dveca[i] = dvec1[i]; } for ( i = 0; i < n; i++ ) { dvecb[i] = dvec2[i]; } /* Record the sign of the product. Make the factors positive. */ product_sign = 1; if ( dveca[n-1] != 0 ) { product_sign = - product_sign; dvec_complementx ( n, dveca, dveca ); } if ( dvecb[n-1] != 0 ) { product_sign = - product_sign; dvec_complementx ( n, dvecb, dvecb ); } for ( i = 0; i < n; i++ ) { dvecc[i] = 0; } /* Multiply. */ for ( i = 1; i <= n-1; i++ ) { for ( j = i; j <= n-1; j++ ) { dvecc[j-1] = dvecc[j-1] + dveca[i-1] * dvecb[j-i]; } } /* Take care of carries. Unlike the DVEC_ADD routine, we do NOT allow carries into the N-th position. */ for ( i = 0; i < n-1; i++ ) { carry = dvecc[i] / base; dvecc[i] = dvecc[i] - carry * base; if ( i < n - 2 ) { dvecc[i+1] = dvecc[i+1] + carry; } } /* Take care of the sign of the product. */ if ( product_sign < 0 ) { dvec_complementx ( n, dvecc, dvecc ); } /* Copy the output. */ for ( i = 0; i < n; i++ ) { dvec3[i] = dvecc[i]; } free ( dveca ); free ( dvecb ); free ( dvecc ); return; } /******************************************************************************/ void dvec_print ( int n, int dvec[], char *title ) /******************************************************************************/ /* Purpose: dvec_print() prints a decimal integer vector, with an optional title. Discussion: A DVEC is an integer vector of decimal digits, intended to represent an integer. DVEC(1) is the units digit, DVEC(N-1) is the coefficient of 10^(N-2), and DVEC(N) contains sign information. It is 0 if the number is positive, and 9 if the number is negative. The vector is printed "backwards", that is, the first entry printed is DVEC(N). Licensing: This code is distributed under the MIT license. Modified: 27 May 2015 Author: John Burkardt Parameters: Input, int N, the number of components of the vector. Input, int DVEC[N], the vector to be printed. Input, char *TITLE, a title to be printed first. TITLE may be blank. */ { int i; if ( 0 < s_len_trim ( title ) ) { printf ( "\n" ); printf ( "%s\n", title ); printf ( "\n" ); } if ( dvec[n-1] == 9 ) { printf ( "-" ); } else { printf ( "+" ); } for ( i = n - 2; 0 <= i; i-- ) { printf ( "%d", dvec[i] ); } printf ( "\n" ); return; } /******************************************************************************/ void dvec_sub ( int n, int dvec1[], int dvec2[], int dvec3[] ) /******************************************************************************/ /* Purpose: dvec_sub() subtracts two decimal vectors. Discussion: A DVEC is an integer vector of decimal digits, intended to represent an integer. DVEC(1) is the units digit, DVEC(N-1) is the coefficient of 10^(N-2), and DVEC(N) contains sign information. It is 0 if the number is positive, and 9 if the number is negative. Licensing: This code is distributed under the MIT license. Modified: 25 March 2009 Author: John Burkardt Parameters: Input, int N, the length of the vectors. Input, int DVEC1[N], DVEC2[N]), the vectors to be subtracted. Output, int DVEC3[N], the value of DVEC1 - DVEC2. */ { int i; for ( i = 0; i < n; i++ ) { dvec3[i] = dvec2[i]; } dvec_complementx ( n, dvec3, dvec3 ); dvec_add ( n, dvec1, dvec3, dvec3 ); return; } /******************************************************************************/ int dvec_to_i4 ( int n, int dvec[] ) /******************************************************************************/ /* Purpose: dvec_to_i4() makes an integer from a (signed) decimal vector. Discussion: A DVEC is an integer vector of decimal digits, intended to represent an integer. DVEC(1) is the units digit, DVEC(N-1) is the coefficient of 10^(N-2), and DVEC(N) contains sign information. It is 0 if the number is positive, and 9 if the number is negative. Licensing: This code is distributed under the MIT license. Modified: 27 May 2015 Author: John Burkardt Parameters: Input, int N, the dimension of the vector. Input, int DVEC[N], the decimal vector. Output, int DVEC_TO_I4, the integer. */ { int base = 10; int *dvec2; int i; int i_sign; int i4; dvec2 = ( int * ) malloc ( n * sizeof ( int ) ); for ( i = 0; i < n; i++ ) { dvec2[i] = dvec[i]; } i_sign = 1; if ( dvec2[n-1] == base - 1 ) { i_sign = -1; dvec_complementx ( n-1, dvec2, dvec2 ); } i4 = 0; for ( i = n - 2; 0 <= i; i-- ) { i4 = base * i4 + dvec2[i]; } i4 = i_sign * i4; free ( dvec2 ); return i4; } /******************************************************************************/ void equiv_next ( int n, int *npart, int jarray[], int iarray[], int *more ) /******************************************************************************/ /* Purpose: equiv_next() computes the partitions of a set one at a time. Discussion: A partition of a set assigns each element to exactly one subset. The number of partitions of a set of size N is the Bell number B(N). Licensing: This code is distributed under the MIT license. Modified: 23 March 2009 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, number of elements in the set to be partitioned. Output, int *NPART, number of subsets in the partition. Output, int JARRAY[N]. JARRAY[I] is the number of elements in the I-th subset of the partition. Output, int IARRAY[N]. IARRAY(I) is the class to which element I belongs. Input/output, int *MORE. Set MORE = FALSE before first call. It is reset and held at TRUE as long as the partition returned is not the last one. When MORE is returned FALSE, all the partitions have been computed and returned. */ { int i; int l; int m; if ( !( *more ) ) { *npart = 1; for ( i = 0; i < n; i++ ) { iarray[i] = 1; } jarray[0] = n; } else { m = n; while ( jarray[iarray[m-1]-1] == 1 ) { iarray[m-1] = 1; m = m - 1; } l = iarray[m-1]; *npart = *npart + m - n; jarray[0] = jarray[0] + n - m; if ( l == *npart ) { *npart = *npart + 1; jarray[*npart-1] = 0; } iarray[m-1] = l + 1; jarray[l-1] = jarray[l-1] - 1; jarray[l] = jarray[l] + 1; } *more = ( *npart != n ); return; } /******************************************************************************/ void equiv_next2 ( int *done, int iarray[], int n ) /******************************************************************************/ /* Purpose: equiv_next2() computes, one at a time, the partitions of a set. Discussion: A partition of a set assigns each element to exactly one subset. The number of partitions of a set of size N is the Bell number B(N). Licensing: This code is distributed under the MIT license. Modified: 23 March 2009 Author: John Burkardt. Parameters: Input/output, int *DONE. Before the very first call, the user should set DONE to TRUE, which prompts the program to initialize its data, and return the first partition. Thereafter, the user should call again, for the next partition, and so on, until the routine returns with DONE equal to TRUE, at which point there are no more partitions to compute. Input/output, int IARRAY[N], contains the information defining the current partition. The user should not alter IARRAY between calls. Except for the very first call, the routine uses the previous output value of IARRAY to compute the next value. The entries of IARRAY are the partition subset to which each element of the original set belongs. If there are NPART distinct parts of the partition, then each entry of IARRAY will be a number between 1 and NPART. Every number from 1 to NPART will occur somewhere in the list. If the entries of IARRAY are examined in order, then each time a new partition subset occurs, it will be the next unused integer. For instance, for N = 4, the program will describe the set where each element is in a separate subset as 1, 2, 3, 4, even though such a partition might also be described as 4, 3, 2, 1 or even 1, 5, 8, 19. Input, int N, the number of elements in the set. */ { int i; int imax; int j; int jmax; if ( *done ) { *done = 0; for ( i = 0; i < n; i++ ) { iarray[i] = 1; } } else { /* Find the last element J that can be increased by 1. This is the element that is not equal to its maximum possible value, which is the maximum value of all preceding elements +1. */ jmax = iarray[0]; imax = 1; for ( j = 2; j <= n; j++ ) { if ( jmax < iarray[j-1] ) { jmax = iarray[j-1]; } else { imax = j; } } /* If no element can be increased by 1, we are done. */ if ( imax == 1 ) { *done = 1; return; } /* Increase the value of the IMAX-th element by 1, set its successors to 1. */ *done = 0; iarray[imax-1] = iarray[imax-1] + 1; for ( i = imax; i < n; i++ ) { iarray[i] = 1; } } return; } /******************************************************************************/ void equiv_print ( int n, int iarray[], char *title ) /******************************************************************************/ /* Purpose: equiv_print() prints a partition of a set. Licensing: This code is distributed under the MIT license. Modified: 23 March 2009 Author: John Burkardt Parameters: Input, int N, number of elements in set to be partitioned. Input, int IARRAY[N], defines the partition or set of equivalence classes. Element I belongs to subset IARRAY[I]. Input, char *TITLE, a title to be printed. */ { int *karray; int j; int k; int kk; int s; int s_max; int s_min; if ( s_len_trim ( title ) != 0 ) { printf ( "\n" ); printf ( "%s\n", title ); } printf ( "\n" ); printf ( " Set Size Elements\n" ); karray = ( int * ) malloc ( n * sizeof ( int ) ); s_min = i4vec_min ( n, iarray ); s_max = i4vec_max ( n, iarray ); for ( s = s_min; s <= s_max; s++ ) { k = 0; for ( j = 0; j < n; j++ ) { if ( iarray[j] == s ) { karray[k] = j+1; k = k + 1; } } if ( 0 < k ) { printf ( " %4d %4d :: ", s, k ); for ( kk = 0; kk < k; kk++ ) { printf ( "%4d ", karray[kk] ); } printf ( "\n" ); } } free ( karray ); return; } /******************************************************************************/ void equiv_print2 ( int n, int s[], char *title ) /******************************************************************************/ /* Purpose: equiv_print2() prints a partition of a set. Discussion: The partition is printed using the parenthesis format. For example, here are the partitions of a set of 4 elements: (1,2,3,4) (1,2,3)(4) (1,2,4)(3) (1,2)(3,4) (1,2)(3)(4) (1,3,4)(2) (1,3)(2,4) (1,3)(2)(4) (1,4)(2,3) (1)(2,3,4) (1)(2,3)(4) (1,4)(2)(3) (1)(2,4)(3) (1)(2)(3,4) (1)(2)(3)(4) Licensing: This code is distributed under the MIT license. Modified: 09 February 2014 Author: John Burkardt Parameters: Input, int N, number of elements in the set. Input, int S[N], defines the partition. Element I belongs to subset S[I]. Input, char *TITLE, a title. */ { int i; int j; int s_max; int s_min; int size; printf ( "\n" ); printf ( "%s\n", title ); printf ( "\n" ); s_min = i4vec_min ( n, s ); s_max = i4vec_max ( n, s ); for ( j = s_min; j <= s_max; j++ ) { printf ( "(" ); size = 0; for ( i = 0; i < n; i++ ) { if ( s[i] == j ) { if ( 0 < size ) { printf ( "," ); } printf ( "%d", i ); size = size + 1; } } printf ( ")" ); } printf ( "\n" ); return; } /******************************************************************************/ void equiv_random ( int n, int *seed, int *npart, int a[] ) /******************************************************************************/ /* Purpose: equiv_random() selects a random partition of a set. Discussion: The user does not control the number of parts in the partition. The equivalence classes are numbered in no particular order. Licensing: This code is distributed under the MIT license. Modified: 30 May 2015 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the number of elements in the set to be partitioned. Input/output, int *SEED, a seed for the random number generator. Output, int *NPART, the number of classes or parts in the partition. NPART will be between 1 and N. Output, int A[N], indicates the class to which each element is assigned. */ { double *b; int i; int j; int k; int l; int m; double sum1; int t; double z; double zhi = 1.0; double zlo = 0.0; b = ( double * ) malloc ( n * sizeof ( double ) ); b[0] = 1.0; for ( l = 1; l <= n-1; l++ ) { sum1 = 1.0 / ( double ) l; for ( k = 1; k <= l-1; k++ ) { sum1 = ( sum1 + b[k-1] ) / ( double ) ( l - k ); } b[l] = ( sum1 + b[l-1] ) / ( double ) ( l + 1 ); } m = n; *npart = 0; for ( ; ; ) { z = r8_uniform_ab ( zlo, zhi, seed ); z = ( double ) ( m ) * b[m-1] * z; k = 0; *npart = *npart + 1; while ( 0.0 <= z ) { a[m-1] = *npart; m = m - 1; if ( m == 0 ) { break; } z = z - b[m-1]; k = k + 1; z = z * k; } if ( m == 0 ) { break; } } /* Randomly permute the assignments. */ for ( i = 0; i < n - 1; i++ ) { j = i4_uniform_ab ( i, n - 1, seed ); t = a[i]; a[i] = a[j]; a[j] = t; } /* Free memory. */ free ( b ); return; } /******************************************************************************/ void euler_row ( int n, int ieuler[] ) /******************************************************************************/ /* Purpose: euler_row() returns the N-th row of Euler's triangle. Discussion: E(N,K) counts the number of permutations of the N digits that have exactly K "ascents", that is, K places where the Ith digit is less than the (I+1)th digit. Licensing: This code is distributed under the MIT license. Modified: 11 June 2015 Author: John Burkardt Parameters: Input, int N, the row of Euler's triangle desired. Output, int IEULER[N+1], the N-th row of Euler's triangle, IEULER[K] contains the value of E(N,K). Note that IEULER[0] should be 1 and IEULER[N] should be 0. */ { int irow; int k; ieuler[0] = 1; if ( 0 < n ) { ieuler[1] = 0; for ( irow = 2; irow <= n; irow++ ) { ieuler[irow] = 0; for ( k = irow-1; 1 <= k; k-- ) { ieuler[k] = ( k + 1 ) * ieuler[k] + ( irow - k ) * ieuler[k-1]; } ieuler[0] = 1; } } return; } /******************************************************************************/ int frobenius_number_order2 ( int c1, int c2 ) /******************************************************************************/ /* Purpose: frobenius_number_order2() returns the Frobenius number for order 2. Discussion: The Frobenius number of order N is the solution of the Frobenius coin sum problem for N coin denominations. The Frobenius coin sum problem assumes the existence of N coin denominations, and asks for the largest value that cannot be formed by any combination of coins of these denominations. The coin denominations are assumed to be distinct positive integers. For general N, this problem is fairly difficult to handle. For N = 2, it is known that: * if C1 and C2 are not relatively prime, then there are infinitely large values that cannot be formed. * otherwise, the largest value that cannot be formed is C1 * C2 - C1 - C2, and that exactly half the values between 1 and C1 * C2 - C1 - C2 + 1 cannot be represented. As a simple example, if C1 = 2 and C2 = 7, then the largest unrepresentable value is 5, and there are (5+1)/2 = 3 unrepresentable values, namely 1, 3, and 5. For a general N, and a set of coin denominations C1, C2, ..., CN, the Frobenius number F(N, C(1:N) ) is defined as the largest value B for which the equation C1*X1 + C2*X2 + ... + CN*XN = B has no nonnegative integer solution X(1:N). In the Mathematica Package "NumberTheory", the Frobenius number can be determined by < .0 = 0.0 1 = 1 => .1 = 0.5 2 = 10 => .01 = 0.25 3 = 11 => .11 = 0.75 4 = 100 => .001 = 0.125 5 = 101 => .101 = 0.625 6 = 110 => .011 = 0.375 7 = 111 => .111 = 0.875 8 = 1000 => .0001 = 0.0625 Licensing: This code is distributed under the MIT license. Modified: 25 February 2003 Author: John Burkardt Reference: John Halton, On the efficiency of certain quasi-random sequences of points in evaluating multi-dimensional integrals, Numerische Mathematik, Volume 2, 1960, pages 84-90. John Hammersley, Monte Carlo methods for solving multivariable problems, Proceedings of the New York Academy of Science, Volume 86, 1960, pages 844-874. Johannes van der Corput, Verteilungsfunktionen I & II, Nederl. Akad. Wetensch. Proc., Volume 38, 1935, pages 813-820, pages 1058-1066. Parameters: Input, int SEED, the index of the desired element. SEED should be nonnegative. SEED = 0 is allowed, and returns R = 0. Input, int BASE, the van der Corput base, which is usually a prime number. BASE must be greater than 1. Output, double VAN_DER_CORPUT, the SEED-th element of the van der Corput sequence for base BASE. */ { double base_inv; int digit; double r; if ( base <= 1 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "I4_TO_VAN_DER_CORPUT(): Fatal error!\n" ); fprintf ( stderr, " The input base BASE is <= 1!\n" ); fprintf ( stderr, " BASE = %d\n", base ); exit ( 1 ); } if ( seed < 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "I4_TO_VAN_DER_CORPUT(): Fatal error!\n" ); fprintf ( stderr, " SEED < 0." ); fprintf ( stderr, " SEED = %d\n", seed ); exit ( 1 ); } r = 0.0; base_inv = 1.0 / ( ( double ) base ); while ( seed != 0 ) { digit = seed % base; r = r + ( ( double ) digit ) * base_inv; base_inv = base_inv / ( ( double ) base ); seed = seed / base; } return r; } /******************************************************************************/ int i4_uniform_ab ( int a, int b, int *seed ) /******************************************************************************/ /* Purpose: i4_uniform_ab() returns a scaled pseudorandom I4 between A and B. Discussion: The pseudorandom number should be uniformly distributed between A and B. Licensing: This code is distributed under the MIT license. Modified: 24 May 2012 Author: John Burkardt Reference: Paul Bratley, Bennett Fox, Linus Schrage, A Guide to Simulation, Second Edition, Springer, 1987, ISBN: 0387964673, LC: QA76.9.C65.B73. Bennett Fox, Algorithm 647: Implementation and Relative Efficiency of Quasirandom Sequence Generators, ACM Transactions on Mathematical Software, Volume 12, Number 4, December 1986, pages 362-376. Pierre L'Ecuyer, Random Number Generation, in Handbook of Simulation, edited by Jerry Banks, Wiley, 1998, ISBN: 0471134031, LC: T57.62.H37. Peter Lewis, Allen Goodman, James Miller, A Pseudo-Random Number Generator for the System/360, IBM Systems Journal, Volume 8, Number 2, 1969, pages 136-143. Parameters: Input, int A, B, the limits of the interval. Input/output, int *SEED, the "seed" value, which should NOT be 0. On output, SEED has been updated. Output, int I4_UNIFORM_AB, a number between A and B. */ { int c; const int i4_huge = 2147483647; int k; float r; int value; if ( *seed == 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "I4_UNIFORM_AB(): Fatal error!\n" ); fprintf ( stderr, " Input value of SEED = 0.\n" ); exit ( 1 ); } /* Guaranteee A <= B. */ if ( b < a ) { c = a; a = b; b = c; } k = *seed / 127773; *seed = 16807 * ( *seed - k * 127773 ) - k * 2836; if ( *seed < 0 ) { *seed = *seed + i4_huge; } r = ( float ) ( *seed ) * 4.656612875E-10; /* Scale R to lie between A-0.5 and B+0.5. */ r = ( 1.0 - r ) * ( ( float ) ( a ) - 0.5 ) + r * ( ( float ) ( b ) + 0.5 ); /* Round R to the nearest integer. */ value = round ( r ); /* Guarantee that A <= VALUE <= B. */ if ( value < a ) { value = a; } if ( b < value ) { value = b; } return value; } /******************************************************************************/ int i4_width ( int i ) /******************************************************************************/ /* Purpose: i4_width() returns the "width" of an I4. Example: I I4_WIDTH ----- ------- -1234 5 -123 4 -12 3 -1 2 0 1 1 1 12 2 123 3 1234 4 12345 5 Discussion: The width of an integer is the number of characters necessary to print it. The width of an integer can be useful when setting the appropriate output format for a vector or array of values. Licensing: This code is distributed under the MIT license. Modified: 26 August 2008 Author: John Burkardt Parameters: Input, int I, the number whose width is desired. Output, int I4_WIDTH, the number of characters necessary to represent the integer in base 10, including a negative sign if necessary. */ { int width; if ( 0 <= i ) { width = i4_log_10 ( i ) + 1; } else { width = i4_log_10 ( i ) + 2; } return width; } /******************************************************************************/ void i4mat_01_rowcolsum ( int m, int n, int r[], int c[], int a[], int *error ) /******************************************************************************/ /* Purpose: i4mat_01_rowcolsum() creates a 0/1 integer matrix with given row and column sums. Discussion: Given an M vector R and N vector C, there may exist one or more M by N matrices with entries that are 0 or 1, whose row sums are R and column sums are C. For convenience, this routine requires that the entries of R and C be given in nonincreasing order. There are several requirements on R and C. The simple requirements are that the entries of R and C must be nonnegative, that the entries of R must each be no greater than N, and those of C no greater than M, and that the sum of the entries of R must equal the sum of the entries of C. The final technical requirement is that if we form R*, the conjugate partition of R, then C is majorized by R*, that is, that every partial sum from 1 to K of the entries of C is no bigger than the sum of the same entries of R*, for every K from 1 to N. Given these conditions on R and C, there is at least one 0/1 matrix with the given row and column sums. The conjugate partition of R is constructed as follows: R*(1) is the number of entries of R that are 1 or greater. R*(2) is the number of entries of R that are 2 or greater. ... R*(N) is the number of entries of R that are N (can't be greater). Example: M = N = 5 R = ( 3, 2, 2, 1, 1 ) C = ( 2, 2, 2, 2, 1 ) A = 1 0 1 0 1 1 0 0 1 0 0 1 0 1 0 0 1 0 0 0 0 0 1 0 0 Licensing: This code is distributed under the MIT license. Modified: 25 March 2009 Author: John Burkardt Reference: Jack van Lint, Richard Wilson, A Course in Combinatorics, Oxford, 1992, pages 148-156. James Sandeson, Testing Ecoint Patterns, American Scientist, Volume 88, July-August 2000, pages 332-339. Ian Saunders, Algorithm AS 205, Enumeration of R x C Tables with Repeated Row Totals, Applied Statistics, Volume 33, Number 3, pages 340-352, 1984. Parameters: Input, int M, N, the number of rows and columns in the array. Input, int R[M], C[N], the row and column sums desired for the array. Both vectors must be arranged in descending order. The elements of R must be between 0 and N. The elements of C must be between 0 and M. Output, int A[M*N], the M by N matrix with the given row and column sums. Each entry of A is 0 or 1. Output, int *ERROR, is 1 if an error occurred. */ { int c_sum; int i; int j; int k; int *r_conj; int r_sum; int *r2; for ( i = 0; i < m; i++ ) { for ( j = 0; j < n; j++ ) { a[i+j*m] = 0; } } /* Check conditions. */ *error = 0; if ( i4vec_sum ( m, r ) != i4vec_sum ( n, c ) ) { printf ( "\n" ); printf ( "I4MAT_01_ROWCOLSUM - Warning!\n" ); printf ( " Row sums R and column sums C don't have the same sum!\n" ); *error = 1; return; } if ( !i4vec_descends ( m, r ) ) { printf ( "\n" ); printf ( "I4MAT_01_ROWCOLSUM - Warning!\n" ); printf ( " Row sum vector R is not descending!\n" ); *error = 1; return; } if ( n < r[0] || r[m-1] < 0 ) { *error = 1; return; } if ( !i4vec_descends ( n, c ) ) { printf ( "\n" ); printf ( "I4MAT_01_ROWCOLSUM - Warning!\n" ); printf ( " Column sum vector C is not descending!\n" ); *error = 1; return; } if ( m < c[0] || c[n-1] < 0 ) { *error = 1; return; } /* Compute the conjugate of R. */ r_conj = ( int * ) malloc ( n * sizeof ( int ) ); for ( i = 0; i < n; i++ ) { r_conj[i] = 0; } for ( i = 0; i < m; i++ ) { for ( j = 0; j < r[i]; j++ ) { r_conj[j] = r_conj[j] + 1; } } /* C must be majorized by R_CONJ. */ r_sum = 0; c_sum = 0; for ( i = 0; i < n; i++ ) { r_sum = r_sum + r_conj[i]; c_sum = c_sum + c[i]; if ( r_sum < c_sum ) { *error = 1; return; } } free ( r_conj ); if ( *error ) { return; } r2 = ( int * ) malloc ( m * sizeof ( int ) ); /* We need a temporary copy of R that we can decrement. */ for ( i = 0; i < m; i++ ) { r2[i] = r[i]; } for ( j = n-1; 0 <= j; j-- ) { i = i4vec_maxloc_last ( m, r2 ); for ( k = 1; k <= c[j]; k++ ) { /* By adding 1 rather than setting A(I,J) to 1, we were able to spot an error where the index was "sticking". */ a[i+j*m] = a[i+j*m] + 1; r2[i] = r2[i] - 1; if ( 0 < i ) { i = i - 1; } /* There's a special case you have to watch out for. If I was 1, and when you decrement R2(1), I is going to be 1 again, and you're staying in the same column, that's not good. The syntax "R2+1" means the vector starting with the second element of R2. */ else { i = i4vec_maxloc_last ( m, r2 ); if ( i == 0 && k < c[j] ) { i = 1 + i4vec_maxloc_last ( m-1, r2+1 ); } } } } free ( r2 ); return; } /******************************************************************************/ void i4mat_01_rowcolsum2 ( int m, int n, int r[], int c[], int a[], int *error ) /******************************************************************************/ /* Purpose: i4mat_01_rowcolsum2() creates a 0/1 I4MAT with given row and column sums. Discussion: This routine uses network flow optimization to compute the results. Given an M vector R and N vector C, there may exist one or more M by N matrices with entries that are 0 or 1, whose row sums are R and column sums are C. For convenience, this routine requires that the entries of R and C be given in nonincreasing order. There are several requirements on R and C. The simple requirements are that the entries of R and C must be nonnegative, that the entries of R must each no greater than N, and those of C no greater than M, and that the sum of the entries of R must equal the sum of the entries of C. The final technical requirement is that if we form R*, the conjugate partition of R, then C is majorized by R*, that is, that every partial sum from 1 to K of the entries of C is no bigger than the sum of the same entries of R*, for every K from 1 to N. Given these conditions on R and C, there is at least one 0/1 matrix with the given row and column sums. The conjugate partition of R is constructed as follows: R*(1) is the number of entries of R that are 1 or greater. R*(2) is the number of entries of R that are 2 or greater. ... R*(N) is the number of entries of R that are N (can't be greater). Example: M = N = 5 R = ( 3, 2, 2, 1, 1 ) C = ( 2, 2, 2, 2, 1 ) A = 1 0 1 0 1 1 0 0 1 0 0 1 0 1 0 0 1 0 0 0 0 0 1 0 0 Licensing: This code is distributed under the MIT license. Modified: 25 March 2009 Author: John Burkardt Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Jack van Lint, Richard Wilson, A Course in Combinatorics, Oxford, 1992, pages 148-156. James Sandeson, Testing Ecoint Patterns, American Scientist, Volume 88, July-August 2000, pages 332-339. Parameters: Input, int M, N, the number of rows and columns in the array. These values do not have to be equal. Input, int R[M], C[N], the row and column sums desired for the array. Both vectors must be arranged in descending order. The elements of R must be between 0 and N. The elements of C must be between 0 and M. One of the conditions for a solution to exist is that the sum of the elements in R equal the sum of the elements in C. Output, int A[M*N], the matrix with the given row and column sums. Each entry of A is 0 or 1. Output, int *ERROR, is 1 if an error occurred. */ { int *capflo; int i; int *icut; int *iendpt; int isink; int j; int k; int nedge; int nnode; int *node_flow; int source; *error = 0; capflo = ( int * ) malloc ( 2*2*(m+m*n+n) * sizeof ( int ) ); icut = ( int * ) malloc ( ( m+n+2 )* sizeof ( int ) ); iendpt = ( int * ) malloc ( 2*2*(m+m*n+n) * sizeof ( int ) ); node_flow = ( int * ) malloc ( (m+n+2) * sizeof ( int ) ); /* There are M + N + 2 nodes. The last two are the special source and sink. */ source = m + n + 1; isink = m + n + 2; nnode = m + n + 2; /* The source is connected to each of the R nodes. */ k = 0; for ( i = 0; i < m; i++ ) { iendpt[0+2*k] = source; iendpt[1+2*k] = i+1; capflo[0+2*k] = r[i]; capflo[1+2*k] = 0; k = k + 1; iendpt[0+2*k] = i+1; iendpt[1+2*k] = source; capflo[0+2*k] = r[i]; capflo[1+2*k] = 0; k = k + 1; } /* Every R node is connected to every C node, with capacity 1. */ for ( i = 0; i < m; i++ ) { for ( j = 0; j < n; j++ ) { iendpt[0+2*k] = i+1; iendpt[1+2*k] = j+1+m; capflo[0+2*k] = 1; capflo[1+2*k] = 0; k = k + 1; iendpt[0+2*k] = j+1+m; iendpt[1+2*k] = i+1; capflo[0+2*k] = 1; capflo[1+2*k] = 0; k = k + 1; } } /* Every C node is connected to the sink. */ for ( j = 0; j < n; j++ ) { iendpt[0+2*k] = j+1+m; iendpt[1+2*k] = isink; capflo[0+2*k] = c[j]; capflo[1+2*k] = 0; k = k + 1; iendpt[0+2*k] = isink; iendpt[1+2*k] = j+1+m; capflo[0+2*k] = c[j]; capflo[1+2*k] = 0; k = k + 1; } /* Determine the maximum flow on the network. */ nedge = k; network_flow_max ( nnode, nedge, iendpt, capflo, source, isink, icut, node_flow ); /* We have a perfect solution if, and only if, the edges leading from the source, and the edges leading to the sink, are all saturated. */ for ( k = 0; k < nedge; k++ ) { i = iendpt[0+2*k]; j = iendpt[1+2*k] - m; if ( i <= m && 1 <= j && j <= n ) { if ( capflo[1+2*k] != 0 && capflo[1+2*k] != 1 ) { *error = 1; } } if ( iendpt[0+2*k] == source ) { if ( capflo[0+2*k] != capflo[1+2*k] ) { *error = 1; } } if ( iendpt[1+2*k] == isink ) { if ( capflo[0+2*k] != capflo[1+2*k] ) { *error = 1; } } } /* If we have a solution, then A(I,J) = the flow on the edge from R node I to C node J. */ for ( i = 0; i < m; i++ ) { for ( j = 0; j < n; j++ ) { a[i+j*m] = 0; } } for ( k = 0; k < nedge; k++ ) { i = iendpt[0+2*k]; j = iendpt[1+2*k] - m; if ( i <= m && 1 <= j && j <= n ) { a[i+j*m] = capflo[1+2*k]; } } free ( icut ); free ( iendpt ); free ( node_flow ); return; } /******************************************************************************/ void i4mat_perm0 ( int n, int a[], int p[] ) /******************************************************************************/ /* Purpose: i4mat_perm0() permutes the rows and columns of a square I4MAT. Licensing: This code is distributed under the MIT license. Modified: 25 March 2009 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the order of the matrix. Input/output, int A[N*N]. On input, the matrix to be permuted. On output, the permuted matrix. Input, int P[N], the permutation. P(I) is the new number of row and column I. */ { int i; int i1; int is; int it; int j; int j1; int j2; int k; int lc; int nc; int temp; perm0_cycle ( n, p, &is, &nc, 1 ); /* Temporarily increment P by 1. */ for ( i = 0; i < n; i++ ) { p[i] = p[i] + 1; } for ( i = 1; i <= n; i++ ) { i1 = - p[i-1]; if ( 0 < i1 ) { lc = 0; for ( ; ; ) { i1 = p[i1-1]; lc = lc + 1; if ( i1 <= 0 ) { break; } } i1 = i; for ( j = 1; j <= n; j++ ) { if ( p[j-1] <= 0 ) { j2 = j; k = lc; for ( ; ; ) { j1 = j2; it = a[i1-1+(j1-1)*n]; for ( ; ; ) { i1 = abs ( p[i1-1] ); j1 = abs ( p[j1-1] ); temp = a[i1-1+(j1-1)*n]; a[i1-1+(j1-1)*n] = it; it = temp; if ( j1 != j2 ) { continue; } k = k - 1; if ( i1 == i ) { break; } } j2 = abs ( p[j2-1] ); if ( k == 0 ) { break; } } } } } } /* Restore the positive signs of the data. */ for ( i = 0; i < n; i++ ) { p[i] = abs ( p[i] ); } /* Decrement P by 1. */ for ( i = 0; i < n; i++ ) { p[i] = p[i] - 1; } return; } /******************************************************************************/ void i4mat_2perm0 ( int m, int n, int a[], int p[], int q[] ) /******************************************************************************/ /* Purpose: i4mat_2perm0() permutes the rows and columns of a rectangular I4MAT. Licensing: This code is distributed under the MIT license. Modified: 25 March 2009 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int M, number of rows in the matrix. Input, int N, number of columns in the matrix. Input/output, int A[M*N]. On input, the matrix to be permuted. On output, the permuted matrix. Input, int P[M], the row permutation. P(I) is the new number of row I. Input, int Q[N]. The column permutation. Q(I) is the new number of column I. */ { int i; int i1; int is; int it; int j; int j1; int j2; int k; int lc; int nc; int *p1; int *q1; int temp; /* Wretched maneuvers to deal with necessity of 1-based values, and to handle case where P and Q are same vector. */ p1 = i4vec_copy_new ( m, p ); perm0_cycle ( m, p1, &is, &nc, 1 ); for ( i = 0; i < m; i++ ) { p1[i] = p1[i] + 1; } q1 = i4vec_copy_new ( n, q ); perm0_cycle ( n, q1, &is, &nc, 1 ); for ( j = 0; j < n; j++ ) { q1[j] = q1[j] + 1; } for ( i = 1; i <= m; i++ ) { i1 = - p1[i-1]; if ( 0 < i1 ) { lc = 0; for ( ; ; ) { i1 = p1[i1-1]; lc = lc + 1; if ( i1 <= 0 ) { break; } } i1 = i; for ( j = 1; j <= n; j++ ) { if ( q1[j-1] <= 0 ) { j2 = j; k = lc; for ( ; ; ) { j1 = j2; it = a[i1-1+(j1-1)*m]; for ( ; ; ) { i1 = abs ( p1[i1-1] ); j1 = abs ( q1[j1-1] ); temp = it; it = a[i1-1+(j1-1)*m]; a[i1-1+(j1-1)*m] = temp; if ( j1 != j2 ) { continue; } k = k - 1; if ( i1 == i ) { break; } } j2 = abs ( q1[j2-1] ); if ( k == 0 ) { break; } } } } } } /* Discard the 1-based permutations. */ free ( p1 ); free ( q1 ); return; } /******************************************************************************/ void i4mat_print ( int m, int n, int a[], char *title ) /******************************************************************************/ /* Purpose: i4mat_print() prints an I4MAT, with an optional title. Discussion: An I4MAT is an MxN array of I4's, stored by (I,J) -> [I+J*M]. Licensing: This code is distributed under the MIT license. Modified: 28 May 2008 Author: John Burkardt Parameters: Input, int M, the number of rows in A. Input, int N, the number of columns in A. Input, int A[M*N], the M by N matrix. Input, char *TITLE, a title to be printed. */ { i4mat_print_some ( m, n, a, 1, 1, m, n, title ); return; } /******************************************************************************/ void i4mat_print_some ( int m, int n, int a[], int ilo, int jlo, int ihi, int jhi, char *title ) /******************************************************************************/ /* Purpose: i4mat_print_some() prints some of an I4MAT. Discussion: An I4MAT is an MxN array of I4's, stored by (I,J) -> [I+J*M]. Licensing: This code is distributed under the MIT license. Modified: 28 May 2008 Author: John Burkardt Parameters: Input, int M, the number of rows of the matrix. M must be positive. Input, int N, the number of columns of the matrix. N must be positive. Input, int A[M*N], the matrix. Input, int ILO, JLO, IHI, JHI, designate the first row and column, and the last row and column to be printed. Input, char *TITLE, a title for the matrix. */ { # define INCX 10 int i; int i2hi; int i2lo; int j; int j2hi; int j2lo; printf ( "\n" ); printf ( "%s\n", title ); /* Print the columns of the matrix, in strips of INCX. */ for ( j2lo = jlo; j2lo <= jhi; j2lo = j2lo + INCX ) { j2hi = j2lo + INCX - 1; j2hi = i4_min ( j2hi, n ); j2hi = i4_min ( j2hi, jhi ); printf ( "\n" ); /* For each column J in the current range... Write the header. */ printf ( " Col:" ); for ( j = j2lo; j <= j2hi; j++ ) { printf ( " %6d", j ); } printf ( "\n" ); printf ( " Row\n" ); printf ( "\n" ); /* Determine the range of the rows in this strip. */ i2lo = i4_max ( ilo, 1 ); i2hi = i4_min ( ihi, m ); for ( i = i2lo; i <= i2hi; i++ ) { /* Print out (up to INCX) entries in row I, that lie in the current strip. */ printf ( "%5d", i ); for ( j = j2lo; j <= j2hi; j++ ) { printf ( " %6d", a[i-1+(j-1)*m] ); } printf ( "\n" ); } } return; # undef INCX } /******************************************************************************/ void i4mat_u1_inverse ( int n, int a[], int b[] ) /******************************************************************************/ /* Purpose: i4mat_u1_inverse() inverts a unit upper triangular I4MAT. Discussion: A unit upper triangular matrix is a matrix with only 1's on the main diagonal, and only 0's below the main diagonal. Above the main diagonal, the entries may be assigned any value. It may be surprising to note that the inverse of an integer unit upper triangular matrix is also an integer unit upper triangular matrix. Note that this routine can invert a matrix in place, that is, with no extra storage. If the matrix is stored in A, then the call i4mat_u1_inverse ( n, a, a ) will result in A being overwritten by its inverse, which can save storage if the original value of A is not needed later. Licensing: This code is distributed under the MIT license. Modified: 25 March 2009 Author: John Burkardt Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the number of rows and columns in the matrix. Input, int A[N*N], the unit upper triangular matrix to be inverted. Output, int B[N*N], the inverse matrix. */ { int i; int isum; int j; int k; for ( j = n; 1 <= j; j-- ) { for ( i = n; 1 <= i; i-- ) { if ( i == j ) { isum = 1; } else { isum = 0; } for ( k = i+1; k <= j; k++ ) { isum = isum - a[i-1+(k-1)*n] * b[k-1+(j-1)*n]; } b[i-1+(j-1)*n] = isum; } } return; } /******************************************************************************/ void i4poly ( int n, int a[], int x0, int iopt, int *val ) /******************************************************************************/ /* Purpose: i4poly() performs operations on I4POLY's in power or factorial form. Discussion: The power sum form of a polynomial is P(X) = A1 + A2*X + A3*X^2 + ... + (AN+1)*X^N The Taylor expansion at C has the form P(X) = A1 + A2*(X-C) + A3*(X-C)^2 + ... + (AN+1)*(X-C)^N The factorial form of a polynomial is P(X) = A1 + A2*X + A3*(X)*(X-1) + A4*(X)*(X-1)*(X-2)+... + (AN+1)*(X)*(X-1)*...*(X-N+1) Licensing: This code is distributed under the MIT license. Modified: 25 March 2009 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the number of coefficients in the polynomial (in other words, the polynomial degree + 1) Input/output, int A[N], the coefficients of the polynomial. Depending on the option chosen, these coefficients may be overwritten by those of a different form of the polynomial. Input, int X0, for IOPT = -1, 0, or positive, the value of the argument at which the polynomial is to be evaluated, or the Taylor expansion is to be carried out. Input, int IOPT, a flag describing which algorithm is to be carried out: -3: Reverse Stirling. Input the coefficients of the polynomial in factorial form, output them in power sum form. -2: Stirling. Input the coefficients in power sum form, output them in factorial form. -1: Evaluate a polynomial which has been input in factorial form. 0: Evaluate a polynomial input in power sum form. 1 or more: Given the coefficients of a polynomial in power sum form, compute the first IOPT coefficients of the polynomial in Taylor expansion form. Output, int *VAL, for IOPT = -1 or 0, the value of the polynomial at the point X0. */ { int eps; int i; int m; int n1; int w; int z; n1 = i4_min ( n, iopt ); n1 = i4_max ( 1, n1 ); if ( iopt < -1 ) { n1 = n; } eps = i4_max ( -iopt, 0 ) % 2; w = - n * eps; if ( -2 < iopt ) { w = w + x0; } for ( m = 1; m <= n1; m++ ) { *val = 0; z = w; for ( i = m; i <= n; i++ ) { z = z + eps; *val = a[n+m-i-1] + z * *val; if ( iopt != 0 && iopt != -1 ) { a[n+m-i-1] = *val; } } if ( iopt < 0 ) { w = w + 1; } } return; } /******************************************************************************/ int *i4poly_add ( int na, int a[], int nb, int b[] ) /******************************************************************************/ /* Purpose: i4poly_add() adds two I4POLY's. Discussion: The polynomials are in power sum form. The power sum form is: p(x) = a(0) + a(1)*x + ... + a(n-1)*x^(n-1) + a(n)*x^(n) Licensing: This code is distributed under the MIT license. Modified: 21 November 2013 Author: John Burkardt Parameters: Input, int NA, the degree of polynomial A. Input, int A[NA+1], the coefficients of the first polynomial factor. Input, int NB, the degree of polynomial B. Input, int B[NB+1], the coefficients of the second polynomial factor. Output, int C[max(NA,NB)+1], the coefficients of A + B. */ { int i; int *c; c = ( int * ) malloc ( ( i4_max ( na, nb ) + 1 ) * sizeof ( int ) ); if ( nb == na ) { for ( i = 0; i <= na; i++ ) { c[i] = a[i] + b[i]; } } else if ( nb < na ) { for ( i = 0; i <= nb; i++ ) { c[i] = a[i] + b[i]; } for ( i = nb + 1; i <= na; i++ ) { c[i] = a[i]; } } else if ( na < nb ) { for ( i = 0; i <= na; i++ ) { c[i] = a[i] + b[i]; } for ( i = na + 1; i <= nb; i++ ) { c[i] = b[i]; } } return c; } /******************************************************************************/ void i4poly_cyclo ( int n, int phi[] ) /******************************************************************************/ /* Purpose: i4poly_cyclo() computes a cyclotomic polynomial. Discussion: For 1 <= N, let I = SQRT ( - 1 ) L = EXP ( 2 * PI * I / N ) Then the N-th cyclotomic polynomial is defined by PHI(N;X) = Product ( 1 <= K <= N and GCD(K,N) = 1 ) ( X - L^K ) We can use the Moebius MU function to write PHI(N;X) = Product ( mod ( D, N ) = 0 ) ( X^D - 1 )^MU(N/D) There is a sort of inversion formula: X^N - 1 = Product ( mod ( D, N ) = 0 ) PHI(D;X) Example: N PHI 0 1 1 X - 1 2 X + 1 3 X^2 + X + 1 4 X^2 + 1 5 X^4 + X^3 + X^2 + X + 1 6 X^2 - X + 1 7 X^6 + X^5 + X^4 + X^3 + X^2 + X + 1 8 X^4 + 1 9 X^6 + X^3 + 1 10 X^4 - X^3 + X^2 - X + 1 Licensing: This code is distributed under the MIT license. Modified: 25 March 2009 Author: John Burkardt Reference: Raymond Seroul, Programming for Mathematicians, Springer Verlag, 2000, page 269. Parameters: Input, int N, the index of the cyclotomic polynomial desired. Output, int PHI[N+1], the N-th cyclotomic polynomial. */ { # define POLY_MAX 100 int d; int den[POLY_MAX+1]; int den_n; int *factor; int i; int j; int mu; int nq; int nr; int num[POLY_MAX+1]; int num_n; int *rem; factor = ( int * ) malloc ( ( n + 1 ) * sizeof ( int ) ); rem = ( int * ) malloc ( ( n + 1 ) * sizeof ( int ) ); num[0] = 1; for ( i = 1; i <= POLY_MAX; i++ ) { num[i] = 0; } num_n = 0; den[0] = 1; for ( i = 1; i <= POLY_MAX; i++ ) { den[i] = 0; } den_n = 0; for ( i = 0; i <= n; i++ ) { phi[i] = 0; } for ( d = 1; d <= n; d++ ) { /* For each divisor D of N, ... */ if ( ( n % d ) == 0 ) { mu = i4_moebius ( n / d ); /* ...multiply the numerator or denominator by (X^D-1). */ factor[0] = -1; for ( j = 1; j <= d-1; j++ ) { factor[j] = 0; } factor[d] = 1; if ( mu == +1 ) { if ( POLY_MAX < num_n + d ) { printf ( "\n" ); printf ( "I4POLY_CYCLO - Warning!\n" ); printf ( " Numerator polynomial degree too high.\n" ); return; } i4poly_mul ( num_n, num, d, factor, num ); num_n = num_n + d; } else if ( mu == -1 ) { if ( POLY_MAX < den_n + d ) { printf ( "\n" ); printf ( "I4POLY_CYCLO - Warning!\n" ); printf ( " Denominator polynomial degree too high.\n" ); return; } i4poly_mul ( den_n, den, d, factor, den ); den_n = den_n + d; } } } /* PHI = NUM / DEN */ i4poly_div ( num_n, num, den_n, den, &nq, phi, &nr, rem ); free ( factor ); free ( rem ); return; # undef POLY_MAX } /******************************************************************************/ int i4poly_degree ( int na, int a[] ) /******************************************************************************/ /* Purpose: i4poly_degree() returns the degree of an I4POLY. Discussion: The degree of a polynomial is the index of the highest power of X with a nonzero coefficient. The degree of a constant polynomial is 0. The degree of the zero polynomial is debatable, but this routine returns the degree as 0. Licensing: This code is distributed under the MIT license. Modified: 25 March 2009 Author: John Burkardt Parameters: Input, int NA, the dimension of A. Input, int A[NA+1], the coefficients of the polynomials. Output, int I4POLY_DEGREE, the degree of the polynomial. */ { int degree; degree = na; while ( 0 < degree ) { if ( a[degree] != 0 ) { return degree; } degree = degree - 1; } return degree; } /******************************************************************************/ int *i4poly_dif ( int na, int a[], int d ) /******************************************************************************/ /* Purpose: i4poly_dif() differentiates an I4POLY. Discussion: The polynomials are in power sum form. The power sum form is: p(x) = a(0) + a(1)*x + ... + a(n-1)*x^(n-1) + a(n)*x^(n) Licensing: This code is distributed under the MIT license. Modified: 21 November 2013 Author: John Burkardt Parameters: Input, int NA, the degree of polynomial A. Input, int A[NA+1], the coefficients of a polynomial. Input, int D, the number of times the polynomial is to be differentiated. Output, int I4POLY_DIF[NA-D+1], the coefficients of the differentiated polynomial. */ { int *b; int i; if ( na < d ) { b = ( int * ) malloc ( 1 * sizeof ( int ) ); b[0] = 0; return b; } b = ( int * ) malloc ( ( na - d + 1 ) * sizeof ( int ) ); for ( i = 0; i <= na - d; i++ ) { b[i] = a[i+d] * i4_fall ( i + d, d ); } return b; } /******************************************************************************/ void i4poly_div ( int na, int a[], int nb, int b[], int *nq, int q[], int *nr, int r[] ) /******************************************************************************/ /* Purpose: i4poly_div() computes the quotient and remainder of two I4POLY's. Discussion: Normally, the quotient and remainder would have rational coefficients. This routine assumes that the special case applies that the quotient and remainder are known beforehand to be integral. The polynomials are assumed to be stored in power sum form. The power sum form is: p(x) = a(0) + a(1)*x + ... + a(n-1)*x^(n-1) + a(n)*x^(n) Licensing: This code is distributed under the MIT license. Modified: 25 March 2009 Author: John Burkardt Parameters: Input, int NA, the degree of polynomial A. Input, int A[NA+1], the coefficients of the polynomial to be divided. Input, int NB, the degree of polynomial B. Input, int B[NB+1], the coefficients of the divisor polynomial. Output, int *NQ, the degree of polynomial Q. If the divisor polynomial is zero, NQ is returned as -1. Output, int Q[NA-NB+1], contains the quotient of A/B. If A and B have full degree, Q should be dimensioned Q(0:NA-NB). In any case, Q(0:NA) should be enough. Output, int *NR, the degree of polynomial R. If the divisor polynomial is zero, NR is returned as -1. Output, int R[NB], contains the remainder of A/B. If B has full degree, R should be dimensioned R(0:NB-1). Otherwise, R will actually require less space. */ { int *a2; int i; int j; int na2; int nb2; na2 = i4poly_degree ( na, a ); nb2 = i4poly_degree ( nb, b ); if ( b[nb2] == 0 ) { *nq = -1; *nr = -1; return; } a2 = ( int * ) malloc ( ( na + 1 ) * sizeof ( int ) ); for ( i = 0; i <= na2; i++ ) { a2[i] = a[i]; } *nq = na2 - nb2; *nr = nb2 - 1; for ( i = *nq; 0 <= i; i-- ) { q[i] = a2[i+nb2] / b[nb2]; a2[i+nb2] = 0; for ( j = 0; j < nb2; j++ ) { a2[i+j] = a2[i+j] - q[i] * b[j]; } } for ( i = 0; i <= *nr; i++ ) { r[i] = a2[i]; } free ( a2 ); return; } /******************************************************************************/ void i4poly_mul ( int na, int a[], int nb, int b[], int c[] ) /******************************************************************************/ /* Purpose: i4poly_mul() computes the product of two I4POLY's. Discussion: The polynomials are in power sum form. The power sum form is: p(x) = a(0) + a(1)*x + ... + a(n-1)*x^(n-1) + a(n)*x^(n) Licensing: This code is distributed under the MIT license. Modified: 25 March 2009 Author: John Burkardt Parameters: Input, int NA, the degree of polynomial A. Input, int A[NA+1], the coefficients of the first polynomial factor. Input, int NB, the degree of polynomial B. Input, int B[NB+1], the coefficients of the second polynomial factor. Output, int C[NA+NB+1], the coefficients of A * B. */ { int *d; int i; int j; d = ( int * ) malloc ( (na+nb+1) * sizeof ( int ) ); for ( i = 0; i <= na+nb; i++ ) { d[i] = 0; } for ( i = 0; i <= na; i++ ) { for ( j = 0; j <= nb; j++ ) { d[i+j] = d[i+j] + a[i] * b[j]; } } for ( i = 0; i <= na+nb; i++ ) { c[i] = d[i]; } free ( d ); return; } /******************************************************************************/ void i4poly_print ( int n, int a[], char *title ) /******************************************************************************/ /* Purpose: i4poly_print() prints out an I4POLY. Discussion: The power sum form is: p(x) = a(0) + a(1)*x + ... + a(n-1)*x^(n-1) + a(n)*x^(n) Licensing: This code is distributed under the MIT license. Modified: 28 May 2003 Author: John Burkardt Parameters: Input, int N, the degree of polynomial A. Input, int A[N+1], the polynomial coefficients. A(0) is the constant term and A(N) is the coefficient of X^N. Input, char *TITLE, an optional title. */ { int i; int mag; int n2; char plus_minus; printf ( "\n" ); printf ( "%s\n", title ); printf ( "\n" ); n2 = i4poly_degree ( n, a ); if ( a[n2] < 0 ) { plus_minus = '-'; } else { plus_minus = ' '; } mag = abs ( a[n2] ); if ( 2 <= n2 ) { printf ( " p(x) = %c%d * x^%d\n", plus_minus, mag, n2 ); } else if ( n2 == 1 ) { printf ( " p(x) = %c%d * x\n", plus_minus, mag ); } else if ( n2 == 0 ) { printf ( " p(x) = %c%d\n", plus_minus, mag ); } for ( i = n2 - 1; 0 <= i; i-- ) { if ( a[i] < 0.0 ) { plus_minus = '-'; } else { plus_minus = '+'; } mag = abs ( a[i] ); if ( mag != 0 ) { if ( 2 <= i ) { printf ( " %c%d * x^%d\n", plus_minus, mag, i ); } else if ( i == 1 ) { printf ( " %c%d * x\n", plus_minus, mag ); } else if ( i == 0 ) { printf ( " %c%d\n", plus_minus, mag ); } } } return; } /******************************************************************************/ int i4poly_to_i4 ( int n, int a[], int x ) /******************************************************************************/ /* Purpose: i4poly_to_i4() evaluates an I4POLY. Discussion: The power sum form is: p(x) = a(0) + a(1)*x + ... + a(n-1)*x^(n-1) + a(n)*x^(n) Licensing: This code is distributed under the MIT license. Modified: 25 March 2009 Author: John Burkardt Parameters: Input, int N, the degree of the polynomial. Input, int A[N+1], the polynomial coefficients. A[0] is the constant term and A[N] is the coefficient of X^N. Input, int X, the point at which the polynomial is to be evaluated. Output, int I4POLY_TO_I4, the value of the polynomial. */ { int i; int value; value = 0; for ( i = n; 0 <= i; i-- ) { value = value * x + a[i]; } return value; } /******************************************************************************/ int i4vec_ascends ( int n, int x[] ) /******************************************************************************/ /* Purpose: i4vec_ascends() determines if an I4VEC is (weakly) ascending. Example: X = ( -8, 1, 2, 3, 7, 7, 9 ) I4VEC_ASCENDS = TRUE The sequence is not required to be strictly ascending. Licensing: This code is distributed under the MIT license. Modified: 14 April 2004 Author: John Burkardt Parameters: Input, int N, the size of the array. Input, int X[N], the array to be examined. Output, int I4VEC_ASCENDS, is TRUE if the entries of X ascend. */ { int i; for ( i = 1; i <= n-1; i++ ) { if ( x[i] < x[i-1] ) { return 0; } } return 1; } /******************************************************************************/ void i4vec_backtrack ( int n, int maxstack, int x[], int *indx, int *k, int *nstack, int stack[], int ncan[] ) /******************************************************************************/ /* Purpose: i4vec_backtrack() supervises a backtrack search for an I4VEC. Discussion: The routine tries to construct a vector one index at a time, using possible candidates as supplied by the user. At any time, the partially constructed vector may be discovered to be unsatisfactory, but the routine records information about where the last arbitrary choice was made, so that the search can be carried out efficiently, rather than starting out all over again. First, call the routine with INDX = 0 so it can initialize itself. Now, on each return from the routine, if INDX is: 1, you've just been handed a complete candidate vector; Admire it, analyze it, do what you like. 2, please determine suitable candidates for position X(K). Return the number of candidates in NCAN(K), adding each candidate to the end of STACK, and increasing NSTACK. 3, you're done. Stop calling the routine; Licensing: This code is distributed under the MIT license. Modified: 16 June 2015 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the number of positions to be filled in the vector. Input, int MAXSTACK, the maximum length of the stack. Input/output, int X[N], the partial or complete candidate vector. Input/output, int *INDX, a communication flag. On input, 0 to start a search. On output: 1, a complete output vector has been determined and returned in X(1:N); 2, candidates are needed for position X(K); 3, no more possible vectors exist. Input/output, int *K, if INDX=2, the current vector index being considered. Input/output, int *NSTACK, the current length of the stack. Input, int STACK[MAXSTACK], a list of all current candidates for all positions 1 through K. Input/output, int NCAN[N], lists the current number of candidates for positions 1 through K. */ { /* If this is the first call, request a candidate for position 1. */ if ( *indx == 0 ) { *k = 1; *nstack = 0; *indx = 2; return; } /* Examine the stack. */ for ( ; ; ) { /* If there are candidates for position K, take the first available one off the stack, and increment K. This may cause K to reach the desired value of N, in which case we need to signal the user that a complete set of candidates is being returned. */ if ( 0 < ncan[(*k)-1] ) { x[(*k)-1] = stack[(*nstack)-1]; *nstack = *nstack - 1; ncan[(*k)-1] = ncan[(*k)-1] - 1; if ( *k != n ) { *k = *k + 1; *indx = 2; } else { *indx = 1; } break; } /* If there are no candidates for position K, then decrement K. If K is still positive, repeat the examination of the stack. */ else { *k = *k - 1; if ( *k <= 0 ) { *indx = 3; break; } } } return; } /******************************************************************************/ int *i4vec_copy_new ( int n, int a1[] ) /******************************************************************************/ /* Purpose: i4vec_copy_new() copies an I4VEC. Discussion: An I4VEC is a vector of I4's. Licensing: This code is distributed under the MIT license. Modified: 04 July 2008 Author: John Burkardt Parameters: Input, int N, the number of entries in the vectors. Input, int A1[N], the vector to be copied. Output, int I4VEC_COPY_NEW[N], the copy of A1. */ { int *a2; int i; a2 = ( int * ) malloc ( n * sizeof ( int ) ); for ( i = 0; i < n; i++ ) { a2[i] = a1[i]; } return a2; } /******************************************************************************/ int i4vec_descends ( int n, int a[] ) /******************************************************************************/ /* Purpose: i4vec_descends() determines if an I4VEC is (weakly) descending. Discussion: An I4VEC is a vector of I4's. Example: X = ( 9, 7, 7, 3, 2, 1, -8 ) I4VEC_DESCENDS = TRUE The sequence is not required to be strictly descending. Licensing: This code is distributed under the MIT license. Modified: 06 September 2008 Author: John Burkardt Parameters: Input, int N, the size of the array. Input, int A[N], the array to be examined. Output, int I4VEC_DESCENDS, is TRUE if the entries of X descend. */ { int i; for ( i = 1; i <= n-1; i++ ) { if ( a[i-1] < a[i] ) { return 0; } } return 1; } /******************************************************************************/ int i4vec_dot_product ( int n, int x[], int y[] ) /******************************************************************************/ /* Purpose: i4vec_dot_product() computes the dot product of two I4VEC's. Discussion: An I4VEC is a vector of I4's. Licensing: This code is distributed under the MIT license. Modified: 19 December 2011 Author: John Burkardt Parameters: Input, int N, the size of the array. Input, int X[N], Y[N], the arrays. Output, int I4VEC_DOT_PRODUCT, the dot product of X and Y. */ { int i; int value; value = 0; for ( i = 0; i < n; i++ ) { value = value + x[i] * y[i]; } return value; } /******************************************************************************/ int i4vec_frac ( int n, int a[], int k ) /******************************************************************************/ /* Purpose: i4vec_frac() searches for the K-th smallest entry in an I4VEC. Discussion: An I4VEC is a vector of I4's. Hoare's algorithm is used. Licensing: This code is distributed under the MIT license. Modified: 18 September 2005 Parameters: Input, int N, the number of elements of A. Input/output, int A[N]. On input, A is the array to search. On output, the elements of A have been somewhat rearranged. Input, int K, the fractile to be sought. If K = 1, the minimum entry is sought. If K = N, the maximum is sought. Other values of K search for the entry which is K-th in size. K must be at least 1, and no greater than N. Output, double I4VEC_FRAC, the value of the K-th fractile of A. */ { int frac; int i; int iryt; int j; int left; int temp; int x; if ( n <= 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "I4VEC_FRAC(): Fatal error!\n" ); fprintf ( stderr, " Illegal nonpositive value of N = %d\n", n ); exit ( 1 ); } if ( k <= 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "I4VEC_FRAC(): Fatal error!\n" ); fprintf ( stderr, " Illegal nonpositive value of K = %d\n", k ); exit ( 1 ); } if ( n < k ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "I4VEC_FRAC(): Fatal error!\n" ); fprintf ( stderr, " Illegal N < K, K = %d\n", k ); exit ( 1 ); } left = 1; iryt = n; for ( ; ; ) { if ( iryt <= left ) { frac = a[k-1]; break; } x = a[k-1]; i = left; j = iryt; for ( ; ; ) { if ( j < i ) { if ( j < k ) { left = i; } if ( k < i ) { iryt = j; } break; } // // Find I so that X <= A(I). // while ( a[i-1] < x ) { i = i + 1; } // // Find J so that A(J) <= X. // while ( x < a[j-1] ) { j = j - 1; } if ( i <= j ) { temp = a[i-1]; a[i-1] = a[j-1]; a[j-1] = temp; i = i + 1; j = j - 1; } } } return frac; } /******************************************************************************/ void i4vec_heap_d ( int n, int a[] ) /******************************************************************************/ /* Purpose: i4vec_heap_d() reorders an I4VEC into a descending heap. Discussion: A heap is an array A with the property that, for every index J, A[J] >= A[2*J+1] and A[J] >= A[2*J+2], (as long as the indices 2*J+1 and 2*J+2 are legal). Diagram: A(0) / \ A(1) A(2) / \ / \ A(3) A(4) A(5) A(6) / \ / \ A(7) A(8) A(9) A(10) Licensing: This code is distributed under the MIT license. Modified: 30 April 1999 Author: John Burkardt Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the size of the input array. Input/output, int A[N]. On input, an unsorted array. On output, the array has been reordered into a heap. */ { int i; int ifree; int key; int m; /* Only nodes (N/2)-1 down to 0 can be "parent" nodes. */ for ( i = (n/2)-1; 0 <= i; i-- ) { /* Copy the value out of the parent node. Position IFREE is now "open". */ key = a[i]; ifree = i; for ( ; ; ) { /* Positions 2*IFREE + 1 and 2*IFREE + 2 are the descendants of position IFREE. (One or both may not exist because they equal or exceed N.) */ m = 2 * ifree + 1; /* Does the first position exist? */ if ( n <= m ) { break; } else { /* Does the second position exist? */ if ( m + 1 < n ) { /* If both positions exist, take the larger of the two values, and update M if necessary. */ if ( a[m] < a[m+1] ) { m = m + 1; } } /* If the large descendant is larger than KEY, move it up, and update IFREE, the location of the free position, and consider the descendants of THIS position. */ if ( key < a[m] ) { a[ifree] = a[m]; ifree = m; } else { break; } } } /* When you have stopped shifting items up, return the item you pulled out back to the heap. */ a[ifree] = key; } return; } /******************************************************************************/ int i4vec_index ( int n, int a[], int aval ) /******************************************************************************/ /* Purpose: i4vec_index() returns the location of the first occurrence of a given value. Licensing: This code is distributed under the MIT license. Modified: 22 March 2009 Author: John Burkardt Parameters: Input, int N, the number of entries in the vector. Input, int A[N], the vector to be searched. Input, int AVAL, the value to be indexed. Output, int I4VEC_INDEX, the first location in A which has the value AVAL, or -1 if no such index exists. */ { int i; for ( i = 0; i < n; i++ ) { if ( a[i] == aval ) { return i; } } return -1; } /******************************************************************************/ void i4vec_indicator0 ( int n, int a[] ) /******************************************************************************/ /* Purpose: i4vec_indicator0() sets an I4VEC to the indicator vector (0,1,2,...). Discussion: An I4VEC is a vector of I4's. Licensing: This code is distributed under the MIT license. Modified: 27 September 2014 Author: John Burkardt Parameters: Input, int N, the number of elements of A. Output, int A[N], the array. */ { int i; for ( i = 0; i < n; i++ ) { a[i] = i; } return; } /******************************************************************************/ int *i4vec_indicator0_new ( int n ) /******************************************************************************/ /* Purpose: i4vec_indicator0_new() sets an I4VEC to the indicator vector (0,1,2,...). Discussion: An I4VEC is a vector of I4's. Licensing: This code is distributed under the MIT license. Modified: 27 September 2014 Author: John Burkardt Parameters: Input, int N, the number of elements of A. Output, int I4VEC_INDICATOR0_NEW[N], the array. */ { int *a; int i; a = ( int * ) malloc ( n * sizeof ( int ) ); for ( i = 0; i < n; i++ ) { a[i] = i; } return a; } /******************************************************************************/ void i4vec_indicator1 ( int n, int a[] ) /******************************************************************************/ /* Purpose: i4vec_indicator1() sets an I4VEC to the indicator vector (1,2,3,...). Discussion: An I4VEC is a vector of I4's. Licensing: This code is distributed under the MIT license. Modified: 27 September 2014 Author: John Burkardt Parameters: Input, int N, the number of elements of A. Output, int A[N], the array. */ { int i; for ( i = 0; i < n; i++ ) { a[i] = i + 1; } return; } /******************************************************************************/ int *i4vec_indicator1_new ( int n ) /******************************************************************************/ /* Purpose: i4vec_indicator1_new() sets an I4VEC to the indicator vector. Discussion: An I4VEC is a vector of I4's. Licensing: This code is distributed under the MIT license. Modified: 26 August 2008 Author: John Burkardt Parameters: Input, int N, the number of elements of A. Output, int I4VEC_INDICATOR1_NEW[N], the initialized array. */ { int *a; int i; a = ( int * ) malloc ( n * sizeof ( int ) ); for ( i = 0; i < n; i++ ) { a[i] = i + 1; } return a; } /******************************************************************************/ int i4vec_max ( int n, int a[] ) /******************************************************************************/ /* Purpose: i4vec_max() returns the value of the maximum element in an I4VEC. Discussion: An I4VEC is a vector of I4's. Licensing: This code is distributed under the MIT license. Modified: 17 May 2003 Author: John Burkardt Parameters: Input, int N, the number of entries in the array. Input, int A[N], the array to be checked. Output, int IVEC_MAX, the value of the maximum element. This is set to 0 if N <= 0. */ { int i; int value; if ( n <= 0 ) { return 0; } value = a[0]; for ( i = 1; i < n; i++ ) { if ( value < a[i] ) { value = a[i]; } } return value; } /******************************************************************************/ int i4vec_maxloc_last ( int n, int x[] ) /******************************************************************************/ /* Purpose: i4vec_maxloc_last() returns the index of the last maximal I4VEC entry. Example: X = ( 5, 1, 2, 5, 0, 5, 3 ) I4VEC_MAXLOC_LAST = 5 Licensing: This code is distributed under the MIT license. Modified: 25 March 2009 Author: John Burkardt Parameters: Input, int N, the size of the array. Input, int X[N], the array to be examined. Output, int I4VEC_MAXLOC_LAST, the index of the last element of X of maximal value. */ { int i; int index; int value; index = 0; value = x[0]; for ( i = 1; i < n; i++ ) { if ( value <= x[i] ) { index = i; value = x[i]; } } return index; } /******************************************************************************/ int i4vec_min ( int n, int a[] ) /******************************************************************************/ /* Purpose: i4vec_min() returns the minimum element in an I4VEC. Discussion: An I4VEC is a vector of I4's. Licensing: This code is distributed under the MIT license. Modified: 17 May 2003 Author: John Burkardt Parameters: Input, int N, the number of entries in the array. Input, int A[N], the array to be checked. Output, int I4VEC_MIN, the value of the minimum element. This is set to 0 if N <= 0. */ { int i; int value; if ( n <= 0 ) { return 0; } value = a[0]; for ( i = 1; i < n; i++ ) { if ( a[i] < value ) { value = a[i]; } } return value; } /******************************************************************************/ int i4vec_pairwise_prime ( int n, int a[] ) /******************************************************************************/ /* Purpose: i4vec_pairwise_prime() checks whether an I4VEC is pairwise prime. Discussion: Two positive integers I and J are pairwise prime if they have no common factor greater than 1. Licensing: This code is distributed under the MIT license. Modified: 21 March 2009 Author: John Burkardt Parameters: Input, int N, the number of values to check. Input, int A[N], the vector of integers. Output, int I4VEC_PAIRWISE_PRIME, is TRUE if the vector of integers is pairwise prime. */ { int i; int j; for ( i = 0; i < n; i++ ) { for ( j = i+1; j < n; j++ ) { if ( i4_gcd ( a[i], a[j] ) != 1 ) { return 0; } } } return 1; } /******************************************************************************/ void i4vec_print ( int n, int a[], char *title ) /******************************************************************************/ /* Purpose: i4vec_print() prints an I4VEC. Discussion: An I4VEC is a vector of I4's. Licensing: This code is distributed under the MIT license. Modified: 14 November 2003 Author: John Burkardt Parameters: Input, int N, the number of components of the vector. Input, int A[N], the vector to be printed. Input, char *TITLE, a title. */ { int i; fprintf ( stdout, "\n" ); fprintf ( stdout, "%s\n", title ); fprintf ( stdout, "\n" ); for ( i = 0; i < n; i++ ) { fprintf ( stdout, " %6d: %8d\n", i, a[i] ); } return; } /******************************************************************************/ int i4vec_product ( int n, int a[] ) /******************************************************************************/ /* Purpose: i4vec_product() multiplies the entries of an I4VEC. Discussion: An I4VEC is a vector of I4's. Example: Input: A = ( 1, 2, 3, 4 ) Output: I4VEC_PRODUCT = 24 Licensing: This code is distributed under the MIT license. Modified: 26 August 2008 Author: John Burkardt Parameters: Input, int N, the number of entries in the vector. Input, int A[N], the vector Output, int I4VEC_PRODUCT, the product of the entries of A. */ { int i; int product; product = 1; for ( i = 0; i < n; i++ ) { product = product * a[i]; } return product; } /******************************************************************************/ void i4vec_reverse ( int n, int a[] ) /******************************************************************************/ /* Purpose: i4vec_reverse() reverses the elements of an I4VEC. Example: Input: N = 5, A = ( 11, 12, 13, 14, 15 ). Output: A = ( 15, 14, 13, 12, 11 ). Licensing: This code is distributed under the MIT license. Modified: 21 March 2009 Author: John Burkardt Parameters: Input, int N, the number of entries in the array. Input/output, int A[N], the array to be reversed. */ { int i; int temp; for ( i = 0; i < n/2; i++ ) { temp = a[i]; a[i] = a[n-1-i]; a[n-1-i] = temp; } return; } /******************************************************************************/ void i4vec_sort_bubble_a ( int n, int a[] ) /******************************************************************************/ /* Purpose: i4vec_sort_bubble_a() ascending sorts an integer array using bubble sort. Licensing: This code is distributed under the MIT license. Modified: 22 March 2009 Author: John Burkardt Parameters: Input, int N, the number of entries in the array. Input/output, int A[N]. On input, the array to be sorted; On output, the array has been sorted. */ { int i; int j; int k; for ( i = 0; i < n-1; i++ ) { for ( j = i+1; j < n; j++ ) { if ( a[j] < a[i] ) { k = a[i]; a[i] = a[j]; a[j] = k; } } } return; } /******************************************************************************/ void i4vec_sort_heap_a ( int n, int a[] ) /******************************************************************************/ /* Purpose: i4vec_sort_heap_a() ascending sorts an I4VEC using heap sort. Licensing: This code is distributed under the MIT license. Modified: 30 April 1999 Author: John Burkardt Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the number of entries in the array. Input/output, int A[N]. On input, the array to be sorted; On output, the array has been sorted. */ { int n1; int temp; if ( n <= 1 ) { return; } /* 1: Put A into descending heap form. */ i4vec_heap_d ( n, a ); /* 2: Sort A. The largest object in the heap is in A[0]. Move it to position A[N-1]. */ temp = a[0]; a[0] = a[n-1]; a[n-1] = temp; /* Consider the diminished heap of size N1. */ for ( n1 = n-1; 2 <= n1; n1-- ) { /* Restore the heap structure of the initial N1 entries of A. */ i4vec_heap_d ( n1, a ); /* Take the largest object from A[0] and move it to A[N1-1]. */ temp = a[0]; a[0] = a[n1-1]; a[n1-1] = temp; } return; } /******************************************************************************/ int *i4vec_sort_heap_index_a ( int n, int a[] ) /******************************************************************************/ /* Purpose: i4vec_sort_heap_index_a() does an indexed heap ascending sort of an integer vector. Discussion: The sorting is not actually carried out. Rather an index array is created which defines the sorting. This array may be used to sort or index the array, or to sort or index related arrays keyed on the original array. Once the index array is computed, the sorting can be carried out "implicitly: A(INDX(I)), I = 1 to N is sorted, after which A(I), I = 1 to N is sorted. Licensing: This code is distributed under the MIT license. Modified: 25 March 2009 Author: John Burkardt Parameters: Input, int N, the number of entries in the array. Input, int A[N], an array to be index-sorted. Output, int I4VEC_SORT_HEAP_INDEX_A[N], contains the sort index. The I-th element of the sorted array is A(INDX(I)). */ { int aval; int i; int *indx; int indxt; int ir; int j; int l; indx = i4vec_indicator1_new ( n ); l = n / 2 + 1; ir = n; for ( ; ; ) { if ( 1 < l ) { l = l - 1; indxt = indx[l-1]; aval = a[indxt-1]; } else { indxt = indx[ir-1]; aval = a[indxt-1]; indx[ir-1] = indx[0]; ir = ir - 1; if ( ir == 1 ) { indx[0] = indxt; for ( i = 0; i < n; i++ ) { indx[i] = indx[i] - 1; } return indx; } } i = l; j = l + l; while ( j <= ir ) { if ( j < ir ) { if ( a[indx[j-1]-1] < a[indx[j]-1] ) { j = j + 1; } } if ( aval < a[indx[j-1]-1] ) { indx[i-1] = indx[j-1]; i = j; j = j + j; } else { j = ir + 1; } } indx[i-1] = indxt; } } /******************************************************************************/ int *i4vec_sort_heap_index_d ( int n, int a[] ) /******************************************************************************/ /* Purpose: i4vec_sort_heap_index_d() does an indexed heap descending sort of an I4VEC. Discussion: The sorting is not actually carried out. Rather an index array is created which defines the sorting. This array may be used to sort or index the array, or to sort or index related arrays keyed on the original array. Once the index array is computed, the sorting can be carried out "implicitly: A(INDX(I)), I = 1 to N is sorted, after which A(I), I = 1 to N is sorted. Licensing: This code is distributed under the MIT license. Modified: 24 March 2009 Author: John Burkardt Parameters: Input, int N, the number of entries in the array. Input, int A[N], an array to be index-sorted. Output, int I4VEC_SORT_HEAP_INDEX_D[N], contains the sort index. The I-th element of the sorted array is A(INDX(I)). */ { int aval; int i; int *indx; int indxt; int ir; int j; int l; indx = i4vec_indicator1_new ( n ); l = n / 2 + 1; ir = n; for ( ; ; ) { if ( 1 < l ) { l = l - 1; indxt = indx[l-1]; aval = a[indxt-1]; } else { indxt = indx[ir-1]; aval = a[indxt-1]; indx[ir-1] = indx[0]; ir = ir - 1; if ( ir == 1 ) { indx[0] = indxt; for ( i = 0; i < n; i++ ) { indx[i] = indx[i] - 1; } return indx; } } i = l; j = l + l; while ( j <= ir ) { if ( j < ir ) { if ( a[indx[j]-1] < a[indx[j-1]-1] ) { j = j + 1; } } if ( a[indx[j-1]-1] < aval ) { indx[i-1] = indx[j-1]; i = j; j = j + j; } else { j = ir + 1; } } indx[i-1] = indxt; } } /******************************************************************************/ int i4vec_sum ( int n, int a[] ) /******************************************************************************/ /* Purpose: i4vec_sum() sums the entries of an I4VEC. Example: Input: A = ( 1, 2, 3, 4 ) Output: I4VEC_SUM = 10 Licensing: This code is distributed under the MIT license. Modified: 29 May 2003 Author: John Burkardt Parameters: Input, int N, the number of entries in the vector. Input, int A[N], the vector to be summed. Output, int I4VEC_SUM, the sum of the entries of A. */ { int i; int value; value = 0; for ( i = 0; i < n; i++ ) { value = value + a[i]; } return value; } /******************************************************************************/ void i4vec_transpose_print ( int n, int a[], char *title ) /******************************************************************************/ /* Purpose: i4vec_transpose_print() prints an I4VEC "transposed". Discussion: An I4VEC is a vector of I4's. Example: A = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 } TITLE = "My vector: " My vector: 1 2 3 4 5 6 7 8 9 10 11 Licensing: This code is distributed under the MIT license. Modified: 02 June 2015 Author: John Burkardt Parameters: Input, int N, the number of components of the vector. Input, int A[N], the vector to be printed. Input, char *TITLE, a title. */ { int i; int ihi; int ilo; int title_len; title_len = strlen ( title ); if ( 0 < title_len ) { printf ( "\n" ); printf ( "%s\n", title ); } if ( 0 < n ) { for ( ilo = 1; ilo <= n; ilo = ilo + 5 ) { ihi = i4_min ( ilo + 5 - 1, n ); for ( i = ilo; i <= ihi; i++ ) { printf ( "%12d", a[i-1] ); } printf ( "\n" ); } } else { printf ( " (empty vector)\n" ); } return; } /******************************************************************************/ int *i4vec_uniform_ab_new ( int n, int a, int b, int *seed ) /******************************************************************************/ /* Purpose: i4vec_uniform_ab_new() returns a scaled pseudorandom I4VEC. Discussion: The pseudorandom numbers should be uniformly distributed between A and B. Licensing: This code is distributed under the MIT license. Modified: 24 May 2012 Author: John Burkardt Reference: Paul Bratley, Bennett Fox, Linus Schrage, A Guide to Simulation, Second Edition, Springer, 1987, ISBN: 0387964673, LC: QA76.9.C65.B73. Bennett Fox, Algorithm 647: Implementation and Relative Efficiency of Quasirandom Sequence Generators, ACM Transactions on Mathematical Software, Volume 12, Number 4, December 1986, pages 362-376. Pierre L'Ecuyer, Random Number Generation, in Handbook of Simulation, edited by Jerry Banks, Wiley, 1998, ISBN: 0471134031, LC: T57.62.H37. Peter Lewis, Allen Goodman, James Miller, A Pseudo-Random Number Generator for the System/360, IBM Systems Journal, Volume 8, Number 2, 1969, pages 136-143. Parameters: Input, integer N, the dimension of the vector. Input, int A, B, the limits of the interval. Input/output, int *SEED, the "seed" value, which should NOT be 0. On output, SEED has been updated. Output, int I4VEC_UNIFORM_AB_NEW[N], a vector of random values between A and B. */ { int c; int i; const int i4_huge = 2147483647; int k; float r; int value; int *x; if ( *seed == 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "I4VEC_UNIFORM_AB_NEW(): Fatal error!\n" ); fprintf ( stderr, " Input value of SEED = 0.\n" ); exit ( 1 ); } /* Guaranteee A <= B. */ if ( b < a ) { c = a; a = b; b = c; } x = ( int * ) malloc ( n * sizeof ( int ) ); for ( i = 0; i < n; i++ ) { k = *seed / 127773; *seed = 16807 * ( *seed - k * 127773 ) - k * 2836; if ( *seed < 0 ) { *seed = *seed + i4_huge; } r = ( float ) ( *seed ) * 4.656612875E-10; /* Scale R to lie between A-0.5 and B+0.5. */ r = ( 1.0 - r ) * ( ( float ) a - 0.5 ) + r * ( ( float ) b + 0.5 ); /* Use rounding to convert R to an integer between A and B. */ value = round ( r ); /* Guarantee A <= VALUE <= B. */ if ( value < a ) { value = a; } if ( b < value ) { value = b; } x[i] = value; } return x; } /******************************************************************************/ void i4vec0_print ( int n, int a[], char *title ) /******************************************************************************/ /* Purpose: i4vec0_print() prints an integer vector (0-based indices). Licensing: This code is distributed under the MIT license. Modified: 24 March 2009 Author: John Burkardt Parameters: Input, int N, the number of components of the vector. Input, int A[N], the vector to be printed. Input, char *TITLE, a title to be printed first. TITLE may be blank. */ { int i; if ( s_len_trim ( title ) != 0 ) { printf ( "\n" ); printf ( "%s\n", title ); } printf ( "\n" ); for ( i = 0; i <= n-1; i++ ) { printf ( "%6d %8d\n", i, a[i] ); } return; } /******************************************************************************/ void i4vec1_print ( int n, int a[], char *title ) /******************************************************************************/ /* Purpose: i4vec1_print() prints an integer vector (one-based indices). Licensing: This code is distributed under the MIT license. Modified: 24 March 2009 Author: John Burkardt Parameters: Input, int N, the number of components of the vector. Input, int A[N], the vector to be printed. Input, char *TITLE, a title. */ { int i; printf ( "\n" ); printf ( "%s\n", title ); printf ( "\n" ); for ( i = 0; i <= n-1; i++ ) { printf ( " %6d %8d\n", i, a[i] ); } return; } /******************************************************************************/ void index_box2_next_2d ( int n1, int n2, int ic, int jc, int *i, int *j, int *more ) /******************************************************************************/ /* Purpose: index_box2_next_2d() produces index vectors on the surface of a box in 2D. Discussion: The box has center at (IC,JC), and half-widths N1 and N2. The index vectors are exactly those which are between (IC-N1,JC-N1) and (IC+N1,JC+N2) with the property that at least one of I and J is an "extreme" value. Licensing: This code is distributed under the MIT license. Modified: 24 March 2009 Author: John Burkardt Parameters: Input, int N1, N2, the half-widths of the box, that is, the maximum distance allowed between (IC,JC) and (I,J). Input, int IC, JC, the central cell of the box. Input/output, int *I, *J. On input, the previous index set. On output, the next index set. On the first call, MORE should be set to FALSE, and the input values of I and J are ignored. Input/output, int *MORE. On the first call for a given box, the user should set MORE to FALSE. On return, the routine sets MORE to TRUE. When there are no more indices, the routine sets MORE to FALSE. */ { if ( !( *more ) ) { *more = 1; *i = ic - n1; *j = jc - n2; return; } if ( *i == ic + n1 && *j == jc + n2 ) { *more = 0; return; } /* Increment J. */ *j = *j + 1; /* Check J. */ if ( jc + n2 < *j ) { *j = jc - n2; *i = *i + 1; } else if ( *j < jc + n2 && ( *i == ic - n1 || *i == ic + n1 ) ) { return; } else { *j = jc + n2; return; } return; } /******************************************************************************/ void index_box2_next_3d ( int n1, int n2, int n3, int ic, int jc, int kc, int *i, int *j, int *k, int *more ) /******************************************************************************/ /* Purpose: index_box2_next_3d() produces index vectors on the surface of a box in 3D. Discussion: The box has a central cell of (IC,JC,KC), with half widths of (N1,N2,N3). The index vectors are exactly those between (IC-N1,JC-N2,KC-N3) and (IC+N1,JC+N2,KC+N3) with the property that at least one of I, J, and K is an "extreme" value. Licensing: This code is distributed under the MIT license. Modified: 24 March 2009 Author: John Burkardt Parameters: Input, int N1, N2, N3, the "half widths" of the box, that is, the maximum distances from the central cell allowed for I, J and K. Input, int IC, JC, KC, the central cell of the box. Input/output, int *I, *J, *K. On input, the previous index set. On output, the next index set. On the first call, MORE should be set to FALSE, and the input values of I, J, and K are ignored. Input/output, int *MORE. On the first call for a given box, the user should set MORE to FALSE. On return, the routine sets MORE to TRUE. When there are no more indices, the routine sets MORE to FALSE. */ { if ( !( *more ) ) { *more = 1; *i = ic - n1; *j = jc - n2; *k = kc - n3; return; } if ( *i == ic + n1 && *j == jc + n2 && *k == kc + n3 ) { *more = 0; return; } /* Increment K. */ *k = *k + 1; /* Check K. */ if ( kc + n3 < *k ) { *k = kc - n3; *j = *j + 1; } else if ( *k < kc + n3 && ( *i == ic - n1 || *i == ic + n1 || *j == jc - n2 || *j == jc + n2 ) ) { return; } else { *k = kc + n3; return; } /* Check J. */ if ( jc + n2 < *j ) { *j = jc - n2; *i = *i + 1; } else if ( *j < jc + n2 && ( *i == ic - n1 || *i == ic + n1 || *k == kc - n3 || *k == kc + n3 ) ) { return; } else { *j = jc + n2; return; } return; } /******************************************************************************/ void index_box_next_2d ( int n1, int n2, int *i, int *j, int *more ) /******************************************************************************/ /* Purpose: index_box_next_2d() produces index vectors on the surface of a box in 2D. Discussion: The index vectors are exactly those which are between (1,1) and (N1,N2) with the property that at least one of I and J is an "extreme" value. Licensing: This code is distributed under the MIT license. Modified: 24 March 2009 Author: John Burkardt Parameters: Input, int N1, N2, the "dimensions" of the box, that is, the maximum values allowed for I and J. The minimum values are assumed to be 1. Input/output, int *I, *J. On input, the previous index set. On output, the next index set. On the first call, MORE should be set to FALSE, and the input values of I and J are ignored. Input/output, int *MORE. On the first call for a given box, the user should set MORE to FALSE. On return, the routine sets MORE to TRUE. When there are no more indices, the routine sets MORE to FALSE. */ { if ( !( *more ) ) { *more = 1; *i = 1; *j = 1; return; } if ( *i == n1 && *j == n2 ) { *more = 0; return; } /* Increment J. */ *j = *j + 1; /* Check J. */ if ( n2 < *j ) { *j = 1; *i = *i + 1; } else if ( *j < n2 && ( *i == 1 || *i == n1 ) ) { return; } else { *j = n2; return; } return; } /******************************************************************************/ void index_box_next_3d ( int n1, int n2, int n3, int *i, int *j, int *k, int *more ) /******************************************************************************/ /* Purpose: index_box_next_3d() produces index vectors on the surface of a box in 3D. Discussion: The index vectors are exactly those which are between (1,1,1) and (N1,N2,N3) with the property that at least one of I, J, and K is an "extreme" value. Licensing: This code is distributed under the MIT license. Modified: 24 March 2009 Author: John Burkardt Parameters: Input, int N1, N2, N3, the "dimensions" of the box, that is, the maximum values allowed for I, J and K. The minimum values are assumed to be 1. Input/output, int *I, *J, *K. On input, the previous index set. On output, the next index set. On the first call, MORE should be set to FALSE, and the input values of I, J, and K are ignored. Input/output, int *MORE. On the first call for a given box, the user should set MORE to FALSE. On return, the routine sets MORE to TRUE. When there are no more indices, the routine sets MORE to FALSE. */ { if ( !( *more ) ) { *more = 1; *i = 1; *j = 1; *k = 1; return; } if ( *i == n1 && *j == n2 && *k == n3 ) { *more = 0; return; } /* Increment K. */ *k = *k + 1; /* Check K. */ if ( n3 < *k ) { *k = 1; *j = *j + 1; } else if ( *k < n3 && ( *i == 1 || *i == n1 || *j == 1 || *j == n2 ) ) { return; } else { *k = n3; return; } /* Check J. */ if ( n2 < *j ) { *j = 1; *i = *i + 1; } else if ( *j < n2 && ( *i == 1 || *i == n1 || *k == 1 || *k == n3 ) ) { return; } else { *j = n2; return; } return; } /******************************************************************************/ void index_next0 ( int n, int hi, int a[], int *more ) /******************************************************************************/ /* Purpose: index_next0() generates all index vectors within given upper limits. Discussion: The index vectors are generated in such a way that the reversed sequences are produced in lexicographic order. Example: N = 3, HI = 3 1 2 3 --------- 1 1 1 2 1 1 3 1 1 1 2 1 2 2 1 3 2 1 1 3 1 2 3 1 3 3 1 1 1 2 2 1 2 3 1 2 1 2 2 2 2 2 3 2 2 1 3 2 2 3 2 3 3 2 1 1 3 2 1 3 3 1 3 1 2 3 2 2 3 3 2 3 1 3 3 2 3 3 3 3 3 Licensing: This code is distributed under the MIT license. Modified: 24 March 2009 Author: John Burkardt Parameters: Input, int N, the number of entries in A. Input, int HI, the upper limit for the array indices. The lower limit is implicitly 1 and HI must be at least 1. Input/output, int A[N]. On startup calls, with MORE = FALSE, the input value of A doesn't matter, because the routine initializes it. On calls with MORE = TRUE, the input value of A must be the output value of A from the previous call. (In other words, just leave it alone!). On output, A contains the successor set of indices to the input value. Input/output, int *MORE. Set this variable FALSE before the first call. Normally, MORE will be returned TRUE but once all the vectors have been generated, MORE will be reset FALSE and you should stop calling the program. */ { int i; int inc; if ( !( *more ) ) { for ( i = 0; i < n; i++ ) { a[i] = 1; } if ( hi < 1 ) { *more = 0; printf ( "\n" ); printf ( "INDEX_NEXT0 - Warning!\n" ); printf ( " HI is %d\n", hi ); printf ( " but HI must be at least 1.\n" ); return; } } else { inc = 0; while ( hi <= a[inc] ) { a[inc] = 1; inc = inc + 1; } a[inc] = a[inc] + 1; } /* See if there are more entries to compute. */ *more = 0; for ( i = 0; i < n; i++ ) { if ( a[i] < hi ) { *more = 1; } } return; } /******************************************************************************/ void index_next1 ( int n, int hi[], int a[], int *more ) /******************************************************************************/ /* Purpose: index_next1() generates all index vectors within given upper limits. Discussion: The index vectors are generated in such a way that the reversed sequences are produced in lexicographic order. Example: N = 3, HI(1) = 4, HI(2) = 2, HI(3) = 3 1 2 3 --------- 1 1 1 2 1 1 3 1 1 4 1 1 1 2 1 2 2 1 3 2 1 4 2 1 1 1 2 2 1 2 3 1 2 4 1 2 1 2 2 2 2 2 3 2 2 4 2 2 1 1 3 2 1 3 3 1 3 4 1 3 1 2 3 2 2 3 3 2 3 4 2 3 Licensing: This code is distributed under the MIT license. Modified: 24 March 2009 Author: John Burkardt Parameters: Input, int N, the number of entries in A. Input, int HI[N], the upper limits for the array indices. The lower limit is implicitly 1, and each HI(I) should be at least 1. Input/output, int A[N]. On startup calls, with MORE = FALSE, the input value of A doesn't matter, because the routine initializes it. On calls with MORE = TRUE, the input value of A must be the output value of A from the previous call. (In other words, just leave it alone!). On output, A contains the successor set of indices to the input value. Input/output, int *MORE. Set this variable FALSE before the first call. Normally, MORE will be returned TRUE but once all the vectors have been generated, MORE will be reset FALSE and you should stop calling the program. */ { int i; int inc; if ( !( *more ) ) { for ( i = 0; i < n; i++ ) { a[i] = 1; } for ( i = 0; i < n; i++ ) { if ( hi[i] < 1 ) { more = 0; printf ( "\n" ); printf ( "INDEX_NEXT1 - Warning!\n" ); printf ( " Entry %d of HI is %d\n", i, hi[i] ); printf ( " but all entries must be at least 1.\n" ); return; } } } else { inc = 0; while ( hi[inc] <= a[inc] ) { a[inc] = 1; inc = inc + 1; } a[inc] = a[inc] + 1; } /* See if there are more entries to compute. */ *more = 0; for ( i = 0; i < n; i++ ) { if ( a[i] < hi[i] ) { *more = 1; } } return; } /******************************************************************************/ void index_next2 ( int n, int lo[], int hi[], int a[], int *more ) /******************************************************************************/ /* Purpose: index_next2() generates all index vectors within given lower and upper limits. Example: N = 3, LO(1) = 1, LO(2) = 10, LO(3) = 4 HI(1) = 2, HI(2) = 11, HI(3) = 6 1 2 3 --------- 1 10 4 2 10 4 1 11 4 2 11 4 1 10 5 2 10 5 1 11 5 2 11 5 1 10 6 2 10 6 1 11 6 2 11 6 Licensing: This code is distributed under the MIT license. Modified: 24 March 2009 Author: John Burkardt Parameters: Input, int N, the number of entries in A. The rank of the object being indexed. Input, int LO[N], HI[N], the lower and upper limits for the array indices. LO(I) should be less than or equal to HI(I), for each I. Input/output, int A[N]. On startup calls, with MORE = FALSE, the input value of A doesn't matter, because the routine initializes it. On calls with MORE = TRUE, the input value of A must be the output value of A from the previous call. (In other words, just leave it alone!). On output, A contains the successor set of indices to the input value. Input/output, int *MORE. Set this variable FALSE before the first call. Normally, MORE will be returned TRUE but once all the vectors have been generated, MORE will be reset FALSE and you should stop calling the program. */ { int i; int inc; if ( !( *more ) ) { for ( i = 0; i < n; i++ ) { a[i] = lo[i]; } for ( i = 0; i < n; i++ ) { if ( hi[i] < lo[i] ) { more = 0; printf ( "\n" ); printf ( "INDEX_NEXT2 - Warning!\n" ); printf ( " Entry %d of HI is %d\n", i, hi[i] ); printf ( " Entry %d of LO is %d\n", i, lo[i] ); printf ( " but LO(I) <= HI(I) is required.\n" ); return; } } } else { inc = 0; while ( hi[inc] <= a[inc] ) { a[inc] = lo[inc]; inc = inc + 1; } a[inc] = a[inc] + 1; } /* See if there are more entries to compute. */ *more = 0; for ( i = 0; i < n; i++ ) { if ( a[i] < hi[i] ) { *more = 1; } } return; } /******************************************************************************/ int index_rank0 ( int n, int hi, int a[] ) /******************************************************************************/ /* Purpose: index_rank0() ranks an index vector within given upper limits. Example: N = 3, HI = 3 A = ( 3, 1, 2 ) RANK = 12 Licensing: This code is distributed under the MIT license. Modified: 24 March 2009 Author: John Burkardt Parameters: Input, int N, the number of entries in A. Input, int HI, the upper limit for the array indices. The lower limit is implicitly 1, and HI should be at least 1. Input, int A[N], the index vector to be ranked. Output, int INDEX_RANK0, the rank of the index vector, or -1 if A is not a legal index. */ { int i; int range; int rank; rank = -1; for ( i = 0; i < n; i++ ) { if ( a[i] < 1 || hi < a[i] ) { return rank; } } rank = 0; for ( i = n-1; 0 <= i; i-- ) { rank = hi * rank + a[i]; } rank = 1; range = 1; for ( i = 0; i < n; i++ ) { rank = rank + ( a[i] - 1 ) * range; range = range * hi; } return rank; } /******************************************************************************/ int index_rank1 ( int n, int hi[], int a[] ) /******************************************************************************/ /* Purpose: index_rank1() ranks an index vector within given upper limits. Example: N = 3, HI(1) = 4, HI(2) = 2, HI(3) = 3 A = ( 4, 1, 2 ) RANK = 12 Licensing: This code is distributed under the MIT license. Modified: 24 March 2009 Author: John Burkardt Parameters: Input, int N, the number of entries in A. Input, int HI[N], the upper limits for the array indices. The lower limit is implicitly 1, and each HI(I) should be at least 1. Input, int A[N], the index to be ranked. Output, int INDEX_RANK1, the rank of the index vector, or -1 if A is not a legal index. */ { int i; int range; int rank; rank = -1; for ( i = 0; i < n; i++ ) { if ( a[i] < 1 || hi[i] < a[i] ) { return rank; } } rank = 0; for ( i = n-1; 0 <= i; i-- ) { rank = hi[i] * rank + a[i]; } rank = 1; range = 1; for ( i = 0; i < n; i++ ) { rank = rank + ( a[i] - 1 ) * range; range = range * hi[i]; } return rank; } /******************************************************************************/ int index_rank2 ( int n, int lo[], int hi[], int a[] ) /******************************************************************************/ /* Purpose: index_rank2() ranks an index vector within given lower and upper limits. Example: N = 3, LO(1) = 1, LO(2) = 10, LO(3) = 4 HI(1) = 2, HI(2) = 11, HI(3) = 6 A = ( 1, 11, 5 ) RANK = 7 Licensing: This code is distributed under the MIT license. Modified: 24 March 2009 Author: John Burkardt Parameters: Input, int N, the number of entries in A. Input, int LO[N], HI[N], the lower and upper limits for the array indices. LO(I) should be less than or equal to HI(I), for each I. Input, int A[N], the index vector to be ranked. Output, int INDEX_RANK2, the rank of the index vector, or -1 if A is not a legal index vector. */ { int i; int range; int rank; for ( i = 0; i < n; i++ ) { if ( a[i] < lo[i] || hi[i] < a[i] ) { rank = -1; return rank; } } rank = 1; range = 1; for ( i = 0; i < n; i++ ) { rank = rank + ( a[i] - lo[i] ) * range; range = range * ( hi[i] + 1 - lo[i] ); } return rank; } /******************************************************************************/ void index_unrank0 ( int n, int hi, int rank, int a[] ) /******************************************************************************/ /* Purpose: index_unrank0() unranks an index vector within given upper limits. Example: N = 3, HI = 3 RANK = 12 A = ( 3, 1, 2 ) Licensing: This code is distributed under the MIT license. Modified: 24 March 2009 Author: John Burkardt Parameters: Input, int N, the number of entries in A. Input, int HI, the upper limit for the array indices. The lower limit is implicitly 1, and HI should be at least 1. Input, int RANK, the rank of the desired index vector. Output, int A[N], the index vector of the given rank. */ { int i; int j; int k; int range; for ( i = 0; i < n; i++ ) { a[i] = 0; } /* The rank might be too small. */ if ( rank < 1 ) { return; } range = i4_power ( hi, n ); /* The rank might be too large. */ if ( range < rank ) { return; } k = rank - 1; for ( i = n-1; 0 <= i; i-- ) { range = range / hi; j = k / range; a[i] = j + 1; k = k - j * range; } return; } /******************************************************************************/ void index_unrank1 ( int n, int hi[], int rank, int a[] ) /******************************************************************************/ /* Purpose: index_unrank1() unranks an index vector within given upper limits. Example: N = 3, HI(1) = 4, HI(2) = 2, HI(3) = 3 RANK = 11 A = ( 3, 1, 2 ) Licensing: This code is distributed under the MIT license. Modified: 24 March 2009 Author: John Burkardt Parameters: Input, int N, the number of entries in A. Input, int HI[N], the upper limits for the array indices. The lower limit is implicitly 1, and each HI(I) should be at least 1. Input, int RANK, the rank of the desired index vector. Output, int A[N], the index vector of the given rank. */ { int i; int j; int k; int range; for ( i = 0; i < n; i++ ) { a[i] = 0; } /* The rank might be too small. */ if ( rank < 1 ) { return; } range = i4vec_product ( n, hi ); /* The rank might be too large. */ if ( range < rank ) { return; } k = rank - 1; for ( i = n-1; 0 <= i; i-- ) { range = range / hi[i]; j = k / range; a[i] = j + 1; k = k - j * range; } return; } /******************************************************************************/ void index_unrank2 ( int n, int lo[], int hi[], int rank, int a[] ) /******************************************************************************/ /* Purpose: index_unrank2() unranks an index vector within given lower and upper limits. Example: N = 3, LO(1) = 1, LO(2) = 10, LO(3) = 4 HI(1) = 2, HI(2) = 11, HI(3) = 6 RANK = 7 A = ( 1, 11, 5 ) Licensing: This code is distributed under the MIT license. Modified: 24 March 2009 Author: John Burkardt Parameters: Input, int N, the number of entries in A. Input, int LO[N], HI[N], the lower and upper limits for the array indices. It should be the case that LO(I) <= HI(I) for each I. Input, int RANK, the rank of the desired index. Output, int A[N], the index vector of the given rank. */ { int i; int j; int k; int range; for ( i = 0; i < n; i++ ) { a[i] = 0; } /* The rank might be too small. */ if ( rank < 1 ) { return; } range = 1; for ( i = 0; i < n; i++ ) { range = range * ( hi[i] + 1 - lo[i] ); } /* The rank might be too large. */ if ( range < rank ) { return; } k = rank - 1; for ( i = n-1; 0 <= i; i-- ) { range = range / ( hi[i] + 1 - lo[i] ); j = k / range; a[i] = j + lo[i]; k = k - j * range; } return; } /******************************************************************************/ int inverse_mod_n ( int b, int n ) /******************************************************************************/ /* Purpose: inverse_mod_n() computes the inverse of B mod N. Discussion: If Y = inverse_mod_n ( B, N ) then mod ( B * Y, N ) = 1 The value Y will exist if and only if B and N are relatively prime. Examples: B N Y 1 2 1 1 3 1 2 3 2 1 4 1 2 4 0 3 4 3 1 5 1 2 5 3 3 5 2 4 5 4 1 6 1 2 6 0 3 6 0 4 6 0 5 6 5 1 7 1 2 7 4 3 7 5 4 7 2 5 7 3 6 7 6 1 8 1 2 8 0 3 8 3 4 8 0 5 8 5 6 8 0 7 8 7 Licensing: This code is distributed under the MIT license. Modified: 03 November 2009 Author: John Burkardt Parameters: Input, int B, the number whose inverse mod N is desired. B should be positive. Normally, B < N, but this is not required. Input, int N, the number with respect to which the modulus is computed. N should be positive. Output, int INVERSE_MOD_N, the inverse of B mod N, or 0 if there is not inverse for B mode N. */ { int b0; int n0; int q; int r; int t; int t0; int temp; int y; n0 = n; b0 = b; t0 = 0; t = 1; q = n / b; r = n - q * b; while ( 0 < r ) { temp = t0 - q * t; if ( 0 <= temp ) { temp = ( temp % n ); } if ( temp < 0 ) { temp = n - ( ( - temp ) % n ); } t0 = t; t = temp; n0 = b0; b0 = r; q = n0 / b0; r = n0 - q * b0; } if ( b0 != 1 ) { y = 0; return y; } y = ( t % n ); return y; } /******************************************************************************/ void inversion_to_perm0 ( int n, int ins[], int p[] ) /******************************************************************************/ /* Purpose: inversion_to_perm0(): inversion sequence to permutation (0,...,N-1). Discussion: For a given permutation P acting on objects 0 through N-1, the inversion sequence INS is defined as: INS(1) = 0 INS(I) = number of values J < I for which P(I) < P(J). Example: Input: ( 0, 0, 2, 1, 3 ) Output: ( 2, 4, 0, 3, 1 ) Licensing: This code is distributed under the MIT license. Modified: 05 June 2015 Author: John Burkardt Reference: Dennis Stanton, Dennis White, Constructive Combinatorics, Springer, 1986, ISBN: 0387963472, LC: QA164.S79. Parameters: Input, int N, the number of objects being permuted. Input, int INS[N], the inversion sequence of a permutation. It must be the case that 0 <= INS(I) < I for 1 <= I <= N. Output, int P[N], the permutation. */ { int i; int itemp; int j; i4vec_indicator0 ( n, p ); for ( i = n - 1; 1 <= i; i-- ) { itemp = p[i-ins[i]]; for ( j = i-ins[i]; j <= i-1; j++ ) { p[j] = p[j+1]; } p[i] = itemp; } return; } /******************************************************************************/ void involute_enum ( int n, int s[] ) /******************************************************************************/ /* Purpose: involute_enum() enumerates the involutions of N objects. Discussion: An involution is a permutation consisting only of fixed points and pairwise transpositions. An involution is its own inverse permutation. Recursion: S(0) = 1 S(1) = 1 S(N) = S(N-1) + (N-1) * S(N-2) First values: N S(N) 0 1 1 1 2 2 3 4 4 10 5 26 6 76 7 232 8 764 9 2620 10 9496 Licensing: This code is distributed under the MIT license. Modified: 24 March 2009 Author: John Burkardt Parameters: Input, int N, the number of objects to be permuted. Output, int S[N+1], the number of involutions of 0, 1, 2, ... N objects. */ { int i; if ( n < 0 ) { return; } s[0] = 1; if ( n <= 0 ) { return; } s[1] = 1; for ( i = 2; i <= n; i++ ) { s[i] = s[i-1] + ( i - 1 ) * s[i-2]; } return; } /******************************************************************************/ void jfrac_to_rfrac ( int m, double r[], double s[], double p[], double q[] ) /******************************************************************************/ /* Purpose: jfrac_to_rfrac() converts a J-fraction into a rational polynomial fraction. Discussion: The routine accepts a J-fraction: R(1) / ( X + S(1) + R(2) / ( X + S(2) + R(3) / ... + R(M) / ( X + S(M) )... )) and returns the equivalent rational polynomial fraction: P(1) + P(2) * X + ... + P(M) * X^(M-1) ------------------------------------------------------- Q(1) + Q(2) * X + ... + Q(M) * X^(M-1) + Q(M+1) * X^M Licensing: This code is distributed under the MIT license. Modified: 24 March 2009 Author: Original FORTRAN77 version by John Hart, Ward Cheney, Charles Lawson, Hans Maehly, Charles Mesztenyi, John Rice, Henry Thatcher, Christop Witzgall. This version by John Burkardt. Reference: John Hart, Ward Cheney, Charles Lawson, Hans Maehly, Charles Mesztenyi, John Rice, Henry Thatcher, Christoph Witzgall, Computer Approximations, Wiley, 1968. Parameters: Input, int M, defines the number of P, R, and S coefficients, and is one less than the number of Q coefficients. Input, double R[M], S[M], the coefficients defining the J-fraction. Output, double P[M], Q[M+1], the coefficients defining the rational polynomial fraction. The algorithm used normalizes the coefficients so that Q[M+1] = 1.0. */ { double *a; double *b; int i; int k; a = ( double * ) malloc ( m * m * sizeof ( double ) ); b = ( double * ) malloc ( m * m * sizeof ( double ) ); a[0+0*m] = r[0]; b[0+0*m] = s[0]; if ( 1 < m ) { for ( k = 1; k < m; k++ ) { a[k+k*m] = r[0]; b[k+k*m] = b[k-1+(k-1)*m] + s[k]; } a[0+1*m] = r[0] * s[1]; b[0+1*m] = r[1] + s[0] * s[1]; for ( k = 2; k < m; k++ ) { a[0 +k*m] = s[k] * a[0+(k-1)*m] + r[k] * a[0+(k-2)*m]; a[k-1+k*m] = a[k-2+(k-1)*m] + s[k] * r[0]; b[0 +k*m] = s[k] * b[0+(k-1)*m] + r[k] * b[0+(k-2)*m]; b[k-1+k*m] = b[k-2+(k-1)*m] + s[k] * b[k-1+(k-1)*m] + r[k]; } for ( k = 2; k < m; k++ ) { for ( i = 1; i < k-1; i++ ) { a[i+k*m] = a[i-1+(k-1)*m] + s[k] * a[i+(k-1)*m] + r[k] * a[i+(k-2)*m]; b[i+k*m] = b[i-1+(k-1)*m] + s[k] * b[i+(k-1)*m] + r[k] * b[i+(k-2)*m]; } } } for ( i = 0; i < m; i++ ) { p[i] = a[i+(m-1)*m]; } for ( i = 0; i < m; i++ ) { q[i] = b[i+(m-1)*m]; } q[m] = 1.0; free ( a ); free ( b ); return; } /******************************************************************************/ int josephus ( int n, int m, int k ) /******************************************************************************/ /* Purpose: josephus() returns the position X of the K-th man to be executed. Discussion: The classic Josephus problem concerns a circle of 41 men. Every third man is killed and removed from the circle. Counting and executing continues until all are dead. Where was the last survivor sitting? Note that the first person killed was sitting in the third position. Moreover, when we get down to 2 people, and we need to count the "third" one, we just do the obvious thing, which is to keep counting around the circle until our count is completed. The process may be regarded as generating a permutation of the integers from 1 to N. The permutation would be the execution list, that is, the list of the executed men, by position number. Licensing: This code is distributed under the MIT license. Modified: 24 March 2009 Author: John Burkardt. Reference: W W Rouse Ball, Mathematical Recreations and Essays, Macmillan, 1962, pages 32-36. Donald Knuth, The Art of Computer Programming, Volume 1, Fundamental Algorithms, Addison Wesley, 1968, pages 158-159. Donald Knuth, The Art of Computer Programming, Volume 3, Sorting and Searching, Addison Wesley, 1968, pages 18-19. Parameters: Input, int N, the number of men. N must be positive. Input, int M, the counting index. M must not be zero. Ordinarily, M is positive, and no greater than N. Input, int K, the index of the executed man of interest. K must be between 1 and N. Output, int JOSEPHUS, the position of the K-th man. The value will be between 1 and N. */ { int m2; int x; if ( n <= 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "JOSEPHUS(): Fatal error!\n" ); fprintf ( stderr, " N <= 0.\n" ); exit ( 1 ); } if ( m == 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "JOSEPHUS(): Fatal error!\n" ); fprintf ( stderr, " M = 0.\n" ); exit ( 1 ); } if ( k <= 0 || n < k ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "JOSEPHUS(): Fatal error!\n" ); fprintf ( stderr, " J <= 0 or N < K.\n" ); exit ( 1 ); } /* In case M is bigger than N, or negative, get the equivalent positive value between 1 and N. You can skip this operation if 1 <= M <= N. */ m2 = i4_modp ( m, n ); x = k * m2; while ( n < x ) { x = ( m2 * ( x - n ) - 1 ) / ( m2 - 1 ); } return x; } /******************************************************************************/ void ksub_next ( int n, int k, int a[], int *more, int *m, int *m2 ) /******************************************************************************/ /* Purpose: ksub_next() generates the subsets of size K from a set of size N. Licensing: This code is distributed under the MIT license. Modified: 28 May 2015 Author: John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the size of the set from which subsets are drawn. Input, int K, the desired size of the subsets. K must be between 0 and N. Output, int A[K]. A[I] is the I-th element of the subset. Thus A[I] will be an integer between 1 and N. Note that the routine will return the values in A in sorted order: 1 <= A[0] < A[1] < ... < A[K-1] <= N Input/output, int *MORE. Set MORE = FALSE before first call for a new sequence of subsets. It then is set and remains TRUE as long as the subset computed on this call is not the final one. When the final subset is computed, MORE is set to FALSE as a signal that the computation is done. Input/output, int *M, *M2, two variables used by this procedure for bookkeeping. The user must declare these variables, and the output values from one call must be used as the input values on the next. The user should not change these values. */ { int j; if ( k < 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "KSUB_NEXT(): Fatal error!\n" ); fprintf ( stderr, "K = %d\n", k ); fprintf ( stderr, "but 0 <= K is required!\n" ); exit ( 1 ); } if ( n < k ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "KSUB_NEXT(): Fatal error!\n" ); fprintf ( stderr, "N = %d\n", n ); fprintf ( stderr, "K = %d\n", k ); fprintf ( stderr, "but K <= N is required!\n" ); exit ( 1 ); } if ( !( *more ) ) { *m2 = 0; *m = k; } else { if ( *m2 < n - *m ) { *m = 0; } *m = *m + 1; *m2 = a[k-*m]; } for ( j = 1; j <= *m; j++ ) { a[k+j-*m-1] = *m2 + j; } *more = ( a[0] != ( n - k + 1 ) ); return; } /******************************************************************************/ void ksub_next2 ( int n, int k, int a[], int *in, int *iout ) /******************************************************************************/ /* Purpose: ksub_next2() generates the subsets of size K from a set of size N. Discussion: This routine uses the revolving door method. It has no "memory". It simply calculates the successor of the input set, and will start from the beginning after the last set. Licensing: This code is distributed under the MIT license. Modified: 24 March 2009 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the size of the set from which subsets are drawn. N must be positive. Input, int K, the size of the desired subset. K must be between 0 and N. Input/output, int A[K]. On input, the user must supply a subset of size K in A. That is, A must contain K unique numbers, in order, between 1 and N. On output, A(I) is the I-th element of the output subset. The output array is also in sorted order. Output, int *IN, the element of the output subset which was not in the input set. Each new subset differs from the last one by adding one element and deleting another. Output, int *IOUT, the element of the input subset which is not in the output subset. */ { int j; int m; if ( n <= 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "KSUB_NEXT2(): Fatal error!\n" ); fprintf ( stderr, " N = %d\n", n ); fprintf ( stderr, " but 0 < N is required!\n" ); exit ( 1 ); } if ( k < 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "KSUB_NEXT2(): Fatal error!\n" ); fprintf ( stderr, " K = %d\n", k ); fprintf ( stderr, " but 0 <= K is required!\n" ); exit ( 1 ); } if ( n < k ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "KSUB_NEXT2(): Fatal error!\n" ); fprintf ( stderr, " N = %d\n", n ); fprintf ( stderr, " K = %d\n", k ); fprintf ( stderr, " but K <= N is required!\n" ); exit ( 1 ); } j = 0; for ( ; ; ) { if ( 0 < j || ( k % 2 ) == 0 ) { j = j + 1; if ( k < j ) { a[k-1] = k; *in = k; *iout = n; return; } if ( a[j-1] != j ) { *iout = a[j-1]; *in = *iout - 1; a[j-1] = *in; if ( j != 1 ) { *in = j - 1; a[j-2] = *in; } return; } } j = j + 1; m = n; if ( j < k ) { m = a[j] - 1; } if ( m != a[j-1] ) { break; } } *in = a[j-1] + 1; a[j-1] = *in; *iout = *in - 1; if ( j != 1 ) { a[j-2] = *iout; *iout = j - 1; } return; } /******************************************************************************/ void ksub_next3 ( int n, int k, int a[], int *more, int *in, int *iout ) /******************************************************************************/ /* Purpose: ksub_next3() generates the subsets of size K from a set of size N. Discussion: The routine uses the revolving door method. Licensing: This code is distributed under the MIT license. Modified: 24 March 2009 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the size of the set from which subsets are drawn. N must be positive. Input, int K, the size of the desired subsets. K must be between 0 and N. Output, int A[K]. A(I) is the I-th element of the output subset. The elements of A are sorted. Input/output, int *MORE. On first call, set MORE = FALSE to signal the beginning. MORE will be set to TRUE, and on each call, the routine will return another K-subset. Finally, when the last subset has been returned, MORE will be set FALSE and you may stop calling. Output, int *IN, the element of the output subset which was not in the input set. Each new subset differs from the last one by adding one element and deleting another. IN is not defined the first time that the routine returns, and is set to zero. Output, int *IOUT, the element of the input subset which is not in the output subset. IOUT is not defined the first time the routine returns, and is set to zero. */ { int j; int m; if ( n <= 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "KSUB_NEXT3(): Fatal error!\n" ); fprintf ( stderr, " N = %d\n", n ); fprintf ( stderr, " but 0 < N is required!\n" ); exit ( 1 ); } if ( k < 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "KSUB_NEXT3(): Fatal error!\n" ); fprintf ( stderr, " K = %d\n", k ); fprintf ( stderr, " but 0 <= K is required!\n" ); exit ( 1 ); } if ( n < k ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "KSUB_NEXT3(): Fatal error!\n" ); fprintf ( stderr, " N = %d\n", n ); fprintf ( stderr, " K = %d\n", k ); fprintf ( stderr, " but K <= N is required!\n" ); exit ( 1 ); } if ( !( *more ) ) { *in = 0; *iout = 0; i4vec_indicator1 ( k, a ); *more = ( k != n ); return; } j = 0; for ( ; ; ) { if ( 0 < j || ( k % 2 ) == 0 ) { j = j + 1; if ( a[j-1] != j ) { *iout = a[j-1]; *in = *iout - 1; a[j-1] = *in; if ( j != 1 ) { *in = j - 1; a[j-2] = *in; } if ( k != 1 ) { *more = ( a[k-2] == k-1 ); } *more = ( !( *more ) ) || ( a[k-1] != n ); return; } } j = j + 1; m = n; if ( j < k ) { m = a[j] - 1; } if ( m != a[j-1] ) { break; } } *in = a[j-1] + 1; a[j-1] = *in; *iout = *in - 1; if ( j != 1 ) { a[j-2] = *iout; *iout = j - 1; } if ( k != 1 ) { *more = ( a[k-2] == k-1 ); } *more = ( !( *more ) ) || ( a[k-1] != n ); return; } /******************************************************************************/ void ksub_next4 ( int n, int k, int a[], int *done ) /******************************************************************************/ /* Purpose: ksub_next4() generates the subsets of size K from a set of size N. Discussion: The subsets are generated one at a time. The routine should be used by setting DONE to TRUE, and then calling repeatedly. Each call returns with DONE equal to FALSE, the array A contains information defining a new subset. When DONE returns equal to TRUE, there are no more subsets. There are ( N*(N-1)*...*(N+K-1)) / ( K*(K-1)*...*2*1) such subsets. Licensing: This code is distributed under the MIT license. Modified: 12 May 2018 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the size of the entire set. 0 <= N. Input, int K, the size of the desired subset. 0 <= K <= N. Input/output, int A[K], contains information about the subsets. On the first call with DONE = TRUE, the input contents of A don't matter. Thereafter, the input value of A should be the same as the output value of the previous call. In other words, leave the array alone! On output, as long as DONE is returned FALSE, A contains information defining a subset of K elements of a set of N elements. In other words, A will contain K distinct numbers (in order) between 1 and N. Input/output, int *DONE. On the first call, DONE is an input quantity with a value of TRUE which tells the program to initialize data and return the first subset. On return, DONE is an output quantity that is TRUE as long as the routine is returning another subset, and FALSE when there are no more. */ { int j; int jsave; if ( k < 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "KSUB_NEXT4(): Fatal error!\n" ); fprintf ( stderr, " K = %d\n", k ); fprintf ( stderr, " but 0 <= K is required!\n" ); exit ( 1 ); } if ( n < k ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "KSUB_NEXT4(): Fatal error!\n" ); fprintf ( stderr, " N = %d\n", n ); fprintf ( stderr, " K = %d\n", k ); fprintf ( stderr, " but K <= N is required!\n" ); exit ( 1 ); } /* First call: */ if ( *done ) { for ( j = 0; j < k; j++ ) { a[j] = j + 1; } *done = 0; } /* Empty set returned on previous call. */ else if ( k == 0 || n == 0 ) { *done = 1; } /* Next call. */ else if ( a[0] < n - k + 1 ) { jsave = k - 1; for ( j = 0; j < k - 1; j++ ) { if ( a[j] + 1 < a[j+1] ) { jsave = j; break; } } for ( j = 0; j < jsave; j++ ) { a[j] = j + 1; } a[jsave] = a[jsave] + 1; *done = 0; } else { *done = 1; } return; } /******************************************************************************/ void ksub_random ( int n, int k, int *seed, int a[] ) /******************************************************************************/ /* Purpose: ksub_random() selects a random subset of size K from a set of size N. Licensing: This code is distributed under the MIT license. Modified: 30 April 2003 Author: FORTRAN77 original version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the size of the set from which subsets are drawn. Input, int K, number of elements in desired subsets. K must be between 0 and N. Input/output, int *SEED, a seed for the random number generator. Output, int A[K]. A(I) is the I-th element of the output set. The elements of A are in order. */ { int i; int ids; int ihi; int ip; int ir; int is; int ix; int l; int ll; int m; int m0; if ( k < 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "KSUB_RANDOM(): Fatal error!\n" ); fprintf ( stderr, " K = %d\n", k ); fprintf ( stderr, " but 0 <= K is required!\n" ); exit ( 1 ); } else if ( n < k ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "KSUB_RANDOM(): Fatal error!\n" ); fprintf ( stderr, " N = %d\n", n ); fprintf ( stderr, " K = %d\n", k ); fprintf ( stderr, " K <= N is required!\n" ); exit ( 1 ); } if ( k == 0 ) { return; } for ( i = 1; i <= k; i++ ) { a[i-1] = ( ( i - 1 ) * n ) / k; } for ( i = 1; i <= k; i++ ) { for ( ; ; ) { ix = i4_uniform_ab ( 1, n, seed ); l = 1 + ( ix * k - 1 ) / n; if ( a[l-1] < ix ) { break; } } a[l-1] = a[l-1] + 1; } ip = 0; is = k; for ( i = 1; i <= k; i++ ) { m = a[i-1]; a[i-1] = 0; if ( m != ( ( i - 1 ) * n ) / k ) { ip = ip + 1; a[ip-1] = m; } } ihi = ip; for ( i = 1; i <= ihi; i++ ) { ip = ihi + 1 - i; l = 1 + ( a[ip-1] * k - 1 ) / n; ids = a[ip-1] - ( ( l - 1 ) * n ) / k; a[ip-1] = 0; a[is-1] = l; is = is - ids; } for ( ll = 1; ll <= k; ll++ ) { l = k + 1 - ll; if ( a[l-1] != 0 ) { ir = l; m0 = 1 + ( ( a[l-1] - 1 ) * n ) / k; m = ( a[l-1] * n ) / k - m0 + 1; } ix = i4_uniform_ab ( m0, m0 + m - 1, seed ); i = l + 1; while ( i <= ir ) { if ( ix < a[i-1] ) { break; } ix = ix + 1; a[i-2] = a[i-1]; i = i + 1; } a[i-2] = ix; m = m - 1; } return; } /******************************************************************************/ void ksub_random2 ( int n, int k, int *seed, int a[] ) /******************************************************************************/ /* Purpose: ksub_random2() selects a random subset of size K from a set of size N. Discussion: This algorithm is designated Algorithm RKS2 in the reference. Licensing: This code is distributed under the MIT license. Modified: 25 March 2009 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. A Bebbington, A simple method of drawing a sample without replacement, Journal of Applied Statistics, Volume 24, 1975, page 136. Parameters: Input, int N, the size of the set from which subsets are drawn. Input, int K, number of elements in desired subsets. K must be between 0 and N. Input/output, int *SEED, a seed for the random number generator. Output, int A[K]. A(I) is the I-th element of the output set. The elements of A are in order. */ { int available; int candidate; int have; int need; double r; if ( k < 0 || n < k ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "KSUB_RANDOM2(): Fatal error!\n" ); fprintf ( stderr, " N = %d\n", n ); fprintf ( stderr, " K = %d\n", k ); fprintf ( stderr, " but 0 <= K <= N is required!\n" ); exit ( 1 ); } if ( k == 0 ) { return; } need = k; have = 0; available = n; candidate = 0; for ( ; ; ) { candidate = candidate + 1; r = r8_uniform_01 ( seed ); if ( r * ( double ) available <= ( double ) need ) { need = need - 1; a[have] = candidate; have = have + 1; if ( need <= 0 ) { break; } } available = available - 1; } return; } /******************************************************************************/ void ksub_random3 ( int n, int k, int *seed, int a[] ) /******************************************************************************/ /* Purpose: ksub_random3() selects a random subset of size K from a set of size N. Discussion: This routine uses Floyd's algorithm. Licensing: This code is distributed under the MIT license. Modified: 25 March 2009 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the size of the set from which subsets are drawn. Input, int K, number of elements in desired subsets. K must be between 0 and N. Input/output, int *SEED, a seed for the random number generator. Output, int A[N]. I is an element of the subset if A(I) = 1, and I is not an element if A(I)=0. */ { int i; int j; if ( k < 0 || n < k ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "KSUB_RANDOM3(): Fatal error!\n" ); fprintf ( stderr, " N = %d\n", n ); fprintf ( stderr, " K = %d\n", k ); fprintf ( stderr, " but 0 <= K <= N is required!\n" ); exit ( 1 ); } for ( i = 0; i < n; i++ ) { a[i] = 0; } if ( k == 0 ) { return; } for ( i = n-k+1; i <= n; i++ ) { j = i4_uniform_ab ( 1, i, seed ); if ( a[j-1] == 0 ) { a[j-1] = 1; } else { a[i-1] = 1; } } return; } /******************************************************************************/ void ksub_random4 ( int n, int k, int *seed, int a[] ) /******************************************************************************/ /* Purpose: ksub_random4() selects a random subset of size K from a set of size N. Discussion: This routine is somewhat impractical for the given problem, but it is included for comparison, because it is an interesting approach that is superior for certain applications. The approach is mainly interesting because it is "incremental"; it proceeds by considering every element of the set, and does not need to know how many elements there are. This makes this approach ideal for certain cases, such as the need to pick 5 lines at random from a text file of unknown length, or to choose 6 people who call a certain telephone number on a given day. Using this technique, it is possible to make the selection so that, whenever the input stops, a valid uniformly random subset has been chosen. Obviously, if the number of items is known in advance, and it is easy to extract K items directly, there is no need for this approach, and it is less efficient since, among other costs, it has to generate a random number for each item, and make an acceptance/rejection test. Licensing: This code is distributed under the MIT license. Modified: 25 March 2009 Author: John Burkardt Reference: Tom Christiansen, Nathan Torkington, "8.6: Picking a Random Line from a File", Perl Cookbook, pages 284-285, O'Reilly, 1999. Parameters: Input, int N, the size of the set from which subsets are drawn. Input, int K, number of elements in desired subsets. K must be between 0 and N. Input/output, int *SEED, a seed for the random number generator. Output, int A[K], contains the indices of the selected items. */ { int i; int j; int next; double r; next = 0; /* Here, we use a WHILE to suggest that the algorithm proceeds to the next item, without knowing how many items there are in total. Note that this is really the only place where N occurs, so other termination criteria could be used, and we really don't need to know the value of N! */ while ( next < n ) { next = next + 1; if ( next <= k ) { i = next; a[i-1] = next; } else { r = r8_uniform_01 ( seed ); if ( r * ( double ) next <= ( double ) k ) { i = i4_uniform_ab ( 1, k, seed ); /* If we slide the current items down, and insert at the end, we preserve order. */ for ( j = i; j < k; j++ ) { a[j-1] = a[j]; } a[k-1] = next; /* a[i-1] = next; */ } } } return; } /******************************************************************************/ int *ksub_random5 ( int n, int k, int *seed ) /******************************************************************************/ /* Purpose: ksub_random5() selects a random subset of size K from a set of size N. Discussion: Consider the set A = 1, 2, 3, ... N. Choose a random index I1 between 1 and N, and swap items A(1) and A(I1). Choose a random index I2 between 2 and N, and swap items A(2) and A(I2). repeat K times. A(1:K) is your random K-subset. Licensing: This code is distributed under the MIT license. Modified: 09 June 2011 Author: John Burkardt Parameters: Input, int N, the size of the set from which subsets are drawn. Input, int K, number of elements in desired subsets. 1 <= K <= N. Input/output, int *SEED, a seed for the random number generator. Output, int KSUB_RANDOM5[K], the indices of the randomly chosen elements. These are 1-based indices. */ { int *a; int *b; static int base = 1; int i; int j; int t; /* Let B index the set. */ b = ( int * ) malloc ( n * sizeof ( int ) ); for ( i = 0; i < n; i++ ) { b[i] = i + base; } /* Choose item 1 from N things, choose item 2 from N-1 things, choose item K from N-K+1 things. */ for ( i = 0; i < k; i++) { j = i4_uniform_ab ( i, n - 1, seed ); t = b[i]; b[i] = b[j]; b[j] = t; } /* Copy the first K elements. */ a = ( int * ) malloc ( k * sizeof ( int ) ); for ( i = 0; i < k; i++ ) { a[i] = b[i]; } free ( b ); /* Put the elements in ascending order. */ i4vec_sort_heap_a ( k, a ); return a; } /******************************************************************************/ void ksub_rank ( int k, int a[], int *rank ) /******************************************************************************/ /* Purpose: ksub_rank() computes the rank of a subset of an N set. Discussion: The routine accepts an array representing a subset of size K from a set of size N, and returns the rank (or order) of that subset. This is the same order in which routine KSUB_NEXT2 would produce that subset. Note the value of N is not input, and is not, in fact, needed. Licensing: This code is distributed under the MIT license. Modified: 25 March 2009 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int K, the number of elements in the subset. Input, int A[K], contains K distinct numbers between 1 and N, in order. Output, int *RANK, the rank of this subset. */ { int i; int iprod; int j; *rank = 0; for ( i = 1; i <= k; i++ ) { iprod = 1; for ( j = i+1; j <= a[i-1]-1; j++ ) { iprod = iprod * j; } for ( j = 1; j <= a[i-1]-i-1; j++ ) { iprod = iprod / j; } if ( a[i-1] == 1 ) { iprod = 0; } *rank = *rank + iprod; } *rank = *rank + 1; return; } /******************************************************************************/ void ksub_to_comp ( int ns, int ks, int as[], int *nc, int *kc, int ac[] ) /******************************************************************************/ /* Purpose: ksub_to_comp() converts a K-subset to a composition. Discussion: There is a bijection between K subsets and compositions. Because we allow a composition to have entries that are 0, we need to implicitly add 1 to each entry before establishing the bijection. Let AS be a KS subset of a set of the integers 1 through NS. Then let NC = NS - KS, KC = KS + 1, and define AC(1) = AS(1) - 1; AC(2:KC-1) = AS(2:KC-1) - AS(1:KC-2) - 1; AC(KC) = NS - AS(KS). Then AC is a composition of NC into KC parts. Licensing: This code is distributed under the MIT license. Modified: 04 December 2013 Parameters: Input, int NS, the size of the set. Input, int KS, the size of the subset. Input, int AS[KS], the entries of the K-subset, in increasing order. Output, int *NC, the composition sum. Output, int *KC, the number of parts of the composition. Output, int AC[*KC], the parts of the composition. */ { int i; *nc = ns - ks; *kc = ks + 1; ac[0] = as[0] - 1; for ( i = 1; i < *kc - 1; i++ ) { ac[i] = as[i] - as[i-1] - 1; } ac[*kc-1] = ns - as[ks-1]; return; } /******************************************************************************/ void ksub_to_compnz ( int ns, int ks, int as[], int *nc, int *kc, int ac[] ) /******************************************************************************/ /* Purpose: ksub_to_compnz() converts a K-subset to a nonzero composition. Discussion: There is a bijection between K subsets and compositions. Let AS be a KS subset of a set of the integers 1 through NS. Then let NC = NS + 1 KC = KS + 1, and define AC(1) = AS(1); AC(2:KC-1) = AS(2:KC-1) - AS(1:KC-2); AC(KC) = NC - AS(KS). Then AC is a composition of NC into KC parts. Licensing: This code is distributed under the MIT license. Modified: 24 May 2015 Author: John Burkardt Parameters: Input, int NS, the size of the set. Input, int KS, the size of the subset. Input, int AS[KS], the entries of the K-subset, in increasing order. Output, int *NC, the composition sum. Output, int *KC, the number of parts of the composition. Output, int AC[*KC], the parts of the composition. */ { int i; *nc = ns + 1; *kc = ks + 1; ac[0] = as[0]; for ( i = 1; i < *kc - 1; i++ ) { ac[i] = as[i] - as[i-1]; } ac[*kc-1] = *nc - as[ks-1]; return; } /******************************************************************************/ void ksub_unrank ( int k, int rank, int a[] ) /******************************************************************************/ /* Purpose: ksub_unrank() returns the subset of a given rank. Discussion: The routine is given a rank and returns the corresponding subset of K elements of a set of N elements. It uses the same ranking that KSUB_NEXT2 uses to generate all the subsets one at a time. Note that the value of N itself is not input, nor is it needed. Licensing: This code is distributed under the MIT license. Modified: 25 March 2009 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int K, the number of elements in the subset. Input, int RANK, the rank of the desired subset. There are ( N*(N-1)*...*(N+K-1)) / ( K*(K-1)*...*2*1) such subsets, so RANK must be between 1 and that value. Output, int A[K], K distinct integers in order between 1 and N, which define the subset. */ { int i; int ip; int iprod; int jrank; jrank = rank - 1; for ( i = k; 1 <= i; i-- ) { ip = i - 1; iprod = 1; for ( ; ; ) { ip = ip + 1; if ( ip != i ) { iprod = ( ip * iprod ) / ( ip - i ); } if ( jrank < iprod ) { break; } } if ( ip != i ) { iprod = ( ( ip - i ) * iprod ) / ip; } jrank = jrank - iprod; a[i-1] = ip; } return; } /******************************************************************************/ void l4vec_next ( int n, int l4vec[] ) /******************************************************************************/ /* Purpose: l4vec_next() generates the next logical vector. Discussion: In the following discussion, we will let '0' stand for FALSE and '1' for TRUE. The vectors have the order (0,0,...,0), (0,0,...,1), ... (1,1,...,1) and the "next" vector after (1,1,...,1) is (0,0,...,0). That is, we allow wrap around. Note that, in C, there is no distinct LOGICAL type, so this routine actually manipulates an integer vector. Example: N = 3 Input Output ----- ------ 0 0 0 => 0 0 1 0 0 1 => 0 1 0 0 1 0 => 0 1 1 0 1 1 => 1 0 0 1 0 0 => 1 0 1 1 0 1 => 1 1 0 1 1 0 => 1 1 1 1 1 1 => 0 0 0 Licensing: This code is distributed under the MIT license. Modified: 31 May 2008 Author: John Burkardt Parameters: Input, int N, the dimension of the vectors. Input/output, int L4VEC[N], on output, the successor to the input vector. */ { int i; for ( i = n - 1; 0 <= i; i-- ) { if ( l4vec[i] == 0 ) { l4vec[i] = 1; return; } l4vec[i] = 0; } return; } /******************************************************************************/ void matrix_product_opt ( int n, int rank[], int *cost, int order[] ) /******************************************************************************/ /* Purpose: matrix_product_opt() determines the optimal cost of a matrix product. Discussion: The cost of multiplying an LxM matrix by an M by N matrix is assessed as L*M*N. Any particular order of multiplying a set of N matrices is equivalent to parenthesizing an expression of N objects. The actual number of ways of parenthesizing an expression of N objects is C(N), the N-th Catalan number. Licensing: This code is distributed under the MIT license. Modified: 27 March 2009 Author: John Burkardt Reference: Robert Sedgewick, Algorithms, Addison-Wesley, 1984, pages 486-489. Input: int N, the number of matrices to be multiplied. int RANK[N+1], the rank information for the matrices. Matrix I has RANK[I] rows and RANK[I+1] columns. Output: int *COST, the cost of the multiplication if the optimal order is used. int ORDER[N-1], indicates the order in which the N-1 multiplications are to be carried out. ORDER[0] is the first multiplication to do, and so on. */ { # define STACK_MAX 100 int *best; int *cost2; int cost3; int i; int i1; int i2; int i3; int j; int k; int stack[STACK_MAX]; int stack_num; int step; /* Initialize the cost matrix. */ best = ( int * ) malloc ( n * n * sizeof ( int ) ); cost2 = ( int * ) malloc ( n * n * sizeof ( int ) ); for ( i = 0; i < n; i++ ) { for ( j = 0; j <= i; j++ ) { cost2[i+j*n] = 0; } for ( j = i+1; j < n; j++ ) { cost2[i+j*n] = i4_huge ( ); } } /* Initialize the BEST matrix. */ for ( i = 0; i < n; i++ ) { for ( j = 0; j < n; j++ ) { best[i+j*n] = 0; } } /* Compute the cost and best matrices. */ for ( j = 1; j <= n-1; j++ ) { for ( i = 1; i <= n-j; i++ ) { for ( k = i+1; k <= i+j; k++ ) { cost3 = cost2[i-1+(k-2)*n] + cost2[k-1+(i+j-1)*n] + rank[i-1] * rank[k-1] * rank[i+j]; if ( cost3 < cost2[i-1+(i+j-1)*n] ) { cost2[i-1+(i+j-1)*n] = cost3; best[i-1+(i+j-1)*n] = k; } } } } /* Pick off the optimal cost. */ *cost = cost2[0+(n-1)*n]; /* Backtrack to determine the optimal order. */ stack_num = 0; i1 = 1; i2 = n; if ( i1 + 1 < i2 ) { stack[stack_num] = i1; stack_num = stack_num + 1; stack[stack_num] = i2; stack_num = stack_num + 1; } step = n - 1; /* Take an item off the stack. */ while ( 0 < stack_num ) { stack_num = stack_num - 1; i3 = stack[stack_num]; stack_num = stack_num - 1; i1 = stack[stack_num]; i2 = best[i1-1+(i3-1)*n]; step = step - 1; order[step] = i2 - 1; /* The left chunk is matrices (I1...I2-1) */ if ( i1 == i2-1 ) { } else if ( i1+1 == i2-1 ) { step = step - 1; order[step] = i2 - 2; } else { stack[stack_num] = i1; stack_num = stack_num + 1; stack[stack_num] = i2 - 1; stack_num = stack_num + 1; } /* The right chunk is matrices (I2...I3) */ if ( i2 == i3 ) { } else if ( i2+1 == i3 ) { step = step - 1; order[step] = i2; } else { stack[stack_num] = i2; stack_num = stack_num + 1; stack[stack_num] = i3; stack_num = stack_num + 1; } } free ( best ); free ( cost2 ); return; # undef STACK_MAX } /******************************************************************************/ void moebius_matrix ( int n, int a[], int mu[] ) /******************************************************************************/ /* Purpose: moebius_matrix() finds the Moebius matrix from a covering relation. Discussion: This routine can be called with A and MU being the same matrix. The routine will correctly compute the Moebius matrix, which will, in this case, overwrite the input matrix. Licensing: This code is distributed under the MIT license. Modified: 08 June 2015 Author: John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Input: int N, number of elements in the partially ordered set. int A[N*N]. A(I,J) = 1 if I is covered by J, 0 otherwise. Output: int MU[N*N], the Moebius matrix as computed by the routine. */ { int i; int j; int *p1; int *p2; p1 = ( int * ) malloc ( n * sizeof ( n ) ); /* Compute a reordering of the elements of the partially ordered matrix. */ triang ( n, a, p1 ); /* Copy the matrix. */ for ( i = 0; i < n; i++ ) { for ( j = 0; j < n; j++ ) { mu[i+j*n] = a[i+j*n]; } } /* Apply the reordering to MU. */ i4mat_2perm0 ( n, n, mu, p1, p1 ); /* Negate the (strict) upper triangular elements of MU. */ for ( i = 0; i < n-1; i++ ) { for ( j = i+1; j < n; j++ ) { mu[i+j*n] = - mu[i+j*n]; } } /* Compute the inverse of MU. */ i4mat_u1_inverse ( n, mu, mu ); /* All nonzero elements are reset to 1. */ for ( i = 0; i < n; i++ ) { for ( j = i; j < n; j++ ) { if ( mu[i+j*n] != 0 ) { mu[i+j*n] = 1; } } } /* Invert the matrix again. */ i4mat_u1_inverse ( n, mu, mu ); /* Compute the inverse permutation. */ p2 = perm0_inverse ( n, p1 ); /* Unpermute the rows and columns of MU. */ i4mat_2perm0 ( n, n, mu, p2, p2 ); free ( p1 ); free ( p2 ); return; } /******************************************************************************/ void moebius_values ( int *n_data, int *n, int *c ) /******************************************************************************/ /* Purpose: moebius_values() returns some values of the Moebius function. Discussion: MU(N) is defined as follows: MU(N) = 1 if N = 1; 0 if N is divisible by the square of a prime; (-1)^K, if N is the product of K distinct primes. In Mathematica, the function can be evaluated by: MoebiusMu[n] First values: N MU(N) 1 1 2 -1 3 -1 4 0 5 -1 6 1 7 -1 8 0 9 0 10 1 11 -1 12 0 13 -1 14 1 15 1 16 0 17 -1 18 0 19 -1 20 0 Note: As special cases, MU(N) is -1 if N is a prime, and MU(N) is 0 if N is a square, cube, etc. Formula: The Moebius function is related to Euler's totient function: PHI(N) = Sum ( D divides N ) MU(D) * ( N / D ). Licensing: This code is distributed under the MIT license. Modified: 16 February 2003 Author: John Burkardt Reference: Milton Abramowitz, Irene Stegun, Handbook of Mathematical Functions, National Bureau of Standards, 1964, ISBN: 0-486-61272-4, LC: QA47.A34. Stephen Wolfram, The Mathematica Book, Fourth Edition, Cambridge University Press, 1999, ISBN: 0-521-64314-7, LC: QA76.95.W65. Parameters: Input, int *N_DATA. The user sets N_DATA to 0 before the first call. Output, int *N_DATA. On each call, the routine increments N_DATA by 1, and returns the corresponding data; when there is no more data, the output value of N_DATA will be 0 again. Output, int *N, the argument of the Moebius function. Output, int *C, the value of the Moebius function. */ { # define N_MAX 20 static int c_vec[N_MAX] = { 1, -1, -1, 0, -1, 1, -1, 0, 0, 1, -1, 0, -1, 1, 1, 0, -1, 0, -1, 0 }; static int n_vec[N_MAX] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 }; if ( *n_data < 0 ) { *n_data = 0; } *n_data = *n_data + 1; if ( N_MAX < *n_data ) { *n_data = 0; *n = 0; *c = 0; } else { *n = n_vec[*n_data-1]; *c = c_vec[*n_data-1]; } return; # undef N_MAX } /******************************************************************************/ int monomial_count ( int degree_max, int dim ) /******************************************************************************/ /* Purpose: monomial_count() counts the number of monomials up to a given degree. Discussion: In 3D, there are 10 monomials of degree 3 or less: Degree Count List ------ ----- ---- 0 1 1 1 3 x y z 2 6 xx xy xz yy yz zz 3 10 xxx xxy xxz xyy xyz xzz yyy yyz yzz zzz Total 20 The formula is COUNTS(DEGREE,DIM) = (DIM-1+DEGREE)! / (DIM-1)! / DEGREE! TOTAL = (DIM +DEGREE)! / (DIM)! / DEGREE! Licensing: This code is distributed under the MIT license. Modified: 23 March 2009 Author: John Burkardt Parameters: Input, int DEGREE_MAX, the maximum degree. Input, int DIM, the spatial dimension. Output, int MONOMIAL_COUNT, the total number of monomials of degrees 0 through DEGREE_MAX. */ { int bot; int top; int total; total = 1; if ( degree_max < dim ) { top = dim + 1; for ( bot = 1; bot <= degree_max; bot++ ) { total = ( total * top ) / bot; top = top + 1; } } else { top = degree_max + 1; for ( bot = 1; bot <= dim; bot++ ) { total = ( total * top ) / bot; top = top + 1; } } return total; } /******************************************************************************/ int *monomial_counts ( int degree_max, int dim ) /******************************************************************************/ /* Purpose: monomial_counts() counts the number of monomials up to a given degree. Discussion: In 3D, there are 10 monomials of degree 3 or less: Degree Count List ------ ----- ---- 0 1 1 1 3 x y z 2 6 xx xy xz yy yz zz 3 10 xxx xxy xxz xyy xyz xzz yyy yyz yzz zzz Total 20 The formula is COUNTS(DEGREE,DIM) = (DIM-1+DEGREE)! / (DIM-1)! / DEGREE! TOTAL = (DIM +DEGREE)! / (DIM)! / DEGREE! Licensing: This code is distributed under the MIT license. Modified: 23 March 2009 Author: John Burkardt Parameters: Input, int DEGREE_MAX, the maximum degree. Input, int DIM, the spatial dimension. Output, int MONOMIAL_COUNTS[DEGREE_MAX+1], the number of monomials of each degree. */ { int *counts; int degree; counts = ( int * ) malloc ( ( degree_max + 1 ) * sizeof ( int ) ); degree = 0; counts[degree] = 1; for ( degree = 1; degree <= degree_max; degree++ ) { counts[degree] = ( counts[degree-1] * ( dim - 1 + degree ) ) / degree; } return counts; } /******************************************************************************/ int morse_thue ( unsigned int ui ) /******************************************************************************/ /* Purpose: morse_thue() generates a Morse_Thue number. Discussion: The Morse_Thue sequence can be defined in a number of ways. A) Start with the string containing the single letter '0'; then repeatedly apply the replacement rules '0' -> '01' and '1' -> '10' to the letters of the string. The Morse_Thue sequence is the resulting letter sequence. B) Starting with the string containing the single letter '0', repeatedly append the binary complement of the string to itself. Thus, '0' becomes '0' + '1' or '01', then '01' becomes '01' + '10', which becomes '0110' + '1001', and so on. C) Starting with I = 0, the I-th Morse-Thue number is determined by taking the binary representation of I, adding the digits, and computing the remainder modulo 2. Example: I binary S -- ------ -- 0 0 0 1 1 1 2 10 1 3 11 0 4 100 1 5 101 0 6 110 0 7 111 1 8 1000 1 Licensing: This code is distributed under the MIT license. Modified: 30 December 2014 Author: John Burkardt Parameters: Input, unsigned int UI, the index of the Morse-Thue number. Output, int MORSE_THUE, the Morse-Thue number of index I. */ { # define NBITS 32 int b[NBITS]; int i; int s; /* Expand UI into binary form. */ ui4_to_ubvec ( ui, NBITS, b ); /* Sum the 1's in the binary representation. */ s = 0; for ( i = 0; i < NBITS; i++ ) { s = s + b[i]; } /* Take the value modulo 2. */ s = s % 2; return s; # undef NBITS } /******************************************************************************/ int multinomial_coef1 ( int nfactor, int factor[] ) /******************************************************************************/ /* Purpose: multinomial_coef1() computes a multinomial coefficient. Discussion: The multinomial coefficient is a generalization of the binomial coefficient. It may be interpreted as the number of combinations of N objects, where FACTOR(1) objects are indistinguishable of type 1, ... and FACTOR(NFACTOR) are indistinguishable of type NFACTOR, and N is the sum of FACTOR(1) through FACTOR(NFACTOR). NCOMB = N! / ( FACTOR(1)! FACTOR(2)! ... FACTOR(NFACTOR)! ) The log of the gamma function is used, to avoid overflow. Licensing: This code is distributed under the MIT license. Modified: 22 March 2009 Author: John Burkardt Parameters: Input, int NFACTOR, the number of factors. Input, int FACTOR[NFACTOR], contains the factors. 0 <= FACTOR(I) Output, int MULTINOMIAL_COEF1, the value of the multinomial coefficient. */ { double arg; double fack; double facn; int i; int n; int value; /* Each factor must be nonnegative. */ for ( i = 0; i < nfactor; i++ ) { if ( factor[i] < 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "MULTINOMIAL_COEF1(): Fatal error\n" ); fprintf ( stderr, " Factor %d = %d\n", i, factor[i] ); fprintf ( stderr, " But this value must be nonnegative.\n" ); exit ( 1 ); } } /* The factors sum to N. */ n = i4vec_sum ( nfactor, factor ); arg = ( double ) ( n + 1 ); facn = lgamma ( arg ); for ( i = 0; i < nfactor; i++ ) { arg = ( double ) ( factor[i] + 1 ); fack = lgamma ( arg ); facn = facn - fack; } value = r8_nint ( exp ( facn ) ); return value; } /******************************************************************************/ int multinomial_coef2 ( int nfactor, int factor[] ) /******************************************************************************/ /* Purpose: multinomial_coef2() computes a multinomial coefficient. Discussion: The multinomial coefficient is a generalization of the binomial coefficient. It may be interpreted as the number of combinations of N objects, where FACTOR(1) objects are indistinguishable of type 1, ... and FACTOR(NFACTOR) are indistinguishable of type NFACTOR, and N is the sum of FACTOR(1) through FACTOR(NFACTOR). NCOMB = N! / ( FACTOR(1)! FACTOR(2)! ... FACTOR(NFACTOR)! ) A direct method is used, which should be exact. However, there is a possibility of intermediate overflow of the result. Licensing: This code is distributed under the MIT license. Modified: 22 March 2009 Author: John Burkardt Parameters: Input, int NFACTOR, the number of factors. Input, int FACTOR[NFACTOR], contains the factors. 0 <= FACTOR(I) Output, int MULTINOMIAL_COEF2, the value of the multinomial coefficient. */ { int i; int j; int k; int value; /* Each factor must be nonnegative. */ for ( i = 0; i < nfactor; i++ ) { if ( factor[i] < 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "MULTINOMIAL_COEF2(): Fatal error!\n" ); fprintf ( stderr, " Factor %d = %d\n", i, factor[i] ); fprintf ( stderr, " But this value must be nonnegative.\n" ); exit ( 1 ); } } value = 1; k = 0; for ( i = 0; i < nfactor; i++ ) { for ( j = 1; j <= factor[i]; j++ ) { k = k + 1; value = ( value * k ) / j; } } return value; } /******************************************************************************/ int multiperm_enum ( int n, int k, int counts[] ) /******************************************************************************/ /* Purpose: multiperm_enum() enumerates multipermutations. Discussion: A multipermutation is a permutation of objects, some of which are identical. While there are 6 permutations of the distinct objects A,B,C, there are only 3 multipermutations of the objects A,B,B. In general, there are N! permutations of N distinct objects, but there are N! / ( ( M1! ) ( M2! ) ... ( MK! ) ) multipermutations of N objects, in the case where the N objects consist of K types, with M1 examples of type 1, M2 examples of type 2 and so on, and for which objects of the same type are indistinguishable. Example: Input: N = 5, K = 3, COUNTS = (/ 1, 2, 2 /) Output: Number = 30 Licensing: This code is distributed under the MIT license. Modified: 27 March 2009 Author: John Burkardt Parameters: Input, int N, the number of items in the multipermutation. Input, int K, the number of types of items. 1 <= K. Ordinarily, K <= N, but we allow any positive K, because we also allow entries in COUNTS to be 0. Input, int COUNTS[K], the number of items of each type. 0 <= COUNTS(1:K) <= N and sum ( COUNTS(1:K) ) = N. Output, int MULTIPERM_ENUM, the number of multipermutations. */ { int i; int j; int number; int sum; int top; if ( n < 0 ) { number = -1; return number; } if ( n == 0 ) { number = 1; return number; } if ( k < 1 ) { number = -1; return number; } for ( i = 0; i < k; i++ ) { if ( counts[i] < 0 ) { number = -1; return number; } } sum = 0; for ( i = 0; i < k; i++ ) { sum = sum + counts[i]; } if ( sum != n ) { number = -1; return number; } /* Ready for computation. By design, the integer division should never have a remainder. */ top = 0; number = 1; for ( i = 0; i < k; i++ ) { for ( j = 1; j <= counts[i]; j++ ) { top = top + 1; number = ( number * top ) / j; } } return number; } /******************************************************************************/ void multiperm_next ( int n, int a[], int *more ) /******************************************************************************/ /* Purpose: multiperm_next() returns the next multipermutation. Discussion: To begin the computation, the user must set up the first multipermutation. To compute ALL possible multipermutations, this first permutation should list the values in ascending order. The routine will compute, one by one, the next multipermutation, in lexicographical order. On the call after computing the last multipermutation, the routine will return MORE = FALSE (and will reset the multipermutation to the FIRST one again.) Licensing: This code is distributed under the MIT license. Modified: 27 March 2009 Author: John Burkardt Parameters: Input, int N, the number of items in the multipermutation. Input, int A[N]: the current multipermutation. Output, int A[N]: the next multipermutation. Output, int *MORE, is TRUE if the next multipermutation was computed, or FALSE if no further multipermutations could be computed. */ { int i; int m; int temp; /* Step 1: Find M, the last location in A for which A(M) < A(M+1). */ m = 0; for ( i = 1; i <= n-1; i++ ) { if ( a[i-1] < a[i] ) { m = i; } } /* Step 2: If no M was found, we've run out of multipermutations. */ if ( m == 0 ) { *more = 0; i4vec_sort_heap_a ( n, a ); return; } else { *more = 1; } /* Step 3: Ascending sort A(M+1:N). */ if ( m + 1 < n ) { i4vec_sort_heap_a ( n-m, a+m ); } /* Step 4: Locate the first larger value after A(M). */ i = 1; for ( ; ; ) { if ( a[m-1] < a[m+i-1] ) { break; } i = i + 1; } /* Step 5: Interchange A(M) and the next larger value. /*/ temp = a[m-1]; a[m-1] = a[m+i-1]; a[m+i-1] = temp; return; } /******************************************************************************/ void network_flow_max ( int nnode, int nedge, int iendpt[], int icpflo[], int source, int sink, int cut[], int node_flow[] ) /******************************************************************************/ /* Purpose: network_flow_max() finds the maximal flow and a minimal cut in a network. Discussion: Apparently, I didn't get around to converting this routine! Licensing: This code is distributed under the MIT license. Modified: 01 April 2009 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int NNODE, the number of nodes. Input, int NEDGE, the number of edges. Input, int IENDPT[2*NEDGE], the edges of the network, defined as pairs of nodes. Each edge should be listed TWICE, the second time in reverse order. Input, int ICPFLO[2*NEDGE]: ICPFLO[1,I] contains the capacities. Input, int SOURCE, the designated source node. Input, int SINK, the designated sink node. Output, int IENDPT[2*NEDGE]: the edges have been reordered, and so the columns of IENDPT have been rearranged. Output, int ICPFLO[2*NEDGE]: ICPFLO(2,I) is the flow on edge I and ICPFLO(1,I) has been rearranged to match the reordering of IENDPT. Output, int CUT[NNODE]. CUT(I) = 1 if node I is in the minimal cut set, otherwise 0. Output, int NODE_FLOW[NNODE]. NODE_FLOW(I) is the value of the flow through node I. */ { return; } /******************************************************************************/ unsigned int nim_sum ( unsigned int ui, unsigned int uj ) /******************************************************************************/ /* Purpose: nim_sum() computes the Nim sum of two integers. Discussion: If K is the Nim sum of I and J, then each bit of K is the exclusive OR of the corresponding bits of I and J. Example: I J K I_2 J_2 K_2 ---- ---- ---- ---------- ---------- ---------- 0 0 0 0 0 0 1 0 1 1 0 1 1 1 0 1 1 0 2 7 5 10 111 101 11 28 23 1011 11100 10111 Licensing: This code is distributed under the MIT license. Modified: 23 March 2009 Author: John Burkardt Parameters: Input, unsigned int UI, UJ, the integers to be Nim-summed. Output, unsigned int NIM_SUM, the Nim sum of I and J. */ { # define NBITS 32 int bvec1[NBITS]; int bvec2[NBITS]; int bvec3[NBITS]; unsigned int value; ui4_to_ubvec ( ui, NBITS, bvec1 ); ui4_to_ubvec ( uj, NBITS, bvec2 ); ubvec_xor ( NBITS, bvec1, bvec2, bvec3 ); value = ubvec_to_ui4 ( NBITS, bvec3 ); return value; # undef NBITS } /******************************************************************************/ void padovan ( int n, int p[] ) /******************************************************************************/ /* Purpose: padovan() returns the first N values of the Padovan sequence. Discussion: The Padovan sequence has the initial values: P(0) = 1 P(1) = 1 P(2) = 1 and subsequent entries are generated by the recurrence P(I+1) = P(I-1) + P(I-2) Example: 0 1 1 1 2 1 3 2 4 2 5 3 6 4 7 5 8 7 9 9 10 12 Licensing: This code is distributed under the MIT license. Modified: 23 March 2009 Author: John Burkardt Reference: Ian Stewart, "A Neglected Number", Scientific American, Volume 274, pages 102-102, June 1996. Ian Stewart, Math Hysteria, Oxford, 2004. Parameters: Input, int N, the number of terms. Output, int P[N], terms 0 though N-1 of the sequence. */ { int i; if ( n < 1 ) { return; } p[0] = 1; if ( n < 2 ) { return; } p[1] = 1; if ( n < 3 ) { return; } p[2] = 1; for ( i = 4; i <= n; i++ ) { p[i-1] = p[i-3] + p[i-4]; } return; } /******************************************************************************/ void pell_basic ( int d, int *x0, int *y0 ) /******************************************************************************/ /* Purpose: pell_basic() returns the fundamental solution for Pell's basic equation. Discussion: Pell's equation has the form: X^2 - D * Y^2 = 1 where D is a given non-square integer, and X and Y may be assumed to be positive integers. Example: D X0 Y0 2 3 2 3 2 1 5 9 4 6 5 2 7 8 3 8 3 1 10 19 6 11 10 3 12 7 2 13 649 180 14 15 4 15 4 1 17 33 8 18 17 4 19 170 39 20 9 2 Licensing: This code is distributed under the MIT license. Modified: 27 March 2009 Author: John Burkardt Reference: Mark Herkommer, Number Theory, A Programmer's Guide, McGraw Hill, 1999, pages 294-307 Parameters: Input, int D, the coefficient in Pell's equation. D should be positive, and not a perfect square. Output, int *X0, *Y0, the fundamental or 0'th solution. If X0 = Y0 = 0, then the calculation was canceled because of an error. Both X0 and Y0 will be nonnegative. */ { # define TERM_MAX 100 int b[TERM_MAX+1]; int i; int p; int pm1; int pm2; int q; int qm1; int qm2; int r; int term_num; /* Check D. */ if ( d <= 0 ) { printf ( "\n" ); printf ( "PELL_BASIC - Warning!\n" ); printf ( " Pell coefficient D <= 0.\n" ); *x0 = 0; *y0 = 0; return; } i4_sqrt ( d, &q, &r ); if ( r == 0 ) { printf ( "\n" ); printf ( "PELL_BASIC - Warning!\n" ); printf ( " Pell coefficient is a perfect square.\n" ); *x0 = 0; *y0 = 0; return; } /* Find the continued fraction representation of sqrt ( D ). */ i4_sqrt_cf ( d, TERM_MAX, &term_num, b ); /* If necessary, go for two periods. */ if ( ( term_num % 2 ) == 1 ) { for ( i = term_num+1; i <= 2 * term_num; i++ ) { b[i] = b[i-term_num]; } term_num = 2 * term_num; } /* Evaluate the continued fraction using the forward recursion algorithm. */ pm2 = 0; pm1 = 1; qm2 = 1; qm1 = 0; for ( i = 0; i < term_num; i++ ) { p = b[i] * pm1 + pm2; q = b[i] * qm1 + qm2; pm2 = pm1; pm1 = p; qm2 = qm1; qm1 = q; } /* Get the fundamental solution. */ *x0 = p; *y0 = q; return; # undef TERM_MAX } /******************************************************************************/ void pell_next ( int d, int x0, int y0, int xn, int yn, int *xnp1, int *ynp1 ) /******************************************************************************/ /* Purpose: pell_next() returns the next solution of Pell's equation. Discussion: Pell's equation has the form: X^2 - D * Y^2 = 1 where D is a given non-square integer, and X and Y may be assumed to be positive integers. To compute X0, Y0, call PELL_BASIC. To compute X1, Y1, call this routine, with XN and YN set to X0 and Y0. To compute further solutions, call again with X0, Y0 and the previous solution. Example: ------INPUT-------- --OUTPUT-- D X0 Y0 XN YN XNP1 YNP1 2 3 2 3 2 17 12 2 3 2 17 12 99 70 2 3 2 99 70 577 408 2 3 2 577 408 3363 2378 Licensing: This code is distributed under the MIT license. Modified: 27 March 2009 Author: John Burkardt Reference: Mark Herkommer, Number Theory, A Programmer's Guide, McGraw Hill, 1999, pages 294-307 Parameters: Input, int D, the coefficient in Pell's equation. Input, int X0, Y0, the fundamental or 0'th solution. Input, int XN, YN, the N-th solution. Output, int *XNP1, *YNP1, the N+1-th solution. */ { *xnp1 = x0 * xn + d * y0 * yn; *ynp1 = x0 * yn + y0 * xn; return; } /******************************************************************************/ int pell_number ( int n ) /******************************************************************************/ /* Purpose: pell_number() returns the N-th Pell number. Licensing: This code is distributed under the MIT license. Modified: 14 December 2023 Author: John Burkardt Input: int n: the index of the Pell number. Output: int pell_number: the value of the N-th Pell number. */ { int m; int pn; int pnm1; int pnm2; if ( n < 0 ) { printf ( "\n" ); printf ( "pell_number(): Fatal error!\n" ); printf ( " n < 0.\n" ); exit ( 1 ); } for ( m = 0; m <= n; m++ ) { if ( m == 0 ) { pn = 0; } else if ( m == 1 ) { pnm1 = pn; pn = 1; } else { pnm2 = pnm1; pnm1 = pn; pn = 2 * pnm1 + pnm2; } } return pn; } /******************************************************************************/ int pent_enum ( int n ) /******************************************************************************/ /* Purpose: pent_enum() computes the N-th pentagonal number. Discussion: The pentagonal number P(N) counts the number of dots in a figure of N nested pentagons. The pentagonal numbers are defined for both positive and negative N. First values: N P -5 40 -4 26 -3 15 -2 7 -1 2 0 0 1 1 2 5 3 12 4 22 5 35 6 51 7 70 8 92 9 117 10 145 P(N) = ( N * ( 3 * N - 1 ) ) / 2 Licensing: This code is distributed under the MIT license. Modified: 27 March 2009 Author: John Burkardt Parameters: Input, int N, the index of the pentagonal number desired. Output, int PENT_ENUM, the value of the N-th pentagonal number. */ { int p; p = ( n * ( 3 * n - 1 ) ) / 2; return p; } /******************************************************************************/ void perm_ascend ( int n, int a[], int *length, int sub[] ) /******************************************************************************/ /* Purpose: perm_ascend() computes the longest ascending subsequence of permutation. Discussion: Although this routine is intended to be applied to a permutation, it will work just as well for an arbitrary vector. Licensing: This code is distributed under the MIT license. Modified: 27 March 2009 Author: John Burkardt Parameters: Input, int N, the order of the permutation. Input, int A[N], the permutation to be examined. Output, int *LENGTH, the length of the longest increasing subsequence. Output, int SUB[N], contains in entries 1 through LENGTH a longest increasing subsequence of A. */ { int i; int j; int k; int *top; int *top_prev; if ( n <= 0 ) { *length = 0; return; } top = ( int * ) malloc ( n * sizeof ( int ) ); for ( i = 0; i < n; i++ ) { top[i] = 0; } top_prev = ( int * ) malloc ( n * sizeof ( int ) ); for ( i = 0; i < n; i++ ) { top_prev[i] = 0; } for ( i = 0; i < n; i++ ) { sub[i] = 0; } *length = 0; for ( i = 1; i <= n; i++ ) { k = 0; for ( j = 1; j <= *length; j++ ) { if ( a[i-1] <= a[top[j-1]-1] ) { k = j; break; } } if ( k == 0 ) { *length = *length + 1; k = *length; } top[k-1] = i; if ( 1 < k ) { top_prev[i-1] = top[k-2]; } else { top_prev[i-1] = 0; } } j = top[*length-1]; sub[*length-1] = a[j-1]; for ( i = *length-1; 1 <= i; i-- ) { j = top_prev[j-1]; sub[i-1] = a[j-1]; } free ( top ); free ( top_prev ); return; } /******************************************************************************/ int perm_fixed_enum ( int n, int m ) /******************************************************************************/ /* Purpose: perm_fixed_enum() enumerates the permutations of N objects with M fixed. Discussion: A permutation of N objects with M fixed is a permutation in which exactly M of the objects retain their original positions. If M = 0, the permutation is a "derangement". If M = N, the permutation is the identity. The formula is: F(N,M) = ( N! / M! ) * ( 1 - 1/1! + 1/2! - 1/3! ... 1/(N-M)! ) = COMB(N,M) * D(N-M) where D(N-M) is the number of derangements of N-M objects. Licensing: This code is distributed under the MIT license. Modified: 28 March 2009 Author: John Burkardt Parameters: Input, int N, the number of objects to be permuted. N should be at least 1. Input, int M, the number of objects that retain their position. M should be between 0 and N. Output, int PERM_FIXED_ENUM, the number of derangements of N objects in which M objects retain their positions. */ { int fnm; if ( n <= 0 ) { fnm = 1; } else if ( m < 0 ) { fnm = 0; } else if ( n < m ) { fnm = 0; } else if ( m == n ) { fnm = 1; } else if ( n == 1 ) { if ( m == 1 ) { fnm = 1; } else { fnm = 0; } } else { fnm = i4_choose ( n, m ) * derange_enum ( n - m ); } return fnm; } /******************************************************************************/ int perm0_break_count ( int n, int p[] ) /******************************************************************************/ /* Purpose: perm0_break_count() counts breaks in a permutation of (0,...,N-1). Discussion: We begin with a permutation of order N. We prepend an element labeled "-1" and append an element labeled "N". There are now N+1 pairs of neighbors. A "break" is a pair of neighbors whose value differs by more than 1. The identity permutation has a break count of 0. The maximum break count is N+1. Licensing: This code is distributed under the MIT license. Modified: 15 June 2015 Author: John Burkardt Parameters: Input, int N, the order of the permutation. Input, int P[N], a permutation, in standard index form. Output, int PERM0_BREAK_COUNT, the number of breaks in the permutation. */ { int i; int ierror; int value; /* Make sure the permutation is a legal one. */ ierror = perm0_check ( n, p ); if ( ierror != 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "PERM0_BREAK_COUNT(): Fatal error!\n" ); fprintf ( stderr, " PERM0_CHECK rejects this permutation.\n" ); exit ( 1 ); } value = 0; if ( p[0] != 0 ) { value = value + 1; } for ( i = 1; i <= n-1; i++ ) { if ( abs ( p[i] - p[i-1] ) != 1 ) { value = value + 1; } } if ( p[n-1] != n - 1 ) { value = value + 1; } return value; } /******************************************************************************/ int perm0_check ( int n, int p[] ) /******************************************************************************/ /* Purpose: perm0_check() checks a permutation of (0,...,N-1) Discussion: The routine verifies that each of the integers from 0 to to N-1 occurs among the N entries of the permutation. Licensing: This code is distributed under the MIT license. Modified: 24 May 2015 Author: John Burkardt Parameters: Input, int N, the number of entries. Input, int P[N], the array to check. Output, int PERM0_CHECK: 0, P is a legal permutation of (0,...,N-1). 1, P is not a legal permutation of (0,...,N-1); */ { int ierror; int location; int value; ierror = 0; for ( value = 0; value < n; value++ ) { ierror = 1; for ( location = 0; location < n; location++ ) { if ( p[location] == value ) { ierror = 0; break; } } if ( ierror != 0 ) { printf ( "\n" ); printf ( "PERM0_CHECK - Warning!\n" ); printf ( " Permutation is missing value %d\n", value ); break; } } return ierror; } /******************************************************************************/ void perm0_cycle ( int n, int p[], int *isgn, int *ncycle, int iopt ) /******************************************************************************/ /* Purpose: perm0_cycle() analyzes a permutation of (0,...,N-1). Discussion: The routine will count cycles, find the sign of a permutation, and tag a permutation. Example: Input: N = 9 IOPT = 1 P = 2, 3, 9, 6, 7, 8, 5, 4, 1 Output: NCYCLE = 3 ISGN = +1 P = -2, 3, 9, -6, -7, 8, 5, 4, 1 Licensing: This code is distributed under the MIT license. Modified: 28 March 2009 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the number of objects being permuted. Input, int P[N]: P describes a permutation, in the sense that entry I is to be moved to P[I]. If IOPT = 0, then P will not be changed by this routine. Output, int P[N]. If IOPT = 1, then on output, P will be "tagged". That is, one element of every cycle in P will be negated. In this way, a user can traverse a cycle by starting at any entry I1 of P which is negative, moving to I2 = ABS(P[I1]), then to P[I2], and so on, until returning to I1. Output, int *ISGN, the "sign" of the permutation, which is +1 if the permutation is even, -1 if odd. Every permutation may be produced by a certain number of pairwise switches. If the number of switches is even, the permutation itself is called even. Output, int *NCYCLE, the number of cycles in the permutation. Input, int IOPT, requests tagging. 0, the permutation will not be tagged. 1, the permutation will be tagged. */ { int i; int i1; int i2; int ierror; int is; ierror = perm0_check ( n, p ); if ( ierror != 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "PERM0_CYCLE(): Fatal error!\n" ); fprintf ( stderr, " PERM0_CHECK rejects this permutation.\n" ); exit ( 1 ); } /* Increment. */ for ( i = 0; i < n; i++ ) { p[i] = p[i] + 1; } is = 1; *ncycle = n; for ( i = 1; i <= n; i++ ) { i1 = p[i-1]; while ( i < i1 ) { *ncycle = *ncycle - 1; i2 = p[i1-1]; p[i1-1] = -i2; i1 = i2; } if ( iopt != 0 ) { is = - i4_sign ( p[i-1] ); } p[i-1] = abs ( p[i-1] ) * i4_sign ( is ); } *isgn = 1 - 2 * ( ( n - *ncycle ) % 2 ); /* Decrement. */ for ( i = 0; i < n; i++ ) { p[i] = p[i] - 1; } return; } /******************************************************************************/ int perm0_distance ( int n, int a[], int b[] ) /******************************************************************************/ /* Purpose: perm0_distance() computes distance between two permutations of (0,...,N-1). Discussion: The distance is known as the Ulam metric. If we let N be the order of the permutations A and B, and L(P) be the length of the longest ascending subsequence of a permutation P, then the Ulam metric distance between A and B is N - L ( A * inverse ( B ) ). Licensing: This code is distributed under the MIT license. Modified: 28 March 2009 Author: John Burkardt Input: int N, the order of the permutation. int A[N], B[N], the permutations to be examined. Output: int K, the Ulam metric distance between A and B. */ { int *binv; int *c; int length; int *sub; c = ( int * ) malloc ( n * sizeof ( int ) ); sub = ( int * ) malloc ( n * sizeof ( int ) ); binv = perm0_inverse ( n, b ); perm0_mul ( n, a, binv, c ); perm_ascend ( n, c, &length, sub ); free ( binv ); free ( c ); free ( sub ); return ( n - length ); } /******************************************************************************/ void perm0_free ( int npart, int ipart[], int nfree, int ifree[] ) /******************************************************************************/ /* Purpose: perm0_free() reports the unused items in a partial permutation of (0,...,N-1). Discussion: It is assumed that the N objects being permuted are the integers from 0 to N-1, and that IPART contains a "partial" permutation, that is, the NPART entries of IPART represent the beginning of a permutation of all N items. The routine returns in IFREE the items that have not been used yet. Licensing: This code is distributed under the MIT license. Modified: 28 March 2009 Author: John Burkardt Parameters: Input, int NPART, the number of entries in IPART. NPART may be 0. Input, int IPART[NPART], the partial permutation, which should contain, at most once, some of the integers between 0 and NPART+NFREE-1. Input, int NFREE, the number of integers that have not been used in IPART. This is simply N - NPART. NFREE may be zero. Output, int IFREE[NFREE], the integers between 1 and NPART+NFREE that were not used in IPART. */ { int i; int j; int k; int match; int n; n = npart + nfree; if ( npart < 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "PERM0_FREE(): Fatal error!\n" ); fprintf ( stderr, " NPART < 0.\n" ); exit ( 1 ); } else if ( npart == 0 ) { i4vec_indicator0 ( n, ifree ); } else if ( nfree < 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "PERM0_FREE(): Fatal error!\n" ); fprintf ( stderr, " NFREE < 0.\n" ); exit ( 1 ); } else if ( nfree == 0 ) { return; } else { k = 0; for ( i = 0; i < n; i++ ) { match = -1; for ( j = 0; j < npart; j++ ) { if ( ipart[j] == i ) { match = j; break; } } if ( match == -1 ) { k = k + 1; if ( nfree < k ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "PERM0_FREE(): Fatal error!\n" ); fprintf ( stderr, " The partial permutation is illegal.\n" ); fprintf ( stderr, " Technically, because NFREE < K.\n" ); fprintf ( stderr, " N = %d\n", n ); fprintf ( stderr, " NPART = %d\n", npart ); fprintf ( stderr, " NFREE = %d\n", nfree ); fprintf ( stderr, " K = %d\n", k ); fprintf ( stderr, "\n" ); fprintf ( stderr, " The partial permutation:\n" ); fprintf ( stderr, "\n" ); for ( i = 0; i < npart; i++ ) { fprintf ( stderr, "%2d ", ipart[i] ); } fprintf ( stderr, "\n" ); exit ( 1 ); } ifree[k-1] = i; } } } return; } /******************************************************************************/ int *perm0_inverse ( int n, int p1[] ) /******************************************************************************/ /* Purpose: perm0_inverse() inverts a permutation of (0,...,N-1). Licensing: This code is distributed under the MIT license. Modified: 08 June 2015 Author: John Burkardt Parameters: Input, int N, the number of objects being permuted. Input, int P1[N], the permutation. Output, int PERM0_INVERSE[N], the inverse permutation. */ { int i; int i0; int i1; int i2; int ierror; int is; int *p2; if ( n <= 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "PERM0_INVERSE(): Fatal error!\n" ); fprintf ( stderr, " Input value of N = %d\n", n ); exit ( 1 ); } ierror = perm0_check ( n, p1 ); if ( ierror != 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "PERM0_INVERSE(): Fatal error!\n" ); fprintf ( stderr, " PERM0_CHECK rejects this permutation.\n" ); exit ( 1 ); } /* Temporary increment. */ p2 = ( int * ) malloc ( n * sizeof ( int ) ); for ( i = 0; i < n; i++ ) { p2[i] = p1[i] + 1; } is = 1; for ( i = 1; i <= n; i++ ) { i1 = p2[i-1]; while ( i < i1 ) { i2 = p2[i1-1]; p2[i1-1] = - i2; i1 = i2; } is = - i4_sign ( p2[i-1] ); p2[i-1] = abs ( p2[i-1] ) * i4_sign ( is ); } for ( i = 1; i <= n; i++ ) { i1 = - p2[i-1]; if ( 0 <= i1 ) { i0 = i; for ( ; ; ) { i2 = p2[i1-1]; p2[i1-1] = i0; if ( i2 < 0 ) { break; } i0 = i1; i1 = i2; } } } /* Decrement. */ for ( i = 0; i < n; i++ ) { p2[i] = p2[i] - 1; } return p2; } /******************************************************************************/ void perm0_inverse2 ( int n, int p[] ) /******************************************************************************/ /* Purpose: perm0_inverse2() inverts a permutation of (0,...,N-1). Discussion: The routine needs no extra vector storage in order to compute the inverse of a permutation. This feature might be useful if the permutation is large. Licensing: This code is distributed under the MIT license. Modified: 12 June 2015 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the number of objects in the permutation. Input, int P[N]: the permutation, in standard index form. Output, int P[N], the inverse permutation. */ { int i; int ierror; int j; int k; int m; ierror = perm0_check ( n, p ); if ( ierror != 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "PERM0_INVERSE2(): Fatal error!\n" ); fprintf ( stderr, " PERM0_CHECK rejects this permutation.\n" ); exit ( 1 ); } for ( i = 0; i < n; i++ ) { p[i] = p[i] + 1; } for ( m = n; 1 <= m; m-- ) { i = p[m-1]; if ( i < 0 ) { p[m-1] = -i; } else if ( i != m ) { k = m; for ( ; ; ) { j = p[i-1]; p[i-1] = -k; if ( j == m ) { p[m-1] = i; break; } k = i; i = j; } } } for ( i = 0; i < n; i++ ) { p[i] = p[i] - 1; } return; } /******************************************************************************/ int *perm0_inverse3_new ( int n, int p[] ) /******************************************************************************/ /* Purpose: perm0_inverse3_new() produces the inverse of a permutation of (0,...,N-1). Licensing: This code is distributed under the MIT license. Modified: 12 June 2015 Author: John Burkardt Parameters: Input, int N, the number of items permuted. Input, int P[N], a permutation. Output, int PERM_INVERSE3_NEW[N], the inverse permutation. */ { int i; int ierror; int *p_inv; ierror = perm0_check ( n, p ); if ( ierror != 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "PERM0_INVERSE3(): Fatal error!\n" ); fprintf ( stderr, " PERM0_CHECK rejects this permutation.\n" ); exit ( 1 ); } p_inv = ( int * ) malloc ( n * sizeof ( int ) ); for ( i = 0; i < n; i++ ) { p_inv[p[i]] = i; } return p_inv; } /******************************************************************************/ void perm0_lex_next ( int n, int p[], int *more ) /******************************************************************************/ /* Purpose: perm0_lex_next() generates permutations of (0,...,N-1) in lexical order. Example: N = 3 1 0 1 2 2 0 2 1 3 1 0 2 4 1 2 0 5 2 0 1 6 2 1 0 Licensing: This code is distributed under the MIT license. Modified: 28 March 2009 Author: Original FORTRAN77 version by Mok-Kong Shen. This version by John Burkardt. Reference: Mok-Kong Shen, Algorithm 202: Generation of Permutations in Lexicographical Order, Communications of the ACM, Volume 6, September 1963, page 517. Parameters: Input, int N, the number of elements being permuted. Input, int P[N], the permutation, in standard index form. Input, int *MORE: On the first call, the user should set MORE = FALSE which signals the routine to do initialization. Output, int P[N], the next permutation. Output, int *MORE: TRUE then another permutation has been computed and returned, while if MORE is FALSE there are no more permutations. */ { int j; int k; int temp; int u; int w; /* Initialization. */ if ( !( *more ) ) { i4vec_indicator0 ( n, p ); *more = 1; } else { if ( n <= 1 ) { *more = 0; return; } w = n; while ( p[w-1] < p[w-2] ) { if ( w == 2 ) { *more = 0; return; } w = w - 1; } u = p[w-2]; for ( j = n; w <= j; j-- ) { if ( u < p[j-1] ) { p[w-2] = p[j-1]; p[j-1] = u; for ( k = 0; k <= ( n - w - 1 ) / 2; k++ ) { temp = p[n-k-1]; p[n-k-1] = p[w+k-1]; p[w+k-1] = temp; } return; } } } return; } /******************************************************************************/ void perm0_mul ( int n, int p1[], int p2[], int p3[] ) /******************************************************************************/ /* Purpose: perm0_mul() "multiplies" two permutations of (0,...,N-1). Licensing: This code is distributed under the MIT license. Modified: 28 March 2009 Author: John Burkardt Parameters: Input, int N, the order of the permutations. Input, int P1[N], P2[N], the permutations. Output, int P3[N], the product permutation. */ { int i; int ierror; ierror = perm0_check ( n, p1 ); if ( ierror != 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "PERM0_MUL(): Fatal error!\n" ); fprintf ( stderr, " PERM0_CHECK rejects this permutation.\n" ); exit ( 1 ); } ierror = perm0_check ( n, p2 ); if ( ierror != 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "PERM0_MUL(): Fatal error!\n" ); fprintf ( stderr, " PERM0_CHECK rejects this permutation.\n" ); exit ( 1 ); } for ( i = 0; i < n; i++ ) { p3[i] = p2[p1[i]]; } return; } /******************************************************************************/ void perm0_next ( int n, int p[], int *more, int *even ) /******************************************************************************/ /* Purpose: perm0_next() computes permutations of (0,...,N-1), one at a time. Discussion: The routine is initialized by calling with MORE = TRUE, in which case it returns the identity permutation. If the routine is called with MORE = FALSE, then the successor of the input permutation is computed. Licensing: This code is distributed under the MIT license. Modified: 13 June 2015 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the number of objects being permuted. Input/output, int P[N], the permutation, in standard index form. On the first call, the input value is unimportant. On subsequent calls, the input value should be the same as the output value from the previous call. In other words, the user should just leave P alone. On output, contains the "next" permutation. Input/output, int *MORE. Set MORE = FALSE before the first call. MORE will be reset to TRUE and a permutation will be returned. Each new call produces a new permutation until MORE is returned FALSE. Input/output, int *EVEN. The input value of EVEN should simply be its output value from the previous call; (the input value on the first call doesn't matter.) On output, EVEN is TRUE if the output permutation is even, that is, involves an even number of transpositions. */ { int i; int i1; int ia; int id; int is; int j; int l; int m; if ( !( *more ) ) { i4vec_indicator0 ( n, p ); *more = 1; *even = 1; if ( n == 1 ) { *more = 0; return; } if ( p[n-1] != 0 || p[0] != 1 + ( n % 2 ) ) { return; } for ( i = 1; i <= n-3; i++ ) { if ( p[i] != p[i-1] + 1 ) { return; } } *more = 0; } else { if ( n == 1 ) { p[0] = 0; *more = 0; return; } if ( *even ) { ia = p[0]; p[0] = p[1]; p[1] = ia; *even = 0; if ( p[n-1] != 0 || p[0] != 1 + ( n % 2 ) ) { return; } for ( i = 1; i <= n-3; i++ ) { if ( p[i] != p[i-1] + 1 ) { return; } } *more = 0; return; } else { *more = 0; is = 0; for ( i1 = 2; i1 <= n; i1++ ) { ia = p[i1-1]; i = i1 - 1; id = 0; for ( j = 1; j <= i; j++ ) { if ( ia < p[j-1] ) { id = id + 1; } } is = id + is; if ( id != i * ( is % 2 ) ) { *more = 1; break; } } if ( !( *more ) ) { p[0] = 0; return; } } m = ( ( is + 1 ) % 2 ) * ( n + 1 ); for ( j = 1; j <= i; j++ ) { if ( i4_sign ( p[j-1] - ia ) != i4_sign ( p[j-1] - m ) ) { m = p[j-1]; l = j; } } p[l-1] = ia; p[i1-1] = m; *even = 1; } return; } /******************************************************************************/ void perm0_next2 ( int n, int p[], int *done ) /******************************************************************************/ /* Purpose: perm0_next2() generates permutations of (0,...,N-1). Discussion: The routine generates the permutations one at a time. It uses a particular ordering of permutations, generating them from the first (which is the identity permutation) to the N!-th. The same ordering is used by the routines PERM0_RANK and PERM0_UNRANK. Licensing: This code is distributed under the MIT license. Modified: 28 March 2009 Author: John Burkardt. Reference: Dennis Stanton, Dennis White, Constructive Combinatorics, Springer, 1986, ISBN: 0387963472, LC: QA164.S79. Parameters: Input, int N, the number of elements in the set to be permuted. Input/output, int P[N], the permutation, in standard index form. Input/output, int *DONE. The user should set the input value of DONE only once, before the first call to compute the permutations. The user should set DONE to TRUE, which signals the routine that it is to initialize itself. Thereafter, the routine will set DONE to FALSE and will compute a new permutation on each call. However, when there are no more permutations to compute, the routine will not return a new permutation, but instead will return DONE with the value TRUE. At this point, all the permutations have been computed. */ { static int *active = NULL; int i; static int *idir = NULL; static int *invers = NULL; int j; int nactiv; /* An input value of FALSE for DONE is assumed to mean a new computation is beginning. */ if ( *done ) { i4vec_indicator1 ( n, p ); if ( active ) { free ( active ); } active = ( int * ) malloc ( n * sizeof ( int ) ); if ( idir ) { free ( idir ); } idir = ( int * ) malloc ( n * sizeof ( int ) ); if ( invers ) { free ( invers ); } invers = ( int * ) malloc ( n * sizeof ( int ) ); for ( i = 0; i < n; i++ ) { invers[i] = p[i]; } for ( i = 0; i < n; i++ ) { idir[i] = -1; } active[0] = 0; for ( i = 1; i < n; i++ ) { active[i] = 1; } /* Set the DONE flag to FALSE, signifying there are more permutations to come. Except, of course, that we must take care of the trivial case! */ if ( 1 < n ) { *done = 0; } else { *done = 1; } } /* Otherwise, assume we are in a continuing computation */ else { for ( i = 0; i < n; i++ ) { p[i] = p[i] + 1; } nactiv = 0; for ( i = 1; i <= n; i++ ) { if ( active[i-1] != 0 ) { nactiv = i; } } if ( nactiv <= 0 ) { *done = 1; } else { j = invers[nactiv-1]; p[j-1] = p[j+idir[nactiv-1]-1]; p[j+idir[nactiv-1]-1] = nactiv; invers[nactiv-1] = invers[nactiv-1] + idir[nactiv-1]; invers[p[j-1]-1] = j; if ( j + 2 * idir[nactiv-1] < 1 || n < j + 2 * idir[nactiv-1] ) { idir[nactiv-1] = - idir[nactiv-1]; active[nactiv-1] = 0; } else if ( nactiv < p[j+2*idir[nactiv-1]-1] ) { idir[nactiv-1] = - idir[nactiv-1]; active[nactiv-1] = 0; } for ( i = nactiv; i < n; i++ ) { active[i] = 1; } } } if ( *done ) { free ( active ); active = NULL; free ( idir ); idir = NULL; free ( invers ); invers = NULL; } for ( i = 0; i < n; i++ ) { p[i] = p[i] - 1; } return; } /******************************************************************************/ void perm0_next3 ( int n, int p[], int *more, int *rank ) /******************************************************************************/ /* Purpose: perm0_next3() computes permutations of (0,...,N-1). Discussion: The routine is initialized by calling with MORE = TRUE in which case it returns the identity permutation. If the routine is called with MORE = FALSE then the successor of the input permutation is computed. Trotter's algorithm is used. Licensing: This code is distributed under the MIT license. Modified: 09 November 2018 Author: Original FORTRAN77 version by Hale Trotter, This version by John Burkardt. Reference: Hale Trotter, PERM, Algorithm 115, Communications of the Association for Computing Machinery, Volume 5, 1962, pages 434-435. Parameters: Input, int N, the number of objects being permuted. Input/output, int P[N], the permutation, in standard index form. If MORE is TRUE, then P is assumed to contain the "previous" permutation, and on P(I) is the value of the I-th object under the next permutation. Otherwise, P will be set to the "first" permutation. Input/output, int *MORE. Set MORE = FALSE before first calling this routine. MORE will be reset to TRUE and a permutation will be returned. Each new call produces a new permutation until MORE is returned FALSE. Input/output, int *RANK, the number of the current permutation. */ { int i; int m2; int n2; int q; int s; int t; int temp; if ( ! ( *more ) ) { for ( i = 0; i < n; i++ ) { p[i] = i; } *more = 1; *rank = 1; } else { n2 = n; m2 = *rank; s = n; for ( ; ; ) { q = m2 % n2; t = m2 % ( 2 * n2 ); if ( q != 0 ) { break; } if ( t == 0 ) { s = s - 1; } m2 = m2 / n2; n2 = n2 - 1; if ( n2 == 0 ) { for ( i = 0; i < n; i++ ) { p[i] = i; } *more = 0; *rank = 1; break; } } if ( n2 != 0 ) { if ( q == t ) { s = s - q; } else { s = s + q - n2; } temp = p[s-1]; p[s-1] = p[s]; p[s] = temp; *rank = *rank + 1; } } return; } /******************************************************************************/ void perm0_print ( int n, int p[], char *title ) /******************************************************************************/ /* Purpose: perm0_print() prints a permutation of (0,...,N-1). Discussion: The permutation is assumed to be 0-based. Example: Input: P = 6 1 3 0 4 2 5 Printed output: "This is the permutation:" 0 1 2 3 4 5 6 6 1 3 0 4 2 5 Licensing: This code is distributed under the MIT license. Modified: 23 June 2015 Author: John Burkardt Parameters: Input, int N, the number of objects permuted. Input, int P[N], the permutation, in standard index form. Input, char *TITLE, an optional title. If no title is supplied, then only the permutation is printed. */ { int i; int ihi; int ilo; int inc = 20; if ( s_len_trim ( title ) != 0 ) { printf ( "\n" ); printf ( "%s\n", title ); for ( ilo = 0; ilo < n; ilo = ilo + inc ) { ihi = ilo + inc; if ( n < ihi ) { ihi = n; } printf ( "\n" ); printf ( " " ); for ( i = ilo; i < ihi; i++ ) { printf ( "%4d", i ); } printf ( "\n" ); printf ( " " ); for ( i = ilo; i < ihi; i++ ) { printf ( "%4d", p[i] ); } printf ( "\n" ); } } else { for ( ilo = 0; ilo < n; ilo = ilo + inc ) { ihi = ilo + inc; if ( n < ihi ) { ihi = n; } printf ( " " ); for ( i = ilo; i < ihi; i++ ) { printf ( "%4d", p[i] ); } printf ( "\n" ); } } return; } /******************************************************************************/ void perm0_random ( int n, int *seed, int p[] ) /******************************************************************************/ /* Purpose: perm0_random() selects a random permutation of (0,...,N-1). Discussion: The algorithm is known as the Fisher-Yates or Knuth shuffle. Licensing: This code is distributed under the MIT license. Modified: 28 March 2009 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the number of objects to be permuted. Input/output, int *SEED, a seed for the random number generator. Output, int P[N], a permutation of (0,...,N-1). */ { int i; int j; int t; for ( i = 0; i < n; i++ ) { p[i] = i; } for ( i = 0; i < n - 1; i++ ) { j = i4_uniform_ab ( i, n - 1, seed ); t = p[i]; p[i] = p[j]; p[j] = t; } return; } /******************************************************************************/ void perm0_random2 ( int n, int *seed, int p[] ) /******************************************************************************/ /* Purpose: perm0_random2() selects a random permutation of (0,...,N-1). Licensing: This code is distributed under the MIT license. Modified: 28 March 2009 Author: Original FORTRAN77 version by James Filliben. This version by John Burkardt Reference: K L Hoffman, D R Shier, Algorithm 564, A Test Problem Generator for Discrete Linear L1 Approximation Problems, ACM Transactions on Mathematical Software, Volume 6, Number 4, December 1980, pages 615-617. Parameters: Input, int N, the number of elements of the array. Input/output, int *SEED, a seed for the random number generator. Output, int P[N], a permutation, in standard index form. */ { int i; int j; int temp; if ( n < 1 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "PERM0_RANDOM2(): Fatal error!\n" ); fprintf ( stderr, " Illegal input value of N = %d\n", n ); fprintf ( stderr, " N must be at least 1!\n" ); exit ( 1 ); } if ( n == 1 ) { p[0] = 0; return; } i4vec_indicator0 ( n, p ); for ( i = 1; i <= n; i++ ) { j = i + i4_uniform_ab ( 1, n, seed ); if ( n < j ) { j = j - n; } if ( i != j ) { temp = p[j-1]; p[j-1] = p[i-1]; p[i-1] = temp; } } return; } /******************************************************************************/ int perm0_rank ( int n, int p[], int invers[] ) /******************************************************************************/ /* Purpose: perm0_rank() ranks a permutation of (0,...,N-1). Discussion: This is the same as asking for the step at which PERM0_NEXT2 would compute the permutation. The value of the rank will be between 1 and N!. Licensing: This code is distributed under the MIT license. Modified: 13 June 2015 Author: John Burkardt. Reference: Dennis Stanton, Dennis White, Constructive Combinatorics, Springer, 1986, ISBN: 0387963472, LC: QA164.S79. Parameters: Input, int N, the number of elements in the set that is permuted by P. Input, int P[N], a permutation, in standard index form. Output, int INVERS[N], the inverse permutation of P. It is computed as part of the algorithm, and may be of use to the user. INVERS(P(I)) = I for each entry I. Output, int PERM0_RANK, the rank of the permutation. This gives the order of the given permutation in the set of all the permutations on N elements. */ { int count; int i; int ierror; int j; int rank; int rem; /* Make sure the permutation is a legal one. */ ierror = perm0_check ( n, p ); if ( ierror != 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "PERM0_RANK(): Fatal error!\n" ); fprintf ( stderr, " PERM0_CHECK rejects this permutation.\n" ); exit ( 1 ); } /* Compute the inverse permutation. */ for ( i = 0; i < n; i++ ) { invers[i] = p[i]; } perm0_inverse2 ( n, invers ); rank = 0; for ( i = 1; i <= n; i++) { count = 0; for ( j = 0; j < invers[i-1]; j++ ) { if ( p[j] < i ) { count = count + 1; } } if ( ( rank % 2 ) == 1 ) { rem = count; } else { rem = i - 1 - count; } rank = i * rank + rem; } rank = rank + 1; return rank; } /******************************************************************************/ int perm0_sign ( int n, int p[] ) /******************************************************************************/ /* Purpose: perm0_sign() returns the sign of a permutation of (0,...,N-1). Discussion: A permutation can always be replaced by a sequence of pairwise transpositions. A given permutation can be represented by many different such transposition sequences, but the number of such transpositions will always be odd or always be even. If the number of transpositions is even or odd, the permutation is said to be even or odd. Example: Input: N = 9 P = 2, 3, 9, 6, 7, 8, 5, 4, 1 Output: PERM_SIGN = +1 Licensing: This code is distributed under the MIT license. Modified: 08 July 2011 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the number of objects permuted. Input, int P[N], a permutation, in standard index form. Output, int PERM0_SIGN, the "sign" of the permutation. +1, the permutation is even, -1, the permutation is odd. */ { int i; int ierror; int j; int p_sign; int *q; int temp; ierror = perm0_check ( n, p ); if ( ierror != 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "PERM0_SIGN(): Fatal error!\n" ); fprintf ( stderr, " PERM0_CHECK rejects this permutation.\n" ); exit ( 1 ); } /* Make a temporary copy of the permutation. */ q = ( int * ) malloc ( n * sizeof ( int ) ); for ( i = 0; i < n; i++ ) { q[i] = p[i]; } /* Start with P_SIGN indicating an even permutation. Restore each element of the permutation to its correct position, updating P_SIGN as you go. */ p_sign = 1; for ( i = 1; i <= n - 1; i++ ) { j = i4vec_index ( n, q, i ); if ( j != i - 1 ) { temp = q[i-1]; q[i-1] = q[j]; q[j] = temp; p_sign = - p_sign; } } free ( q ); return p_sign; } /******************************************************************************/ void perm0_to_equiv ( int n, int p[], int *npart, int jarray[], int iarray[] ) /******************************************************************************/ /* Purpose: perm0_to_equiv() find the partition induced by a permutation of (0,...,N-1). Example: Input: N = 9 P = 1, 2, 8, 5, 6, 7, 4, 3, 0 Output: NPART = 3 JARRAY = 4, 3, 2 IARRAY = 1, 1, 1, 2 3 2 3 2, 1 Licensing: This code is distributed under the MIT license. Modified: 15 June 2015 Author: John Burkardt Parameters: Input, int N, the number of objects being permuted. Input, int P[N], a permutation, in standard index form. Output, int *NPART, number of subsets in the partition. Output, int JARRAY[N]. JARRAY(I) is the number of elements in the I-th subset of the partition. Output, int IARRAY[N]. IARRAY(I) is the class to which element I belongs. */ { int i; int ierror; int j; int k; ierror = perm0_check ( n, p ); if ( ierror != 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "PERM0_TO_EQUIV(): Fatal error!\n" ); fprintf ( stderr, " PERM0_CHECK rejects this permutation.\n" ); exit ( 1 ); } /* Initialize. */ for ( i = 0; i < n; i++ ) { iarray[i] = -1; } for ( i = 0; i < n; i++ ) { jarray[i] = -1; } *npart = 0; /* Search for the next item J which has not been assigned a subset/orbit. */ for ( j = 0; j < n; j++ ) { if ( iarray[j] != -1 ) { continue; } /* Begin a new subset/orbit. */ *npart = *npart + 1; k = j; /* Add the item to the subset/orbit. */ for ( ; ; ) { jarray[*npart-1] = jarray[*npart-1] + 1; iarray[k] = *npart; /* Apply the permutation. If the permuted object isn't already in the subset/orbit, add it. */ k = p[k]; if ( iarray[k] != -1 ) { break; } } } return; } /******************************************************************************/ void perm0_to_inversion ( int n, int p[], int ins[] ) /******************************************************************************/ /* Purpose: perm0_to_inversion(): permutation (0,...,N-1) to inversion sequence. Discussion: For a given permutation P acting on objects 0 through N-1, the inversion sequence INS is defined as: INS(1) = 0 INS(I) = number of values J < I for which P(I) < P(J). Example: Input: ( 2, 4, 0, 3, 1 ) Output: ( 0, 0, 2, 1, 3 ) The original permutation can be recovered from the inversion sequence. Licensing: This code is distributed under the MIT license. Modified: 05 June 2015 Author: John Burkardt Reference: Dennis Stanton, Dennis White, Constructive Combinatorics, Springer, 1986, ISBN: 0387963472, LC: QA164.S79. Parameters: Input, int N, the number of objects being permuted. Input, int P[N], the permutation, in standard index form. The I-th item has been mapped to P(I). Output, int INS[N], the inversion sequence of the permutation. */ { int i; int ierror; int j; ierror = perm0_check ( n, p ); if ( ierror != 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "PERM0_TO_INVERSION(): Fatal error!\n" ); fprintf ( stderr, " PERM0_CHECK rejects this permutation.\n" ); exit ( 1 ); } for ( i = 0; i < n; i++ ) { ins[i] = 0; } for ( i = 0; i < n; i++ ) { for ( j = 0; j < i; j++ ) { if ( p[i] < p[j] ) { ins[i] = ins[i] + 1; } } } return; } /******************************************************************************/ void perm0_to_ytb ( int n, int p[], int lambda[], int a[] ) /******************************************************************************/ /* Purpose: perm0_to_ytb() converts a permutation of (0,...,N-1) to a Young tableau. Discussion: The mapping is not invertible. In most cases, several permutations correspond to the same tableau. Example: N = 7 P = 6 1 3 0 4 2 5 YTB = 1 2 3 6 4 5 7 LAMBDA = 4 2 1 0 0 0 0 A = 1 1 1 2 2 1 3 Licensing: This code is distributed under the MIT license. Modified: 28 March 2009 Author: John Burkardt Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the integer to be partitioned. Input, int P[N], a permutation, in standard index form. Output, int LAMBDA[N]. LAMBDA[I] is the length of the I-th row. Output, int A[N]. A[I] is the row containing I. */ { int another; int compare; int i; int put_index; int put_row; int put_value; /* Initialize. */ for ( i = 0; i < n; i++ ) { lambda[i] = 0; } for ( i = 0; i < n; i++ ) { a[i] = 0; } /* Now insert each item of the permutation. */ for ( put_index = 1; put_index <= n; put_index++ ) { put_value = p[put_index-1]; put_row = 1; for ( ; ; ) { another = 0; for ( compare = put_value+1; compare <= n; compare++ ) { if ( a[compare-1] == put_row ) { another = 1; a[put_value-1] = put_row; a[compare-1] = 0; put_value = compare; put_row = put_row + 1; break; } } if ( !another ) { break; } } a[put_value-1] = put_row; lambda[put_row-1] = lambda[put_row-1] + 1; } return; } /******************************************************************************/ void perm0_unrank ( int n, int rank, int p[] ) /******************************************************************************/ /* Purpose: perm0_unrank() "unranks" a permutation of (0,...,N-1). Discussion: That is, given a rank, it computes the corresponding permutation. This is the same as asking for the permutation which PERM0_NEXT2 would compute at the RANK-th step. The value of the rank should be between 1 and N!. Licensing: This code is distributed under the MIT license. Modified: 27 March 2009 Author: John Burkardt. Reference: Dennis Stanton, Dennis White, Constructive Combinatorics, Springer, 1986, ISBN: 0387963472, LC: QA164.S79. Parameters: Input, int N, the number of elements in the set. Input, int RANK, the desired rank of the permutation. This gives the order of the given permutation in the set of all the permutations on N elements, using the ordering of PERM0_NEXT2. Output, int P[N], the permutation, in standard index form. */ { int i; int icount; int iprev; int irem; int j; int jdir; int jrank; for ( i = 0; i < n; i++ ) { p[i] = -1; } if ( rank < 1 || i4_factorial ( n ) < rank ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "PERM0_UNRANK(): Fatal error!\n" ); fprintf ( stderr, " Illegal input value for RANK.\n" ); fprintf ( stderr, " RANK must be between 1 and N!,\n" ); fprintf ( stderr, " but the input value is %d\n", rank ); exit ( 1 ); } jrank = rank - 1; for ( i = 1; i <= n; i++ ) { iprev = n + 1 - i; irem = jrank % iprev; jrank = jrank / iprev; if ( ( jrank % 2 ) == 1 ) { j = 0; jdir = 1; } else { j = n + 1; jdir = -1; } icount = 0; for ( ; ; ) { j = j + jdir; if ( p[j-1] == -1 ) { icount = icount + 1; } if ( irem < icount ) { break; } } p[j-1] = iprev - 1; } return; } /******************************************************************************/ void perm1_canon_to_cycle ( int n, int p1[], int p2[] ) /******************************************************************************/ /* Purpose: perm1_canon_to_cycle(): permutation of (1,...,N) from canonical to cycle form. Discussion: This algorithm relies on the assumption that the entries in the permutation vector are strictly positive, and uses the sign of the entries as a temporary marker. Thus it cannot be implemented directly with a 0-based permutation. Example: Input: 4 5 2 1 6 3 Output: -4 5 -2 -1 6 3, indicating the cycle structure ( 4, 5 ) ( 2 ) ( 1, 6, 3 ) Licensing: This code is distributed under the MIT license. Modified: 23 June 2015 Author: John Burkardt Reference: Donald Knuth, The Art of Computer Programming, Volume 1, Fundamental Algorithms, Addison Wesley, 1968, page 176. Parameters: Input, int N, the number of objects permuted. Input, int P1[N], the permutation, in canonical form. Output, int P2[N], the permutation, in cycle form. */ { int i; int pmin; for ( i = 0; i < n; i++ ) { p2[i] = p1[i]; } pmin = p2[0] + 1; for ( i = 0; i < n; i++ ) { if ( p2[i] < pmin ) { pmin = p2[i]; p2[i] = -p2[i]; } } return; } /******************************************************************************/ int perm1_check ( int n, int p[] ) /******************************************************************************/ /* Purpose: perm1_check() checks a permutation of (1,...,N). Discussion: The routine verifies that each of the integers from 1 to to N occurs among the N entries of the permutation. Licensing: This code is distributed under the MIT license. Modified: 24 May 2015 Author: John Burkardt Parameters: Input, int N, the number of entries. Input, int P[N], the array to check. Output, int PERM1_CHECK: 0, P is a legal permutation of (1,...,N). 1, P is not a legal permutation of (1,...,N); */ { int ierror; int location; int value; ierror = 0; for ( value = 1; value <= n; value++ ) { ierror = 1; for ( location = 0; location < n; location++ ) { if ( p[location] == value ) { ierror = 0; break; } } if ( ierror != 0 ) { printf ( "\n" ); printf ( "perm1_check(): Fatal error!\n" ); printf ( " Permutation is missing value %d\n", value ); break; } } return ierror; } /******************************************************************************/ int perm1_cycle_max ( int n, int p[] ) /******************************************************************************/ /* Purpose: perm1_cycle_max() returns maximum cycle length of permutation of 1 to N. Discussion: P = 2, 3, 9, 6, 7, 8, 5, 4, 1 Cycles: ( 1, 2, 3, 9 ), ( 4, 6, 8 ), ( 5, 7 ) cycle_max = 4 Licensing: This code is distributed under the MIT license. Modified: 14 November 2022 Author: John Burkardt Input: int N, the number of objects permuted. int P[N], the permutation, in canonical form. Output: int cycle_max: the maximum cycle length. */ { int cycle_length; int cycle_max; int i; int j; cycle_max = 0; for ( i = 0; i < n; i++ ) { j = p[i] - 1; cycle_length = 1; while ( j != i ) { j = p[j] - 1; cycle_length = cycle_length + 1; } if ( cycle_max < cycle_length ) { cycle_max = cycle_length; } } return cycle_max; } /******************************************************************************/ int *perm1_cycle_stats ( int n, int p[] ) /******************************************************************************/ /* Purpose: perm1_cycle_stats() returns permutation cycle length statistics. Discussion: P = 2, 3, 9, 6, 7, 8, 5, 4, 1 Cycles: ( 1, 2, 3, 9 ), ( 4, 6, 8 ), ( 5, 7 ) cycle_max = 4 1, 2, 3, 4, 5, 6, 7, 8, 9 cycle_stats = ( 0, 1, 1, 1, 0, 0, 0, 0, 0 ) Licensing: This code is distributed under the MIT license. Modified: 26 November 2022 Author: John Burkardt Input: int N, the number of objects permuted. int P[N], the permutation, in canonical form. Output: int cycle_stats[N]: the number of cycles of each length.. */ { int cycle_length; int *cycle_stats; int i; int j; cycle_stats = ( int * ) malloc ( n * sizeof ( int ) ); for ( i = 0; i < n; i++ ) { cycle_stats[i] = 0; } for ( i = 0; i < n; i++ ) { j = p[i] - 1; cycle_length = 1; while ( j != i ) { j = p[j] - 1; cycle_length = cycle_length + 1; } cycle_stats[cycle_length-1] = cycle_stats[cycle_length-1] + 1; } for ( i = 0; i < n; i ++ ) { cycle_stats[i] = cycle_stats[i] / ( i + 1 ); } return cycle_stats; } /******************************************************************************/ void perm1_cycle_to_canon ( int n, int p1[], int p2[] ) /******************************************************************************/ /* Purpose: perm1_cycle_to_canon(): permutation of (1,...,N) from cycle to canonical form. Discussion: This algorithm relies on the assumption that the entres in the permutation vector are strictly positive, and uses the sign of the entries as a temporary marker. Thus it cannot be implemented directly with a 0-based permutation. Example: Input: -6 3 1 -5, 4 -2, indicating the cycle structure ( 6, 3, 1 ) ( 5, 4 ) ( 2 ) Output: 4 5 2 1 6 3 Discussion: The procedure is to "rotate" the elements of each cycle so that the smallest element is first: ( 1, 6, 3 ) ( 4, 5 ) ( 2 ) and then to sort the cycles in decreasing order of their first (and lowest) element: ( 4, 5 ) ( 2 ) ( 1, 6, 3 ) and then to drop the parentheses: 4 5 2 1 6 3 Licensing: This code is distributed under the MIT license. Modified: 23 June 2015 Author: John Burkardt Reference: Donald Knuth, The Art of Computer Programming, Volume 1, Fundamental Algorithms, Addison Wesley, 1968, pages 176. Parameters: Input, int N, the number of objects permuted. Input, int P1[N], the permutation, in cycle form. Output, int P2[N], the permutation, in canonical form. */ { int *hi; int i; int *indx; int j; int k; int *lo; int ncycle; int next; int nhi; int nlo; int nmin; int *pmin; int *ptemp; hi = ( int * ) malloc ( n * sizeof ( int ) ); lo = ( int * ) malloc ( n * sizeof ( int ) ); pmin = ( int * ) malloc ( n * sizeof ( int ) ); ptemp = ( int * ) malloc ( n * sizeof ( int ) ); for ( i = 0; i < n; i++ ) { p2[i] = p1[i]; } /* Work on the next cycle. */ nlo = 1; ncycle = 0; while ( nlo <= n ) /* Identify NHI, the last index in this cycle. */ { ncycle = ncycle + 1; nhi = nlo; while ( nhi < n ) { if ( p2[nhi] < 0 ) { break; } nhi = nhi + 1; } /* Identify the smallest value in this cycle. */ p2[nlo-1] = -p2[nlo-1]; pmin[ncycle-1] = p2[nlo-1]; nmin = nlo; for ( i = nlo+1; i <= nhi; i++ ) { if ( p2[i-1] < pmin[ncycle-1] ) { pmin[ncycle-1] = p2[i-1]; nmin = i; } } /* Rotate the cycle so A_MIN occurs first. */ for ( i = nlo; i <= nmin-1; i++ ) { ptemp[i+nhi-nmin] = p2[i-1]; } for ( i = nmin; i <= nhi; i++ ) { ptemp[i+nlo-nmin-1] = p2[i-1]; } lo[ncycle-1] = nlo; hi[ncycle-1] = nhi; /* Prepare to operate on the next cycle. */ nlo = nhi + 1; } /* Compute a sorting index for the cycle minima. */ indx = i4vec_sort_heap_index_d ( ncycle, pmin ); /* Copy the cycles out of the temporary array in sorted order. */ j = 0; for ( i = 0; i < ncycle; i++ ) { next = indx[i]; nlo = lo[next]; nhi = hi[next]; for ( k = nlo; k <= nhi; k++ ) { j = j + 1; p2[j-1] = ptemp[k-1]; } } free ( hi ); free ( indx ); free ( lo ); free ( pmin ); free ( ptemp ); return; } /******************************************************************************/ void perm1_cycle_to_index ( int n, int p1[], int p2[] ) /******************************************************************************/ /* Purpose: perm1_cycle_to_index(): permutation of (1,...,N) from cycle to standard index form. Discussion: This algorithm relies on the assumption that the entres in the permutation vector are strictly positive, and uses the sign of the entries as a temporary marker. Thus it cannot be implemented directly with a 0-based permutation. Example: Input: N = 9 P1 = -1, 2, 3, 9, -4, 6, 8, -5, 7 Output: P2 = 2, 3, 9, 6, 7, 8, 5, 4, 1 Licensing: This code is distributed under the MIT license. Modified: 23 June 2015 Author: John Burkardt Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the number of objects being permuted. Input, int P1[N], the permutation, in cycle form. Output, int P2[N], the permutation, in standard index form. */ { int j; int k1; int k2; int k3; for ( j = 1; j <= n; j++ ) { k1 = p1[j-1]; if ( k1 < 0 ) { k1 = -k1; k3 = k1; } if ( j + 1 <= n ) { k2 = p1[j]; if ( k2 < 0 ) { k2 = k3; } } else { k2 = k3; } p2[k1-1] = k2; } return; } /******************************************************************************/ void perm1_index_to_cycle ( int n, int p1[], int p2[] ) /******************************************************************************/ /* Purpose: perm1_index_to_cycle(): permutation of (1,...,N) from standard index to cycle form. Discussion: This algorithm relies on the assumption that the entres in the permutation vector are strictly positive, and uses the sign of the entries as a temporary marker. Thus it cannot be implemented directly with a 0-based permutation. Example: Input: N = 9 P1 = 2, 3, 9, 6, 7, 8, 5, 4, 1 Output: P2 = -1, 2, 3, 9, -4, 6, 8, -5, 7 Licensing: This code is distributed under the MIT license. Modified: 23 June 2015 Author: John Burkardt Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the number of objects being permuted. Input, int P1[N], the permutation, in standard index form. Output, int P2[N], the permutation, in cycle form. */ { int i; int ierror; int j; int k; ierror = perm1_check ( n, p1 ); if ( ierror != 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "PERM1_INDEX_TO_CYCLE(): Fatal error!\n" ); fprintf ( stderr, " PERM1_CHECK rejects this permutation.\n" ); exit ( 1 ); } i = 0; j = 1; while ( j <= n ) { if ( p1[j-1] < 0 ) { j = j + 1; } else { k = j; i = i + 1; p2[i-1] = - k; while ( p1[k-1] != j ) { i = i + 1; p2[i-1] = p1[k-1]; p1[k-1] = - p1[k-1]; k = abs ( p1[k-1] ); } p1[k-1] = - p1[k-1]; } } for ( i = 0; i < n; i++ ) { p1[i] = abs ( p1[i] ); } return; } /******************************************************************************/ void perm1_print ( int n, int p[], char *title ) /******************************************************************************/ /* Purpose: perm1_print() prints a permutation of (1,...,N). Discussion: The permutation is assumed to be 0-based. Example: Input: P = 7 2 4 1 5 3 6 Printed output: "This is the permutation:" 1 2 3 4 5 6 7 7 2 4 1 5 3 6 Licensing: This code is distributed under the MIT license. Modified: 23 June 2015 Author: John Burkardt Parameters: Input, int N, the number of objects permuted. Input, int P[N], the permutation, in standard index form. Input, char *TITLE, an optional title. If no title is supplied, then only the permutation is printed. */ { int i; int ihi; int ilo; int inc = 20; if ( s_len_trim ( title ) != 0 ) { printf ( "\n" ); printf ( "%s\n", title ); for ( ilo = 0; ilo < n; ilo = ilo + inc ) { ihi = ilo + inc; if ( n < ihi ) { ihi = n; } printf ( "\n" ); printf ( " " ); for ( i = ilo; i < ihi; i++ ) { printf ( "%4d", i + 1 ); } printf ( "\n" ); printf ( " " ); for ( i = ilo; i < ihi; i++ ) { printf ( "%4d", p[i] ); } printf ( "\n" ); } } else { for ( ilo = 0; ilo < n; ilo = ilo + inc ) { ihi = ilo + inc; if ( n < ihi ) { ihi = n; } printf ( " " ); for ( i = ilo; i < ihi; i++ ) { printf ( "%4d", p[i] ); } printf ( "\n" ); } } return; } /******************************************************************************/ void perrin ( int n, int p[] ) /******************************************************************************/ /* Purpose: perrin() returns the first N values of the Perrin sequence. Discussion: The Perrin sequence has the initial values: P(0) = 3 P(1) = 0 P(2) = 2 and subsequent entries are generated by the recurrence P(I+1) = P(I-1) + P(I-2) Note that if N is a prime, then N must evenly divide P(N). Example: 0 3 1 0 2 2 3 3 4 2 5 5 6 5 7 7 8 10 9 12 10 17 Licensing: This code is distributed under the MIT license. Modified: 27 March 2009 Author: John Burkardt Reference: Ian Stewart, "A Neglected Number", Scientific American, Volume 274, pages 102-102, June 1996. Ian Stewart, Math Hysteria, Oxford, 2004. Eric Weisstein, CRC Concise Encyclopedia of Mathematics, CRC Press, 1999. Parameters: Input, integer N, the number of terms. Output, integer P(N), the terms 0 through N-1 of the sequence. */ { int i; if ( n < 1 ) { return; } p[0] = 3; if ( n < 2 ) { return; } p[1] = 0; if ( n < 3 ) { return; } p[2] = 2; for ( i = 4; i <= n; i++ ) { p[i-1] = p[i-3] + p[i-4]; } return; } /******************************************************************************/ int pord_check ( int n, int a[] ) /******************************************************************************/ /* Purpose: pord_check() checks a matrix representing a partial ordering. Discussion: The array A is supposed to represent a partial ordering of the elements of a set of N objects. For distinct indices I and J, the value of A(I,J) is: 1, if I << J 0, otherwise ( I and J may be unrelated, or perhaps J << I). Diagonal elements of A are ignored. This routine checks that the values of A do represent a partial ordering. Licensing: This code is distributed under the MIT license. Modified: 27 March 2009 Author: John Burkardt Parameters: Input, int N, the number of elements in the set. Input, int A[N*N], the partial ordering. A[I+J*N] is 1 if I is less than J in the partial ordering, 0 otherwise. Output, int PORD_CHECK, is 1 if an error was detected. */ { int i; int j; if ( n <= 0 ) { printf ( "\n" ); printf ( "PORD_CHECK - Warning!\n" ); printf ( " N must be positive, but N = %d\n", n ); return 1; } for ( i = 0; i < n; i++ ) { for ( j = i+1; j < n; j++ ) { if ( 0 < a[i+j*n] ) { if ( 0 < a[j+i*n] ) { printf ( "\n" ); printf ( "PORD_CHECK - Warning!\n" ); printf ( " For indices I = %d\n", i ); printf ( " and J = %d\n", j ); printf ( " A(I,J) = %d\n", a[i+j*n] ); printf ( " A(J,I) = %d\n", a[j+i*n] ); return 1; } } } } return 0; } /******************************************************************************/ int power_mod ( int a, int n, int m ) /******************************************************************************/ /* Purpose: power_mod() computes mod ( A^N, M ). Discussion: Some programming tricks are used to speed up the computation, and to allow computations in which A^N is much too large to store in a real word. First, for efficiency, the power A^N is computed by determining the binary expansion of N, then computing A, A^2, A^4, and so on by repeated squaring, and multiplying only those factors that contribute to A^N. Secondly, the intermediate products are immediately "mod'ed", which keeps them small. For instance, to compute mod ( A^13, 11 ), we essentially compute 13 = 1 + 4 + 8 A^13 = A * A^4 * A^8 mod ( A^13, 11 ) = mod ( A, 11 ) * mod ( A^4, 11 ) * mod ( A^8, 11 ). Fermat's little theorem says that if P is prime, and A is not divisible by P, then ( A^(P-1) - 1 ) is divisible by P. Example: A N M X 13 0 31 1 13 1 31 13 13 2 31 14 13 3 31 27 13 4 31 10 13 5 31 6 13 6 31 16 13 7 31 22 13 8 31 7 13 9 31 29 13 10 31 5 13 11 31 3 13 12 31 8 13 13 31 11 13 14 31 19 13 15 31 30 13 16 31 18 13 17 31 17 13 18 31 4 13 19 31 21 13 20 31 25 13 21 31 15 13 22 31 9 13 23 31 24 13 24 31 2 13 25 31 26 13 26 31 28 13 27 31 23 13 28 31 20 13 29 31 12 13 30 31 1 13 31 31 13 Licensing: This code is distributed under the MIT license. Modified: 16 November 2004 Author: John Burkardt Parameters: Input, int A, the base of the expression to be tested. A should be nonnegative. Input, int N, the power to which the base is raised. N should be nonnegative. Input, int M, the divisor against which the expression is tested. M should be positive. Output, int POWER_MOD, the remainder when A^N is divided by M. */ { long long int a_square2; int d; long long int m2; int x; long long int x2; if ( a < 0 ) { return -1; } if ( m <= 0 ) { return -1; } if ( n < 0 ) { return -1; } /* A_SQUARE contains the successive squares of A. */ a_square2 = ( long long int ) a; m2 = ( long long int ) m; x2 = ( long long int ) 1; while ( 0 < n ) { d = n % 2; if ( d == 1 ) { x2 = ( x2 * a_square2 ) % m2; } a_square2 = ( a_square2 * a_square2 ) % m2; n = ( n - d ) / 2; } /* Ensure that 0 <= X. */ while ( x2 < 0 ) { x2 = x2 + m2; } x = ( int ) x2; return x; } /******************************************************************************/ void power_series1 ( int n, double alpha, double a[], double b[] ) /******************************************************************************/ /* Purpose: power_series1() computes a power series for a function G(Z) = (1+F(Z))^ALPHA. Discussion: The power series for F(Z) is given. The form of the power series are: F(Z) = A1*Z + A2*Z^2 + A3*Z^3 + ... + AN*Z^N G(Z) = B1*Z + B2*Z^2 + B3*Z^3 + ... + BN*Z^N Licensing: This code is distributed under the MIT license. Modified: 27 March 2009 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the number of terms in the power series. Input, double ALPHA, the exponent of 1+F(Z) in the definition of G(Z). Input, double A[N], the power series coefficients for F(Z). Output, double B[N], the power series coefficients for G(Z). */ { int i; int j; double v; for ( j = 1; j <= n; j++ ) { v = 0.0; for ( i = 1; i <= j-1; i++ ) { v = v + b[i-1] * a[j-i-1] * ( alpha * ( j - i ) - i ); } b[j-1] = alpha * a[j-1] + v / ( ( double ) j ); } return; } /******************************************************************************/ void power_series2 ( int n, double a[], double b[] ) /******************************************************************************/ /* Purpose: power_series2() computes the power series for a function G(Z) = EXP(F(Z)) - 1. Discussion: The power series for F(Z) is given. The power series have the form: F(Z) = A1*Z + A2*Z^2 + A3*Z^3 + ... + AN*Z^N G(Z) = B1*Z + B2*Z^2 + B3*Z^3 + ... + BN*Z^N Licensing: This code is distributed under the MIT license. Modified: 27 March 2009 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the number of terms in the power series. Input, double A[N], the power series coefficients for F(Z). Output, double B[N], the power series coefficients for G(Z). */ { int i; int j; double v; for ( j = 1; j <= n; j++ ) { v = 0.0; for ( i = 1; i <= j-1; i++ ) { v = v + b[i-1] * a[j-i-1] * ( double ) ( j - i ); } b[j-1] = a[j-1] + v / ( double ) j; } return; } /******************************************************************************/ void power_series3 ( int n, double a[], double b[], double c[] ) /******************************************************************************/ /* Purpose: power_series3() computes the power series for a function H(Z) = G(F(Z)). Discussion: The power series for F and G are given. We assume that F(Z) = A1*Z + A2*Z^2 + A3*Z^3 + ... + AN*Z^N G(Z) = B1*Z + B2*Z^2 + B3*Z^3 + ... + BN*Z^N H(Z) = C1*Z + C2*Z^2 + C3*Z^3 + ... + CN*Z^N Licensing: This code is distributed under the MIT license. Modified: 27 March 2009 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the number of terms in the power series. Input, double A[N], the power series for F Input, double B[N], the power series for G. Output, double C[N], the power series for H. */ { int i; int iq; int j; int m; double r; double v; double *work; work = ( double * ) malloc ( n * sizeof ( double ) ); for ( i = 0; i < n; i++ ) { work[i] = b[0] * a[i]; } /* Search for IQ, the index of the first nonzero entry in A. */ iq = 0; for ( i = 1; i <= n; i++ ) { if ( a[i-1] != 0.0 ) { iq = i; break; } } if ( iq != 0 ) { m = 1; for ( ; ; ) { m = m + 1; if ( n < m * iq ) { break; } if ( b[m-1] == 0.0 ) { continue; } r = b[m-1] * pow ( a[iq-1], m ); work[m*iq-1] = work[m*iq-1] + r; for ( j = 1; j <= n-m*iq; j++ ) { v = 0.0; for ( i = 1; i <= j-1; i++ ) { v = v + c[i-1] * a[j-i+iq-1] * ( double ) ( m * ( j - i ) - i ); } c[j-1] = ( ( double ) m * a[j-1] + v / ( double ) j ) / a[iq-1]; } for ( i = 1; i <= n-m*iq; i++ ) { work[i+m*iq-1] = work[i+m*iq-1] + c[i-1] * r; } } } for ( i = 0; i < n; i++ ) { c[i] = work[i]; } free ( work ); return; } /******************************************************************************/ void power_series4 ( int n, double a[], double b[], double c[] ) /******************************************************************************/ /* Purpose: power_series4() computes the power series for a function H(Z) = G ( 1/F(Z) ). Discussion: POWER_SERIES4 is given the power series for the functions F and G. We assume that F(Z) = A1*Z + A2*Z^2 + A3*Z^3 + ... + AN*Z^N G(Z) = B1*Z + B2*Z^2 + B3*Z^3 + ... + BN*Z^N H(Z) = C1*Z + C2*Z^2 + C3*Z^3 + ... + CN*Z^N Licensing: This code is distributed under the MIT license. Modified: 27 March 2009 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the number of terms in the power series. Input, double A[N], the power series for F. For this problem, A(1) may not be 0.0. Input, double B(N), the power series for G. Output, double C(N), the power series for H. */ { int i; int l; int m; double s; double t; double *work; if ( a[0] == 0.0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "POWER_SERIES4(): Fatal error!\n" ); fprintf ( stderr, " First entry of A is zero.\n" ); exit ( 1 ); } work = ( double * ) malloc ( n * sizeof ( double ) ); t = 1.0; for ( i = 0; i < n; i++ ) { t = t / a[0]; c[i] = b[i] * t; work[i] = a[i] * t; } for ( m = 2; m <= n; m++ ) { s = -work[m-1]; for ( i = m; i <= n; i++ ) { for ( l = i; l <= n; l++ ) { c[l-1] = c[l-1] + s * c[l-m]; work[l-1] = work[l-1] + s * work[l-m]; } } } free ( work ); return; } /******************************************************************************/ int prime ( int n ) /******************************************************************************/ /* Purpose: prime() returns any of the first PRIME_MAX prime numbers. Discussion: PRIME_MAX is 1600, and the largest prime stored is 13499. Thanks to Bart Vandewoestyne for pointing out a typo, 18 February 2005. Licensing: This code is distributed under the MIT license. Modified: 21 March 2009 Author: John Burkardt Reference: Milton Abramowitz, Irene Stegun, Handbook of Mathematical Functions, US Department of Commerce, 1964, ISBN: 0-486-61272-4, LC: QA47.A34. Daniel Zwillinger, CRC Standard Mathematical Tables and Formulae, 30th Edition, CRC Press, 1996, pages 95-98. Parameters: Input, int N, the index of the desired prime number. In general, is should be true that 0 <= N <= PRIME_MAX. N = -1 returns PRIME_MAX, the index of the largest prime available. N = 0 is legal, returning PRIME = 1. Output, int PRIME, the N-th prime. If N is out of range, PRIME is returned as -1. */ { # define PRIME_MAX 1600 int npvec[PRIME_MAX] = { 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, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117, 8123, 8147, 8161, 8167, 8171, 8179, 8191, 8209, 8219, 8221, 8231, 8233, 8237, 8243, 8263, 8269, 8273, 8287, 8291, 8293, 8297, 8311, 8317, 8329, 8353, 8363, 8369, 8377, 8387, 8389, 8419, 8423, 8429, 8431, 8443, 8447, 8461, 8467, 8501, 8513, 8521, 8527, 8537, 8539, 8543, 8563, 8573, 8581, 8597, 8599, 8609, 8623, 8627, 8629, 8641, 8647, 8663, 8669, 8677, 8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737, 8741, 8747, 8753, 8761, 8779, 8783, 8803, 8807, 8819, 8821, 8831, 8837, 8839, 8849, 8861, 8863, 8867, 8887, 8893, 8923, 8929, 8933, 8941, 8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011, 9013, 9029, 9041, 9043, 9049, 9059, 9067, 9091, 9103, 9109, 9127, 9133, 9137, 9151, 9157, 9161, 9173, 9181, 9187, 9199, 9203, 9209, 9221, 9227, 9239, 9241, 9257, 9277, 9281, 9283, 9293, 9311, 9319, 9323, 9337, 9341, 9343, 9349, 9371, 9377, 9391, 9397, 9403, 9413, 9419, 9421, 9431, 9433, 9437, 9439, 9461, 9463, 9467, 9473, 9479, 9491, 9497, 9511, 9521, 9533, 9539, 9547, 9551, 9587, 9601, 9613, 9619, 9623, 9629, 9631, 9643, 9649, 9661, 9677, 9679, 9689, 9697, 9719, 9721, 9733, 9739, 9743, 9749, 9767, 9769, 9781, 9787, 9791, 9803, 9811, 9817, 9829, 9833, 9839, 9851, 9857, 9859, 9871, 9883, 9887, 9901, 9907, 9923, 9929, 9931, 9941, 9949, 9967, 9973,10007, 10009,10037,10039,10061,10067,10069,10079,10091,10093,10099, 10103,10111,10133,10139,10141,10151,10159,10163,10169,10177, 10181,10193,10211,10223,10243,10247,10253,10259,10267,10271, 10273,10289,10301,10303,10313,10321,10331,10333,10337,10343, 10357,10369,10391,10399,10427,10429,10433,10453,10457,10459, 10463,10477,10487,10499,10501,10513,10529,10531,10559,10567, 10589,10597,10601,10607,10613,10627,10631,10639,10651,10657, 10663,10667,10687,10691,10709,10711,10723,10729,10733,10739, 10753,10771,10781,10789,10799,10831,10837,10847,10853,10859, 10861,10867,10883,10889,10891,10903,10909,10937,10939,10949, 10957,10973,10979,10987,10993,11003,11027,11047,11057,11059, 11069,11071,11083,11087,11093,11113,11117,11119,11131,11149, 11159,11161,11171,11173,11177,11197,11213,11239,11243,11251, 11257,11261,11273,11279,11287,11299,11311,11317,11321,11329, 11351,11353,11369,11383,11393,11399,11411,11423,11437,11443, 11447,11467,11471,11483,11489,11491,11497,11503,11519,11527, 11549,11551,11579,11587,11593,11597,11617,11621,11633,11657, 11677,11681,11689,11699,11701,11717,11719,11731,11743,11777, 11779,11783,11789,11801,11807,11813,11821,11827,11831,11833, 11839,11863,11867,11887,11897,11903,11909,11923,11927,11933, 11939,11941,11953,11959,11969,11971,11981,11987,12007,12011, 12037,12041,12043,12049,12071,12073,12097,12101,12107,12109, 12113,12119,12143,12149,12157,12161,12163,12197,12203,12211, 12227,12239,12241,12251,12253,12263,12269,12277,12281,12289, 12301,12323,12329,12343,12347,12373,12377,12379,12391,12401, 12409,12413,12421,12433,12437,12451,12457,12473,12479,12487, 12491,12497,12503,12511,12517,12527,12539,12541,12547,12553, 12569,12577,12583,12589,12601,12611,12613,12619,12637,12641, 12647,12653,12659,12671,12689,12697,12703,12713,12721,12739, 12743,12757,12763,12781,12791,12799,12809,12821,12823,12829, 12841,12853,12889,12893,12899,12907,12911,12917,12919,12923, 12941,12953,12959,12967,12973,12979,12983,13001,13003,13007, 13009,13033,13037,13043,13049,13063,13093,13099,13103,13109, 13121,13127,13147,13151,13159,13163,13171,13177,13183,13187, 13217,13219,13229,13241,13249,13259,13267,13291,13297,13309, 13313,13327,13331,13337,13339,13367,13381,13397,13399,13411, 13417,13421,13441,13451,13457,13463,13469,13477,13487,13499 }; if ( n == -1 ) { return PRIME_MAX; } else if ( n == 0 ) { return 1; } else if ( n <= PRIME_MAX ) { return npvec[n-1]; } else { fprintf ( stderr, "\n" ); fprintf ( stderr, "PRIME(): Fatal error!\n" ); fprintf ( stderr, " Unexpected input value of n = %d\n", n ); exit ( 1 ); } return 0; # undef PRIME_MAX } /******************************************************************************/ void pythag_triple_next ( int *i, int *j, int *a, int *b, int *c ) /******************************************************************************/ /* Purpose: pythag_triple_next() computes the next Pythagorean triple. Example: I J A B C A^2+B^2 = C^2 2 1 3 4 5 25 3 2 5 12 13 169 4 1 15 8 17 289 4 3 7 24 25 625 5 2 21 20 29 841 5 4 9 40 41 1681 6 1 35 12 37 1369 6 3 27 36 45 2025 6 5 11 60 61 3721 7 2 45 28 53 2809 Licensing: This code is distributed under the MIT license. Modified: 27 March 2009 Author: John Burkardt Parameters: Input/output, int *I, *J, the generators. On first call, set I = J = 0. On repeated calls, leave I and J at their output values from the previous call. Output, int *A, *B, *C, the next Pythagorean triple. A, B, and C are positive integers which have no common factors, and A^2 + B^2 = C^2. */ { /* I starts at 2 and increases; J starts out at 2 if I is odd, or 1 if I is even, increases by 2, but is always less than I. */ if ( (*i) == 0 && (*j) == 0 ) { (*i) = 2; (*j) = 1; } else if ( (*j) + 2 < (*i) ) { (*j) = (*j) + 2; } else { (*i) = (*i) + 1; *j = ( (*i) % 2 ) + 1; } *a = (*i) * (*i) - (*j) * (*j); *b = 2 * (*i) * (*j); *c = (*i) * (*i) + (*j) * (*j); return; } /******************************************************************************/ double r8_agm ( double a, double b ) /******************************************************************************/ /* Purpose: r8_agm() finds the arithmetic-geometric mean of two R8's. Discussion: The AGM of (A,B) is produced by the following iteration: (A,B) -> ( (A+B)/2, SQRT(A*B) ). The sequence of successive values of (A,B) quickly converge to the AGM. Licensing: This code is distributed under the MIT license. Modified: 06 May 2003 Author: John Burkardt Parameters: Input, double A, B, the numbers whose AGM is desired. A and B should both be non-negative. Output, double R8_AGM, the AGM of the two numbers. */ { double a1; double a2; double b1; double b2; double tol; if ( a < 0.0 ) { return -1.0; } if ( b < 0.0 ) { return -1.0; } if ( a == 0.0 || b == 0.0 ) { return 0.0; } if ( a == b ) { return a; } tol = DBL_EPSILON * ( a + b + 1.0 ); a1 = a; b1 = b; for ( ; ; ) { a2 = ( a1 + b1 ) / 2.0; b2 = sqrt ( a1 * b1 ); if ( fabs ( a2 - b2 ) <= tol ) { return ( ( a2 + b2 ) / 2.0 ); } a1 = a2; b1 = b2; } } /******************************************************************************/ double r8_choose ( int n, int k ) /******************************************************************************/ /* Purpose: r8_choose() computes the combinatorial coefficient C(N,K). Discussion: Real arithmetic is used, and C(N,K) is computed directly, via Gamma functions, rather than recursively. C(N,K) is the number of distinct combinations of K objects chosen from a set of N distinct objects. A combination is like a set, in that order does not matter. The formula is: C(N,K) = N! / ( (N-K)! * K! ) Example: The number of combinations of 2 things chosen from 5 is 10. C(5,2) = ( 5 * 4 * 3 * 2 * 1 ) / ( ( 3 * 2 * 1 ) * ( 2 * 1 ) ) = 10. The actual combinations may be represented as: (1,2), (1,3), (1,4), (1,5), (2,3), (2,4), (2,5), (3,4), (3,5), (4,5). Licensing: This code is distributed under the MIT license. Modified: 22 March 2009 Author: John Burkardt Parameters: Input, int N, the value of N. Input, int K, the value of K. Output, double R8_CHOOSE, the value of C(N,K) */ { double arg; double fack; double facn; double facnmk; double value; if ( n < 0 ) { value = 0.0; } else if ( k == 0 ) { value = 1.0; } else if ( k == 1 ) { value = ( double ) n; } else if ( 1 < k && k < n-1 ) { arg = ( double ) ( n + 1 ); facn = lgamma ( arg ); arg = ( double ) ( k + 1 ); fack = lgamma ( arg ); arg = ( double ) ( n - k + 1 ); facnmk = lgamma ( arg ); value = ( int ) ( 0.5 + exp ( facn - fack - facnmk ) ); } else if ( k == n-1 ) { value = ( double ) n; } else if ( k == n ) { value = 1.0; } else { value = 0.0; } return value; } /******************************************************************************/ double r8_factorial ( int n ) /******************************************************************************/ /* Purpose: r8_factorial() computes the factorial of N. Discussion: factorial ( N ) = product ( 1 <= I <= N ) I Licensing: This code is distributed under the MIT license. Modified: 23 March 2009 Author: John Burkardt Parameters: Input, int N, the argument of the factorial function. If N is less than 1, the function value is returned as 1. Output, double R8_FACTORIAL, the factorial of N. */ { int i; double value; value = 1.0; for ( i = 1; i <= n; i++ ) { value = value * ( double ) ( i ); } return value; } /******************************************************************************/ double r8_fall ( double x, int n ) /******************************************************************************/ /* Purpose: r8_fall() computes the falling factorial function [X]_N. Discussion: Note that the number of "injections" or 1-to-1 mappings from a set of N elements to a set of M elements is [M]_N. The number of permutations of N objects out of M is [M]_N. Moreover, the Stirling numbers of the first kind can be used to convert a falling factorial into a polynomial, as follows: [X]_N = S^0_N + S^1_N * X + S^2_N * X^2 + ... + S^N_N X^N. Formula: [X]_N = X * ( X - 1 ) * ( X - 2 ) * ... * ( X - N + 1 ). Licensing: This code is distributed under the MIT license. Modified: 08 May 2003 Author: John Burkardt Parameters: Input, double X, the argument of the falling factorial function. Input, int N, the order of the falling factorial function. If N = 0, FALL = 1, if N = 1, FALL = X. Note that if N is negative, a "rising" factorial will be computed. Output, double R8_FALL, the value of the falling factorial function. */ { int i; double value; value = 1.0; if ( 0 < n ) { for ( i = 1; i <= n; i++ ) { value = value * x; x = x - 1.0; } } else if ( n < 0 ) { for ( i = -1; n <= i; i-- ) { value = value * x; x = x + 1.0; } } return value; } /******************************************************************************/ void r8_fall_values ( int *n_data, double *x, int *n, double *f ) /******************************************************************************/ /* Purpose: r8_fall_values() returns some values of the falling factorial function. Discussion: In Mathematica, the function can be evaluated by: FactorialPower[X,N] Licensing: This code is distributed under the MIT license. Modified: 19 December 2014 Author: John Burkardt Reference: Milton Abramowitz, Irene Stegun, Handbook of Mathematical Functions, National Bureau of Standards, 1964, ISBN: 0-486-61272-4, LC: QA47.A34. Stephen Wolfram, The Mathematica Book, Fourth Edition, Cambridge University Press, 1999, ISBN: 0-521-64314-7, LC: QA76.95.W65. Parameters: Input, int *N_DATA. The user sets N_DATA to 0 before the first call. Output, int *N_DATA. On each call, the routine increments N_DATA by 1, and returns the corresponding data; when there is no more data, the output value of N_DATA will be 0 again. Output, double *X, int *N, the arguments of the function. Output, double *F, the value of the function. */ { # define N_MAX 15 const double f_vec[N_MAX] = { 120.0000000000000, 163.1601562500000, 216.5625000000000, 281.6601562500000, 360.0000000000000, 1.000000000000000, 7.500000000000000, 48.75000000000000, 268.1250000000000, 1206.562500000000, 4222.968750000000, 10557.42187500000, 15836.13281250000, 7918.066406250000, -3959.03320312500 }; const int n_vec[N_MAX] = { 4, 4, 4, 4, 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; const double x_vec[N_MAX] = { 5.00, 5.25, 5.50, 5.75, 6.00, 7.50, 7.50, 7.50, 7.50, 7.50, 7.50, 7.50, 7.50, 7.50, 7.50 }; if ( *n_data < 0 ) { *n_data = 0; } *n_data = *n_data + 1; if ( N_MAX < *n_data ) { *n_data = 0; *x = 0.0; *n = 0; *f = 0.0; } else { *x = x_vec[*n_data-1]; *n = n_vec[*n_data-1]; *f = f_vec[*n_data-1]; } return; # undef N_MAX } /******************************************************************************/ int r8_nint ( double x ) /******************************************************************************/ /* Purpose: r8_nint() returns the nearest integer to an R8. Example: X R8_NINT 1.3 1 1.4 1 1.5 1 or 2 1.6 2 0.0 0 -0.7 -1 -1.1 -1 -1.6 -2 Licensing: This code is distributed under the MIT license. Modified: 05 May 2006 Author: John Burkardt Parameters: Input, double X, the value. Output, int R8_NINT, the nearest integer to X. */ { int s; int value; if ( x < 0.0 ) { s = -1; } else { s = 1; } value = s * ( int ) ( fabs ( x ) + 0.5 ); return value; } /******************************************************************************/ double r8_pi ( ) /******************************************************************************/ /* Purpose: r8_pi() returns the value of PI. Licensing: This code is distributed under the MIT license. Modified: 08 May 2003 Author: John Burkardt Parameters: Output, double R8_PI, the value of PI. */ { return ( double ) 3.14159265358979323846264338327950288419716939937510; } /******************************************************************************/ double r8_rise ( double x, int n ) /******************************************************************************/ /* Purpose: r8_rise() computes the rising factorial function [X]^N. Discussion: [X}^N = X * ( X + 1 ) * ( X + 2 ) * ... * ( X + N - 1 ). Note that the number of ways of arranging N objects in M ordered boxes is [M}^N. (Here, the ordering in each box matters). Thus, 2 objects in 2 boxes have the following 6 possible arrangements: -/12, 1/2, 12/-, -/21, 2/1, 21/-. Moreover, the number of non-decreasing maps from a set of N to a set of M ordered elements is [M]^N / N!. Thus the set of nondecreasing maps from (1,2,3) to (a,b,c,d) is the 20 elements: aaa, abb, acc, add, aab, abc, acd, aac, abd, aad bbb, bcc, bdd, bbc, bcd, bbd, ccc, cdd, ccd, ddd. Licensing: This code is distributed under the MIT license. Modified: 08 May 2003 Author: John Burkardt Parameters: Input, double X, the argument of the rising factorial function. Input, int N, the order of the rising factorial function. If N = 0, RISE = 1, if N = 1, RISE = X. Note that if N is negative, a "falling" factorial will be computed. Output, double R8_RISE, the value of the rising factorial function. */ { int i; double value; value = 1.0; if ( 0 < n ) { for ( i = 1; i <= n; i++ ) { value = value * x; x = x + 1.0; } } else if ( n < 0 ) { for ( i = -1; n <= i; i-- ) { value = value * x; x = x - 1.0; } } return value; } /******************************************************************************/ void r8_rise_values ( int *n_data, double *x, int *n, double *f ) /******************************************************************************/ /* Purpose: r8_rise_values() returns some values of the rising factorial function. Discussion: Pochhammer(X,Y) = Gamma(X+Y) / Gamma(X) For integer arguments, Pochhammer(M,N) = ( M + N - 1 )! / ( N - 1 )! In Mathematica, the function can be evaluated by: Pochhammer[X,N] Licensing: This code is distributed under the MIT license. Modified: 19 December 2014 Author: John Burkardt Reference: Milton Abramowitz, Irene Stegun, Handbook of Mathematical Functions, National Bureau of Standards, 1964, ISBN: 0-486-61272-4, LC: QA47.A34. Stephen Wolfram, The Mathematica Book, Fourth Edition, Cambridge University Press, 1999, ISBN: 0-521-64314-7, LC: QA76.95.W65. Parameters: Input, int *N_DATA. The user sets N_DATA to 0 before the first call. Output, int *N_DATA. On each call, the routine increments N_DATA by 1, and returns the corresponding data; when there is no more data, the output value of N_DATA will be 0 again. Output, double *X, int *N, the arguments of the function. Output, double *F, the value of the function. */ { # define N_MAX 15 const double f_vec[N_MAX] = { 1680.000000000000, 1962.597656250000, 2279.062500000000, 2631.972656250000, 3024.000000000000, 1.000000000000000, 7.500000000000000, 63.75000000000000, 605.6250000000000, 6359.062500000000, 73129.21875000000, 914115.2343750000, 1.234055566406250E+07, 1.789380571289063E+08, 2.773539885498047E+09 }; const int n_vec[N_MAX] = { 4, 4, 4, 4, 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; const double x_vec[N_MAX] = { 5.00, 5.25, 5.50, 5.75, 6.00, 7.50, 7.50, 7.50, 7.50, 7.50, 7.50, 7.50, 7.50, 7.50, 7.50 }; if ( *n_data < 0 ) { *n_data = 0; } *n_data = *n_data + 1; if ( N_MAX < *n_data ) { *n_data = 0; *x = 0.0; *n = 0; *f = 0.0; } else { *x = x_vec[*n_data-1]; *n = n_vec[*n_data-1]; *f = f_vec[*n_data-1]; } return; # undef N_MAX } /******************************************************************************/ void r8_swap ( double *x, double *y ) /******************************************************************************/ /* Purpose: r8_swap() switches two R8's. Licensing: This code is distributed under the MIT license. Modified: 29 May 2003 Author: John Burkardt Parameters: Input/output, double *X, *Y. On output, the values of X and Y have been interchanged. */ { double z; z = *x; *x = *y; *y = z; return; } /******************************************************************************/ void r8_to_cfrac ( double r, int n, int a[], int p[], int q[] ) /******************************************************************************/ /* Purpose: r8_to_cfrac() converts a double value to a continued fraction. Discussion: The routine is given a double number R. It computes a sequence of continued fraction approximations to R, returning the results as simple fractions of the form P(I) / Q(I). Example: X = 2 * PI N = 7 A = [ *, 6, 3, 1, 1, 7, 2, 146, 3 ] P = [ 1, 6, 19, 25, 44, 333, 710, 103993, 312689 ] Q = [ 0, 1, 3, 4, 7, 53, 113, 16551, 49766 ] (This ignores roundoff error, which will cause later terms to differ). Licensing: This code is distributed under the MIT license. Modified: 23 March 2009 Author: John Burkardt Reference: Norman Richert, Strang's Strange Figures, American Mathematical Monthly, Volume 99, Number 2, February 1992, pages 101-107. Parameters: Input, double R, the double value. Input, int N, the number of convergents to compute. Output, int A[N+1], the partial quotients. Output, int P[N+2], Q[N+2], the numerators and denominators of the continued fraction approximations. */ { int i; double r_copy; double *x; for ( i = 0; i <= n; i++ ) { a[i] = 0; } for ( i = 0; i <= n + 1; i++ ) { p[i] = 0; } for ( i = 0; i <= n + 1; i++ ) { q[i] = 0; } if ( r == 0.0 ) { return; } x = ( double * ) malloc ( ( n + 1 ) * sizeof ( double ) ); r_copy = fabs ( r ); p[0] = 1; q[0] = 0; p[1] = ( int ) r_copy; q[1] = 1; x[0] = r_copy; a[0] = ( int ) x[0]; for ( i = 1; i <= n; i++ ) { x[i] = 1.0 / ( x[i-1] - ( double ) a[i-1] ); a[i] = ( int ) x[i]; p[i+1] = a[i] * p[i] + p[i-1]; q[i+1] = a[i] * q[i] + q[i-1]; } if ( r < 0.0 ) { for ( i = 0; i <= n + 1; i++ ) { p[i] = - p[i]; } } free ( x ); return; } /******************************************************************************/ void r8_to_dec ( double dval, int dec_digit, int *mantissa, int *exponent ) /******************************************************************************/ /* Purpose: r8_to_dec() converts a double quantity to a decimal representation. Discussion: Given the double value DVAL, the routine computes integers MANTISSA and EXPONENT so that it is approximately true that: DVAL = MANTISSA * 10 ^ EXPONENT In particular, only DEC_DIGIT digits of DVAL are used in constructing the representation. Licensing: This code is distributed under the MIT license. Modified: 22 March 2009 Author: John Burkardt Parameters: Input, double DVAL, the value whose decimal representation is desired. Input, int DEC_DIGIT, the number of decimal digits to use. Output, int *MANTISSA, *EXPONENT, the approximate decimal representation of DVAL. */ { double mantissa_double; double ten1; double ten2; /* Special cases. */ if ( dval == 0.0 ) { *mantissa = 0; *exponent = 0; return; } /* Factor DVAL = MANTISSA_DOUBLE * 10^EXPONENT */ mantissa_double = dval; *exponent = 0; /* Now normalize so that 10^(DEC_DIGIT-1) <= ABS(MANTISSA_DOUBLE) < 10^(DEC_DIGIT) */ ten1 = pow ( 10.0, dec_digit - 1 ); ten2 = 10.0 * ten1; while ( fabs ( mantissa_double ) < ten1 ) { mantissa_double = mantissa_double * 10.0; *exponent = *exponent - 1; } while ( ten2 <= fabs ( mantissa_double ) ) { mantissa_double = mantissa_double / 10.0; *exponent = *exponent + 1; } /* MANTISSA is the integer part of MANTISSA_DOUBLE, rounded. */ *mantissa = r8_nint ( mantissa_double ); /* Now divide out any factors of ten from MANTISSA. */ if ( *mantissa != 0 ) { while ( 10 * ( *mantissa / 10 ) == *mantissa ) { *mantissa = *mantissa / 10; *exponent = *exponent + 1; } } return; } /******************************************************************************/ void r8_to_rat ( double a, int ndig, int *iatop, int *iabot ) /******************************************************************************/ /* Purpose: r8_to_rat() converts a real value to a rational value. Discussion: The rational value (IATOP/IABOT) is essentially computed by truncating the decimal representation of the real value after a given number of decimal digits. Licensing: This code is distributed under the MIT license. Modified: 23 March 2009 Author: John Burkardt Parameters: Input, double A, the real value to be converted. Input, int NDIG, the number of decimal digits used. Output, int *IATOP, *IABOT, the numerator and denominator of the rational value that approximates A. */ { double factor; int i; int itemp; factor = pow ( 10.0, ndig ); if ( 0 < ndig ) { *iabot = 1; for ( i = 1; i <= ndig; i++ ) { *iabot = *iabot * 10; } *iatop = 1; } else { *iabot = 1; *iatop = 1; for ( i = 1; i <= -ndig; i++ ) { *iatop = *iatop * 10; } } *iatop = r8_nint ( a * factor ) * (*iatop); *iabot = *iabot; /* Factor out the greatest common factor. */ itemp = i4_gcd ( *iatop, *iabot ); *iatop = *iatop / itemp; *iabot = *iabot / itemp; return; } /******************************************************************************/ double r8_uniform_01 ( int *seed ) /******************************************************************************/ /* Purpose: r8_uniform_01() returns a unit pseudorandom R8. Discussion: This routine implements the recursion seed = 16807 * seed mod ( 2^31 - 1 ) r8_uniform_01 = seed / ( 2^31 - 1 ) The integer arithmetic never requires more than 32 bits, including a sign bit. If the initial seed is 12345, then the first three computations are Input Output R8_UNIFORM_01 SEED SEED 12345 207482415 0.096616 207482415 1790989824 0.833995 1790989824 2035175616 0.947702 Licensing: This code is distributed under the MIT license. Modified: 11 August 2004 Author: John Burkardt Reference: Paul Bratley, Bennett Fox, Linus Schrage, A Guide to Simulation, Springer Verlag, pages 201-202, 1983. Pierre L'Ecuyer, Random Number Generation, in Handbook of Simulation edited by Jerry Banks, Wiley Interscience, page 95, 1998. Bennett Fox, Algorithm 647: Implementation and Relative Efficiency of Quasirandom Sequence Generators, ACM Transactions on Mathematical Software, Volume 12, Number 4, pages 362-376, 1986. P A Lewis, A S Goodman, J M Miller, A Pseudo-Random Number Generator for the System/360, IBM Systems Journal, Volume 8, pages 136-143, 1969. Parameters: Input/output, int *SEED, the "seed" value. Normally, this value should not be 0. On output, SEED has been updated. Output, double R8_UNIFORM_01, a new pseudorandom variate, strictly between 0 and 1. */ { int k; double r; k = *seed / 127773; *seed = 16807 * ( *seed - k * 127773 ) - k * 2836; if ( *seed < 0 ) { *seed = *seed + 2147483647; } /* Although SEED can be represented exactly as a 32 bit integer, it generally cannot be represented exactly as a 32 bit real number! */ r = ( ( double ) ( *seed ) ) * 4.656612875E-10; return r; } /******************************************************************************/ double r8_uniform_ab ( double a, double b, int *seed ) /******************************************************************************/ /* Purpose: r8_uniform_ab() returns a pseudorandom R8 scaled to [A,B]. Licensing: This code is distributed under the MIT license. Modified: 21 November 2004 Author: John Burkardt Parameters: Input, double A, B, the limits of the interval. Input/output, int *SEED, the "seed" value, which should NOT be 0. On output, SEED has been updated. Output, double R8_UNIFORM_AB, a number strictly between A and B. */ { const int i4_huge = 2147483647; int k; double r; double value; k = *seed / 127773; *seed = 16807 * ( *seed - k * 127773 ) - k * 2836; if ( *seed < 0 ) { *seed = *seed + i4_huge; } r = ( ( double ) ( *seed ) ) * 4.656612875E-10; value = a + ( b - a ) * r; return value; } /******************************************************************************/ double r8mat_det ( int n, double a[] ) /******************************************************************************/ /* Purpose: r8mat_det() finds the determinant of a real N by N matrix. Discussion: A brute force calculation is made. This routine should only be used for small matrices, since this calculation requires the summation of N! products of N numbers. Licensing: This code is distributed under the MIT license. Modified: 27 March 2009 Author: John Burkardt Parameters: Input, int N, the number of rows and columns of A. Input, double A[N*N], the matrix whose determinant is desired. Output, double R8MAT_DET, the determinant of the matrix. */ { double det; int even; int i; int more; int *perm; double term; more = 0; det = 0.0; perm = ( int * ) malloc ( n * sizeof ( int ) ); for ( ; ; ) { perm0_next ( n, perm, &more, &even ); if ( even ) { term = 1.0; } else { term = -1.0; } for ( i = 0; i < n; i++ ) { term = term * a[i+perm[i]*n]; } det = det + term; if ( !more ) { break; } } free ( perm ); return det; } /******************************************************************************/ void r8mat_perm0 ( int n, double a[], int p[] ) /******************************************************************************/ /* Purpose: r8mat_perm0() permutes the rows and columns of a square R8MAT. Licensing: This code is distributed under the MIT license. Modified: 27 March 2009 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the order of the matrix. Input/output, double A[N*N]. On input, the matrix to be permuted. On output, the permuted matrix. Input, int P[N], a permutation to be applied to the rows and columns. P[I] is the new number of row and column I. */ { int i; int i1; int iopt = 1; int isgn; double it; int j; int j1; int j2; int k; int lc; int ncycle; double temp; perm0_cycle ( n, p, &isgn, &ncycle, iopt ); /* Temporarily increment P by 1. */ for ( i = 0; i < n; i++ ) { p[i] = p[i] + 1; } for ( i = 1; i <= n; i++ ) { i1 = - p[i-1]; if ( 0 < i1 ) { lc = 0; for ( ; ; ) { i1 = p[i1-1]; lc = lc + 1; if ( i1 <= 0 ) { break; } } i1 = i; for ( j = 1; j <= n; j++ ) { if ( p[j-1] <= 0 ) { j2 = j; k = lc; for ( ; ; ) { j1 = j2; it = a[i1-1+(j1-1)*n]; for ( ; ; ) { i1 = abs ( p[i1-1] ); j1 = abs ( p[j1-1] ); temp = a[i1-1+(j1-1)*n]; a[i1-1+(j1-1)*n] = it; it = temp; if ( j1 != j2 ) { continue; } k = k - 1; if ( i1 == i ) { break; } } j2 = abs ( p[j2-1] ); if ( k == 0 ) { break; } } } } } } /* Restore the positive signs of the data. */ for ( i = 0; i < n; i++ ) { p[i] = abs ( p[i] ); } for ( i = 0; i < n; i++ ) { p[i] = p[i] - 1; } return; } /******************************************************************************/ void r8mat_2perm0 ( int m, int n, double a[], int p[], int q[] ) /******************************************************************************/ /* Purpose: r8mat_2perm0() permutes rows and columns of a rectangular R8MAT, in place. Licensing: This code is distributed under the MIT license. Modified: 27 March 2009 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int M, number of rows in the matrix. Input, int N, number of columns in the matrix. Input/output, double A[M*N]. On input, the matrix to be permuted. On output, the permuted matrix. Input, int P[M], the row permutation. P(I) is the new number of row I. Input, int Q[N], the column permutation. Q(I) is the new number of column I. */ { int i; int i1; int is; int j; int j1; int j2; int k; int lc; int nc; int *p1; int *q1; double t; double temp; /* Wretched maneuvers to deal with necessity of 1-based values, and to handle case where P and Q are same vector. */ p1 = i4vec_copy_new ( m, p ); perm0_cycle ( m, p1, &is, &nc, 1 ); for ( i = 0; i < m; i++ ) { p1[i] = p1[i] + 1; } q1 = i4vec_copy_new ( n, q ); perm0_cycle ( n, q1, &is, &nc, 1 ); for ( j = 0; j < n; j++ ) { q1[j] = q1[j] + 1; } for ( i = 1; i <= m; i++ ) { i1 = - p[i-1]; if ( 0 < i1 ) { lc = 0; for ( ; ; ) { i1 = p[i1-1]; lc = lc + 1; if ( i1 <= 0 ) { break; } } i1 = i; for ( j = 1; j <= n; j++ ) { if ( q[j-1] <= 0 ) { j2 = j; k = lc; for ( ; ; ) { j1 = j2; t = a[i1-1+(j1-1)*n]; for ( ; ; ) { i1 = abs ( p[i1-1] ); j1 = abs ( q[j1-1] ); temp = a[i1-1+(j1-1)*n]; a[i1-1+(j1-1)*n] = t; t = temp; if ( j1 != j2 ) { continue; } k = k - 1; if ( i1 == i ) { break; } } j2 = abs ( q[j2-1] ); if ( k == 0 ) { break; } } } } } } free ( p1 ); free ( q1 ); return; } /******************************************************************************/ double r8mat_permanent ( int n, double a[] ) /******************************************************************************/ /* Purpose: r8mat_permanent() computes the permanent of an R8MAT. Discussion: The permanent function is similar to the determinant. Recall that the determinant of a matrix may be defined as the sum of all the products: S * A(1,I(1)) * A(2,I(2)) * ... * A(N,I(N)) where I is any permutation of the columns of the matrix, and S is the sign of the permutation. By contrast, the permanent function is the (unsigned) sum of all the products A(1,I(1)) * A(2,I(2)) * ... * A(N,I(N)) where I is any permutation of the columns of the matrix. The only difference is that there is no permutation sign multiplying each summand. Symbolically, then, the determinant of a 2 by 2 matrix a b c d is a*d-b*c, whereas the permanent of the same matrix is a*d+b*c. The permanent is invariant under row and column permutations. If a row or column of the matrix is multiplied by S, then the permanent is likewise multiplied by S. If the matrix is square, then the permanent is unaffected by transposing the matrix. Unlike the determinant, however, the permanent does change if one row is added to another, and it is not 1 that the permanent of the product is the product of the permanents. Note that if A is a matrix of all 1's and 0's, then the permanent of A counts exactly which permutations hit exactly 1's in the matrix. This fact can be exploited for various combinatorial calculations. For instance, setting the diagonal of A to 0, and the offdiagonals to 1, the permanent of A counts the number of derangements of N objects. Licensing: This code is distributed under the MIT license. Modified: 27 March 2009 Author: John Burkardt Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, number of rows and columns in matrix. Input, double A[N*N], the matrix whose permanent is desired. Output, double R8MAT_PERMANENT, the value of the permanent of A. */ { int i; int iadd; int *iwork; int j; int more; int ncard; double p; double perm; double prod; double sgn; double *work; double z; more = 0; iwork = ( int * ) malloc ( n * sizeof ( int ) ); work = ( double * ) malloc ( n * sizeof ( double ) ); for ( i = 1; i <= n; i++ ) { work[i-1] = a[i-1+(n-1)*n]; for ( j = 1; j <= n; j++ ) { work[i-1] = work[i-1] - 0.5 * a[i-1+(j-1)*n]; } } p = 0.0; sgn = -1.0; for ( ; ; ) { sgn = -sgn; subset_gray_next ( n-1, iwork, &more, &ncard, &iadd ); if ( ncard != 0 ) { z = ( double ) ( 2 * iwork[iadd-1] - 1 ); for ( i = 1; i <= n; i++ ) { work[i-1] = work[i-1] + z * a[i-1+(iadd-1)*n]; } } prod = 1.0; for ( i = 0; i < n; i++ ) { prod = prod * work[i]; } p = p + sgn * prod; if ( !more ) { break; } } free ( iwork ); free ( work ); perm = p * ( double ) ( 4 * ( n % 2 ) - 2 ); return perm; } /******************************************************************************/ void r8mat_print ( int m, int n, double a[], char *title ) /******************************************************************************/ /* Purpose: r8mat_print() prints an R8MAT, with an optional title. Discussion: An R8MAT is a doubly dimensioned array of double precision values, which may be stored as a vector in column-major order. Entry A(I,J) is stored as A[I+J*M] Licensing: This code is distributed under the MIT license. Modified: 28 May 2008 Author: John Burkardt Parameters: Input, int M, the number of rows in A. Input, int N, the number of columns in A. Input, double A[M*N], the M by N matrix. Input, char *TITLE, a title to be printed. */ { r8mat_print_some ( m, n, a, 1, 1, m, n, title ); return; } /******************************************************************************/ void r8mat_print_some ( int m, int n, double a[], int ilo, int jlo, int ihi, int jhi, char *title ) /******************************************************************************/ /* Purpose: r8mat_print_some() prints some of an R8MAT. Discussion: An R8MAT is a doubly dimensioned array of double precision values, which may be stored as a vector in column-major order. Licensing: This code is distributed under the MIT license. Modified: 28 May 2008 Author: John Burkardt Parameters: Input, int M, the number of rows of the matrix. M must be positive. Input, int N, the number of columns of the matrix. N must be positive. Input, double A[M*N], the matrix. Input, int ILO, JLO, IHI, JHI, designate the first row and column, and the last row and column to be printed. Input, char *TITLE, a title for the matrix. */ { # define INCX 5 int i; int i2hi; int i2lo; int j; int j2hi; int j2lo; if ( 0 < s_len_trim ( title ) ) { printf ( "\n" ); printf ( "%s\n", title ); } /* Print the columns of the matrix, in strips of 5. */ for ( j2lo = jlo; j2lo <= jhi; j2lo = j2lo + INCX ) { j2hi = j2lo + INCX - 1; j2hi = i4_min ( j2hi, n ); j2hi = i4_min ( j2hi, jhi ); printf ( "\n" ); /* For each column J in the current range... Write the header. */ printf ( " Col: "); for ( j = j2lo; j <= j2hi; j++ ) { printf ( " %7d ", j ); } printf ( "\n" ); printf ( " Row\n" ); printf ( "\n" ); /* Determine the range of the rows in this strip. */ i2lo = i4_max ( ilo, 1 ); i2hi = i4_min ( ihi, m ); for ( i = i2lo; i <= i2hi; i++ ) { /* Print out (up to) 5 entries in row I, that lie in the current strip. */ printf ( "%5d", i ); for ( j = j2lo; j <= j2hi; j++ ) { printf ( " %14f", a[i-1+(j-1)*m] ); } printf ( "\n" ); } } printf ( "\n" ); return; # undef INCX } /******************************************************************************/ void r8mat_transpose_print ( int m, int n, double a[], char *title ) /******************************************************************************/ /* Purpose: r8mat_transpose_print() prints an R8MAT, transposed. Licensing: This code is distributed under the MIT license. Modified: 28 May 2008 Author: John Burkardt Parameters: Input, int M, N, the number of rows and columns. Input, double A[M*N], an M by N matrix to be printed. Input, char *TITLE, an optional title. */ { r8mat_transpose_print_some ( m, n, a, 1, 1, m, n, title ); return; } /******************************************************************************/ void r8mat_transpose_print_some ( int m, int n, double a[], int ilo, int jlo, int ihi, int jhi, char *title ) /******************************************************************************/ /* Purpose: r8mat_transpose_print_some() prints some of an R8MAT, transposed. Licensing: This code is distributed under the MIT license. Modified: 28 May 2008 Author: John Burkardt Parameters: Input, int M, N, the number of rows and columns. Input, double A[M*N], an M by N matrix to be printed. Input, int ILO, JLO, the first row and column to print. Input, int IHI, JHI, the last row and column to print. Input, char *TITLE, an optional title. */ { # define INCX 5 int i; int i2; int i2hi; int i2lo; int inc; int j; int j2hi; int j2lo; if ( 0 < s_len_trim ( title ) ) { printf ( "\n" ); printf ( "%s\n", title ); } for ( i2lo = i4_max ( ilo, 1 ); i2lo <= i4_min ( ihi, m ); i2lo = i2lo + INCX ) { i2hi = i2lo + INCX - 1; i2hi = i4_min ( i2hi, m ); i2hi = i4_min ( i2hi, ihi ); inc = i2hi + 1 - i2lo; printf ( "\n" ); printf ( " Row:" ); for ( i = i2lo; i <= i2hi; i++ ) { printf ( " %7d ", i ); } printf ( "\n" ); printf ( " Col\n" ); printf ( "\n" ); j2lo = i4_max ( jlo, 1 ); j2hi = i4_min ( jhi, n ); for ( j = j2lo; j <= j2hi; j++ ) { printf ( "%5d", j ); for ( i2 = 1; i2 <= inc; i2++ ) { i = i2lo - 1 + i2; printf ( " %14f", a[(i-1)+(j-1)*m] ); } printf ( "\n" ); } } printf ( "\n" ); return; # undef INCX } /******************************************************************************/ void r8poly ( int n, double a[], double x0, int iopt, double *val ) /******************************************************************************/ /* Purpose: r8poly() performs operations on R8POLY's in power or factorial form. Discussion: The power sum form of a polynomial is P(X) = A1 + A2*X + A3*X^2 + ... + (AN+1)*X^N The Taylor expansion at C has the form P(X) = A1 + A2*(X-C) + A3*(X-C)^2+... + (AN+1)*(X-C)^N The factorial form of a polynomial is P(X) = A1 + A2*X + A3*(X)*(X-1) + A4*(X)*(X-1)*(X-2) + ... + (AN+1)*(X)*(X-1)*...*(X-N+1) Licensing: This code is distributed under the MIT license. Modified: 27 March 2009 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the number of coefficients in the polynomial (in other words, the polynomial degree + 1) Input/output, double A[N], the coefficients of the polynomial. Depending on the option chosen, these coefficients may be overwritten by those of a different form of the polynomial. Input, double X0, for IOPT = -1, 0, or positive, the value of the argument at which the polynomial is to be evaluated, or the Taylor expansion is to be carried out. Input, int IOPT, a flag describing which algorithm is to be carried out: -3: Reverse Stirling. Input the coefficients of the polynomial in factorial form, output them in power sum form. -2: Stirling. Input the coefficients in power sum form, output them in factorial form. -1: Evaluate a polynomial which has been input in factorial form. 0: Evaluate a polynomial input in power sum form. 1 or more: Given the coefficients of a polynomial in power sum form, compute the first IOPT coefficients of the polynomial in Taylor expansion form. Output, double *VAL, for IOPT = -1 or 0, the value of the polynomial at the point X0. */ { double eps; int i; int m; int n1; double w; double z; n1 = i4_min ( n, iopt ); n1 = i4_max ( 1, n1 ); if ( iopt < -1 ) { n1 = n; } eps = ( double ) ( i4_max ( -iopt, 0 ) % 2 ); w = - ( double ) n * eps; if ( -2 < iopt ) { w = w + x0; } for ( m = 1; m <= n1; m++ ) { *val = 0.0; z = w; for ( i = m; i <= n; i++ ) { z = z + eps; *val = a[n+m-i-1] + z * (*val); if ( iopt != 0 && iopt != -1 ) { a[n+m-i-1] = *val; } } if ( iopt < 0 ) { w = w + 1.0; } } return; } /******************************************************************************/ void r8poly_f2p ( int n, double a[] ) /******************************************************************************/ /* Purpose: r8poly_f2p() converts a polynomial from factorial form to power sum form. Discussion: The (falling) factorial form is p(x) = a(1) + a(2) * x + a(3) * x*(x-1) ... + a(n) * x*(x-1)*...*(x-(n-2)) The power sum form is p(x) = a(1) + a(2)*x + a(3)*x^2 + ... + a(n)*x^(n-1) Licensing: This code is distributed under the MIT license. Modified: 28 March 2009 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the dimension of A. Input/output, double A[N], on input, the polynomial coefficients in factorial form. On output, the polynomial coefficients in power sum form. */ { int i; int m; double val; double w; double z; w = - ( double ) n; for ( m = 1; m <= n; m++ ) { val = 0.0; z = w; for ( i = m; i <= n; i++ ) { z = z + 1.0; val = a[n+m-i-1] + z * val; a[n+m-i-1] = val; } w = w + 1.0; } return; } /******************************************************************************/ double r8poly_fval ( int n, double a[], double x ) /******************************************************************************/ /* Purpose: r8poly_fval() evaluates a polynomial in factorial form. Discussion: The (falling) factorial form of a polynomial is: p(x) = a(1) + a(2) *x + a(3) *x*(x-1) +... + a(n-1)*x*(x-1)*(x-2)...*(x-(n-3)) + a(n) *x*(x-1)*(x-2)...*(x-(n-3))*(x-(n-2)) Licensing: This code is distributed under the MIT license. Modified: 28 March 2009 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the dimension of A. Input, double A[N], the coefficients of the polynomial. A(1) is the constant term. Input, double X, the point at which the polynomial is to be evaluated. Output, double R8POLY_FVAL, the value of the polynomial at X. */ { int i; double value; value = 0.0; for ( i = 1; i <= n; i++ ) { value = a[n-i] + ( x - n + i ) * value; } return value; } /******************************************************************************/ void r8poly_n2p ( int n, double a[], double xarray[] ) /******************************************************************************/ /* Purpose: r8poly_n2p() converts a polynomial from Newton form to power sum form. Discussion: This is done by shifting all the Newton abscissas to zero. Actually, what happens is that the abscissas of the Newton form are all shifted to zero, which means that A is the power sum polynomial description and A, XARRAY is the Newton polynomial description. It is only because all the abscissas are shifted to zero that A can be used as both a power sum and Newton polynomial coefficient array. The Newton form of a polynomial is described by an array of N coefficients A and N abscissas X: p(x) = a(1) + a(2) * (x-x(1)) + a(3) * (x-x(1)) * (x-x(2)) ... + a(n) * (x-x(1)) * (x-x(2)) * ... * (x-x(n-1)) X(N) does not occur explicitly in the formula for the evaluation of p(x), although it is used in deriving the coefficients A. The power sum form of a polynomial is: p(x) = a(1) + a(2)*x + ... + a(n-1)*x^(n-2) + a(n)*x^(n-1) Licensing: This code is distributed under the MIT license. Modified: 28 March 2009 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the dimension of A. Input/output, double A[N]. On input, the coefficients of the polynomial in Newton form, and on output, the coefficients in power sum form. Input/output, double XARRAY[N]. On input, the abscissas of the Newton form of the polynomial. On output, these values have all been set to zero. */ { int i; for ( i = 0; i < n; i++ ) { r8poly_nx ( n, a, xarray, 0.0 ); } return; } /******************************************************************************/ double r8poly_nval ( int n, double a[], double xarray[], double x ) /******************************************************************************/ /* Purpose: r8poly_nval() evaluates a polynomial in Newton form. Definition: The Newton form of a polynomial is; p(x) = a(1) + a(2) *(x-x1) + a(3) *(x-x1)*(x-x2) +... + a(n-1)*(x-x1)*(x-x2)*(x-x3)...*(x-x(n-2)) + a(n) *(x-x1)*(x-x2)*(x-x3)...*(x-x(n-2))*(x-x(n-1)) Licensing: This code is distributed under the MIT license. Modified: 28 March 2009 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the dimension of A. Input, double A[N], the coefficients of the polynomial. A(1) is the constant term. Input, double XARRAY[N-1], the N-1 points X which are part of the definition of the polynomial. Input, double X, the point at which the polynomial is to be evaluated. Output, double R8POLY_NVAL, the value of the polynomial at X. */ { int i; double value; value = a[n-1]; for ( i = n-2; 0 <= i; i-- ) { value = a[i] + ( x - xarray[i] ) * value; } return value; } /******************************************************************************/ void r8poly_nx ( int n, double a[], double xarray[], double x ) /******************************************************************************/ /* Purpose: r8poly_nx() replaces one of the base points in a polynomial in Newton form. Discussion: The Newton form of a polynomial is described by an array of N coefficients A and N abscissas X: p(x) = a(1) + a(2) * (x-x(1)) + a(3) * (x-x(1)) * (x-x(2)) ... + a(n) * (x-x(1)) * (x-x(2)) * ... * (x-x(n-1)) X(N) does not occur explicitly in the formula for the evaluation of p(x), although it is used in deriving the coefficients A. Licensing: This code is distributed under the MIT license. Modified: 28 March 2009 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the dimension of A. Input/output, double A[N], the polynomial coefficients of the Newton form. Input/output, double XARRAY[N], the set of abscissas that are part of the Newton form of the polynomial. On output, the abscissas have been shifted up one index, so that the first location now holds X, and the original value of the last entry is discarded. Input, double X, the new point to be shifted into XARRAY. */ { int i; for ( i = n - 2; 0 <= i; i-- ) { a[i] = a[i] + ( x - xarray[i] ) * a[i+1]; } for ( i = n - 1; 0 < i; i-- ) { xarray[i] = xarray[i-1]; } xarray[0] = x; return; } /******************************************************************************/ void r8poly_p2f ( int n, double a[] ) /******************************************************************************/ /* Purpose: r8poly_p2f() converts a polynomial from power sum form to factorial form. Discussion: The power sum form is p(x) = a(1) + a(2)*x + a(3)*x^2 + ... + a(n)*x^(n-1) The (falling) factorial form is p(x) = a(1) + a(2) * x + a(3) * x*(x-1) ... + a(n) * x*(x-1)*...*(x-(n-2)) Licensing: This code is distributed under the MIT license. Modified: 28 March 2009 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the dimension of A. Input/output, double A[N], on input, the polynomial coefficients in the power sum form, on output, the polynomial coefficients in factorial form. */ { int i; int m; double val; for ( m = 1; m <= n; m++ ) { val = 0.0; for ( i = m; i <= n; i++ ) { val = a[n+m-i-1] + ( double ) ( m - 1 ) * val; a[n+m-i-1] = val; } } return; } /******************************************************************************/ void r8poly_p2n ( int n, double a[], double xarray[] ) /******************************************************************************/ /* Purpose: r8poly_p2n() converts a polynomial from power sum form to Newton form. Discussion: This is done by shifting all the Newton abscissas from zero. The power sum form of a polynomial is: p(x) = a(1) + a(2) * x + ... + a(n-1) * x^(n-2) + a(n) * x^(n-1) The Newton form of a polynomial is described by an array of N coefficients A and N abscissas X: p(x) = a(1) + a(2) * (x-x(1)) + a(3) * (x-x(1)) * (x-x(2)) ... + a(n) * (x-x(1)) * (x-x(2)) * ... * (x-x(n-1)) X(N) does not occur explicitly in the formula for the evaluation of p(x), although it is used in deriving the coefficients A. Licensing: This code is distributed under the MIT license. Modified: 28 March 2009 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the dimension of A. Input/output, double A[N]. On input, the coefficients of the polynomial in power sum form, and on output, the coefficients in Newton form. Input, double XARRAY[N]. On input, the desired abscissas of the Newton form of the polynomial. */ { int i; double *work; double x; work = ( double * ) malloc ( n * sizeof ( double ) ); for ( i = 0; i < n; i++ ) { work[i] = 0.0; } for ( i = n - 1; 0 <= i; i-- ) { x = xarray[i]; r8poly_nx ( n, a, work, x ); } free ( work ); return; } /******************************************************************************/ void r8poly_p2t ( int n, double a[], double x ) /******************************************************************************/ /* Purpose: r8poly_p2t() converts a polynomial from power sum form to Taylor form. Discussion: The power sum form is p(x) = a(1) + a(2)*x + a(3)*x^2 + ... + a(n)*x^(n-1) The Taylor form is p(x) = a(1) + a(2) * (x-x0) + a(3) * (x-x0)^2 ... + a(n) * (x-x0)^(n-1) Licensing: This code is distributed under the MIT license. Modified: 28 March 2009 Author: John Burkardt Parameters: Input, int N, the dimension of A. Input/output, double A[N], on input, the coefficients in power sum form, and on output, the coefficients in Taylor form. Input, double X, the point at which the Taylor form of the polynomial is to be based. */ { int i; int m; double val; for ( m = 1; m <= n; m++ ) { val = 0.0; for ( i = m; i <= n; i++ ) { val = a[n+m-i-1] + x * val; a[n+m-i-1] = val; } } return; } /******************************************************************************/ void r8poly_print ( int n, double a[], char *title ) /******************************************************************************/ /* Purpose: r8poly_print() prints out a polynomial. Discussion: The power sum form is: p(x) = a(0) + a(1)*x + ... + a(n-1)*x^(n-1) + a(n)*x^(n) Licensing: This code is distributed under the MIT license. Modified: 28 March 2009 Author: John Burkardt Parameters: Input, int N, the dimension of A. Input, double A[N+1], the polynomial coefficients. A(0) is the constant term and A(N) is the coefficient of X^N. Input, char *TITLE, an optional title. */ { int i; double mag; char plus_minus; if ( 0 < s_len_trim ( title ) ) { printf ( "\n" ); printf ( "%s\n", title ); } printf ( "\n" ); if ( a[n] < 0.0 ) { plus_minus = '-'; } else { plus_minus = ' '; } mag = fabs ( a[n] ); if ( 2 <= n ) { printf ( " p(x) = %c%f * x^%d\n", plus_minus, mag, n ); } else if ( n == 1 ) { printf ( " p(x) = %c%f * x\n", plus_minus, mag ); } else if ( n == 0 ) { printf ( " p(x) = %c%f\n", plus_minus, mag ); } for ( i = n - 1; 0 <= i; i-- ) { if ( a[i] < 0.0 ) { plus_minus = '-'; } else { plus_minus = '+'; } mag = fabs ( a[i] ); if ( mag != 0.0 ) { if ( 2 <= i ) { printf ( " %c%f * x^%d\n", plus_minus, mag, i ); } else if ( i == 1 ) { printf ( " %c%f * x\n", plus_minus, mag ); } else if ( i == 0 ) { printf ( " %c%f\n", plus_minus, mag ); } } } return; } /******************************************************************************/ double r8poly_pval ( int n, double a[], double x ) /******************************************************************************/ /* Purpose: r8poly_pval() evaluates a polynomial in power sum form. Discussion: The power sum form is: p(x) = a(0) + a(1)*x + ... + a(n-1)*x^(n-1) + a(n)*x^(n) Licensing: This code is distributed under the MIT license. Modified: 28 March 2009 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the dimension of A. Input, double A[N+1], the coefficients of the polynomial. A(0) is the constant term. Input, double X, the point at which the polynomial is to be evaluated. Output, double R8POLY_VAL, the value of the polynomial at X. */ { int i; double value; value = 0.0; for ( i = n; 0 <= i; i-- ) { value = value * x + a[i]; } return value; } /******************************************************************************/ void r8poly_t2p ( int n, double a[], double x ) /******************************************************************************/ /* Purpose: r8poly_t2p() converts a polynomial from Taylor form to power sum form Discussion: The Taylor form is p(x) = a(1) + a(2) * (x-x0) + a(3) * (x-x0)^2 ... + a(n) * (x-x0)^(n-1) The power sum form is p(x) = a(1) + a(2)*x + a(3)*x^2 + ... + a(n)*x^(n-1) Licensing: This code is distributed under the MIT license. Modified: 28 March 2009 Author: John Burkardt Parameters: Input, int N, the dimension of A. Input/output, double A[N]. On input, the coefficients in Taylor form, and on output, the coefficients in power sum form. Input, double X, the point at which the Taylor form polynomial is based. */ { int i; int j; for ( i = n; 1 <= i; i-- ) { for ( j = i; j <= n-1; j++ ) { a[j-1] = a[j-1] - a[j] * x; } } return; } /******************************************************************************/ void r8vec_backtrack ( int n, int maxstack, double x[], int *indx, int *k, int *nstack, double stack[], int ncan[] ) /******************************************************************************/ /* Purpose: r8vec_backtrack() supervises a backtrack search for a vector. Discussion: The routine tries to construct a vector one index at a time, using possible candidates as supplied by the user. At any time, the partially constructed vector may be discovered to be unsatisfactory, but the routine records information about where the last arbitrary choice was made, so that the search can be carried out efficiently, rather than starting out all over again. First, call the routine with INDX = 0 so it can initialize itself. Now, on each return from the routine, if INDX is: 1, you've just been handed a complete candidate vector; Admire it, analyze it, do what you like. 2, please determine suitable candidates for position X(K). Return the number of candidates in NCAN(K), adding each candidate to the end of STACK, and increasing NSTACK. 3, you're done. Stop calling the routine; Licensing: This code is distributed under the MIT license. Modified: 29 March 2009 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the number of positions to be filled in the vector. Input, int MAXSTACK, the maximum length of the stack. Input/output, double X[N], the partial or complete candidate vector. Input/output, int *INDX, a communication flag. On input, 0 to start a search. On output: 1, a complete output vector has been determined and returned in X(1:N); 2, candidates are needed for position X(K); 3, no more possible vectors exist. Inout/output, int *K, if INDX=2, the current vector index being considered. Input/output, int *NSTACK, the current length of the stack. Input/output, double STACK[MAXSTACK], a list of all current candidates for all positions 1 through K. Input/output, int NCAN[N], lists the current number of candidates for positions 1 through K. */ { /* If this is the first call, request a candidate for position 1. */ if ( *indx == 0 ) { *k = 1; *nstack = 0; *indx = 2; return; } /* Examine the stack. */ for ( ; ; ) { /* If there are candidates for position K, take the first available one off the stack, and increment K. This may cause K to reach the desired value of N, in which case we need to signal the user that a complete set of candidates is being returned. */ if ( 0 < ncan[(*k)-1] ) { x[(*k)-1] = stack[(*nstack)-1]; *nstack = *nstack - 1; ncan[(*k)-1] = ncan[(*k)-1] - 1; if ( *k != n ) { *k = *k + 1; *indx = 2; } else { *indx = 1; } break; } /* If there are no candidates for position K, then decrement K. If K is still positive, repeat the examination of the stack. */ else { *k = *k - 1; if ( *k <= 0 ) { *indx = 3; break; } } } return; } /******************************************************************************/ double r8vec_dot_product ( int n, double a1[], double a2[] ) /******************************************************************************/ /* Purpose: r8vec_dot_product() computes the dot product of a pair of R8VEC's. Licensing: This code is distributed under the MIT license. Modified: 26 July 2007 Author: John Burkardt Parameters: Input, int N, the number of entries in the vectors. Input, double A1[N], A2[N], the two vectors to be considered. Output, double R8VEC_DOT_PRODUCT, the dot product of the vectors. */ { int i; double value; value = 0.0; for ( i = 0; i < n; i++ ) { value = value + a1[i] * a2[i]; } return value; } /******************************************************************************/ double r8vec_frac ( int n, double a[], int k ) /******************************************************************************/ /* Purpose: r8vec_frac() searches for the K-th smallest entry in an R8VEC. Discussion: Hoare's algorithm is used. Licensing: This code is distributed under the MIT license. Modified: 23 March 2009 Author: John Burkardt Parameters: Input, int N, the number of elements of A. Input/output, double A[N]. On input, A is the array to search. On output, the elements of A have been somewhat rearranged. Input, int K, the fractile to be sought. If K = 1, the minimum entry is sought. If K = N, the maximum is sought. Other values of K search for the entry which is K-th in size. K must be at least 1, and no greater than N. Output, double R8VEC_FRAC, the value of the K-th fractile of A. */ { double afrac; int i; int iryt; int j; int left; double temp; double x; if ( n <= 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "R8VEC_FRAC(): Fatal error!\n" ); fprintf ( stderr, " Illegal nonpositive value of N = %d\n", n ); exit ( 1 ); } if ( k <= 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "R8VEC_FRAC(): Fatal error!\n" ); fprintf ( stderr, " Illegal nonpositive value of K = %d\n", k ); exit ( 1 ); } if ( n < k ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "R8VEC_FRAC(): Fatal error!\n" ); fprintf ( stderr, " Illegal N < K, K = %d\n", k ); exit ( 1 ); } left = 1; iryt = n; for ( ; ; ) { if ( iryt <= left ) { afrac = a[k-1]; break; } x = a[k-1]; i = left; j = iryt; for ( ; ; ) { if ( j < i ) { if ( j < k ) { left = i; } if ( k < i ) { iryt = j; } break; } /* Find I so that X <= A(I). */ while ( a[i-1] < x ) { i = i + 1; } /* Find J so that A(J) <= X */ while ( x < a[j-1] ) { j = j - 1; } if ( i <= j ) { temp = a[i-1]; a[i-1] = a[j-1]; a[j-1] = temp; i = i + 1; j = j - 1; } } } return afrac; } /******************************************************************************/ double *r8vec_indicator1_new ( int n ) /******************************************************************************/ /* Purpose: r8vec_indicator1_new() sets an R8VEC to the indicator vector {1,...,N}. Licensing: This code is distributed under the MIT license. Modified: 26 August 2008 Author: John Burkardt Parameters: Input, int N, the number of elements of A. Output, double R8VEC_INDICATOR1_NEW[N], the array to be initialized. */ { double *a; int i; a = ( double * ) malloc ( n * sizeof ( double ) ); for ( i = 0; i <= n-1; i++ ) { a[i] = ( double ) ( i + 1 ); } return a; } /******************************************************************************/ int r8vec_mirror_next ( int n, double a[] ) /******************************************************************************/ /* Purpose: r8vec_mirror_next() steps through all sign variations of an R8VEC. Discussion: In normal use, the user would set every element of A to be positive. The routine will take the input value of A, and output a copy in which the signs of one or more entries have been changed. Repeatedly calling the routine with the output from the previous call will generate every distinct "variation" of A; that is, all possible sign variations. When the output variable DONE is TRUE (or equal to 1), then the output value of A_NEW is the last in the series. Note that A may have some zero values. The routine will essentially ignore such entries; more exactly, it will not stupidly assume that -0 is a proper "variation" of 0! Also, it is possible to call this routine with the signs of A set in any way you like. The routine will operate properly, but it will nonethess terminate when it reaches the value of A in which every nonzero entry has negative sign. More efficient algorithms using the Gray code seem to require internal memory in the routine, which is not one of MATLAB's strong points, or the passing back and forth of a "memory array", or the use of global variables, or unnatural demands on the user. This form of the routine is about as clean as I can make it. Example: Input Output --------- -------------- A A R8VEC_MIRROR_NEXT --------- -------- ---- 1 2 3 -1 2 3 0 -1 2 3 1 -2 3 0 1 -2 3 -1 -2 3 0 -1 -2 3 1 2 -3 0 1 2 -3 -1 2 -3 0 -1 2 -3 1 -2 -3 0 1 -2 -3 -1 -2 -3 0 -1 -2 -3 1 2 3 1 1 0 3 -1 0 3 0 -1 0 3 1 0 -3 0 1 0 -3 -1 0 -3 0 -1 0 -3 1 0 3 1 Licensing: This code is distributed under the MIT license. Modified: 01 April 2009 Author: John Burkardt Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the number of entries in the vector. Input/output, double A[N], a vector of real numbers. On output, some signs have been changed. Output, int R8VEC_MIRROR_NEXT, is TRUE if the input vector A was the last element in the series (every entry was nonpositive); the output vector is reset so that all entries are nonnegative, but presumably the ride is over! */ { int i; int positive; /* Seek the first strictly positive entry of A. */ positive = 0; for ( i = 1; i <= n; i++ ) { if ( 0.0 < a[i-1] ) { positive = i; break; } } /* If there is no strictly positive entry of A, there is no successor. */ if ( positive == 0 ) { for ( i = 1; i <= n; i++ ) { a[i-1] = -a[i-1]; } return 1; } /* Otherwise, negate A up to the positive entry. */ for ( i = 1; i <= positive; i++ ) { a[i-1] = -a[i-1]; } return 0; } /******************************************************************************/ void r8vec_print ( int n, double a[], char *title ) /******************************************************************************/ /* Purpose: r8vec_print() prints an R8VEC Licensing: This code is distributed under the MIT license. Modified: 01 April 2009 Author: John Burkardt Parameters: Input, int N, the number of components of the vector. Input, double A[N], the vector to be printed. Input, char *TITLE, a title to be printed first. TITLE may be blank. */ { int i; if ( s_len_trim ( title ) != 0 ) { printf ( "\n" ); printf ( "%s\n", title ); } printf ( "\n" ); for ( i = 0; i <= n-1; i++ ) { printf ( " %8d %12f\n", i, a[i] ); } return; } /******************************************************************************/ double *r8vec_uniform_ab_new ( int n, double b, double c, int *seed ) /******************************************************************************/ /* Purpose: r8vec_uniform_ab_new() returns a scaled pseudorandom R8VEC. Discussion: This routine implements the recursion seed = 16807 * seed mod ( 2^31 - 1 ) unif = seed / ( 2^31 - 1 ) The integer arithmetic never requires more than 32 bits, including a sign bit. Licensing: This code is distributed under the MIT license. Modified: 30 January 2005 Author: John Burkardt Reference: Paul Bratley, Bennett Fox, Linus Schrage, A Guide to Simulation, Second Edition, Springer, 1987, ISBN: 0387964673, LC: QA76.9.C65.B73. Bennett Fox, Algorithm 647: Implementation and Relative Efficiency of Quasirandom Sequence Generators, ACM Transactions on Mathematical Software, Volume 12, Number 4, December 1986, pages 362-376. Pierre L'Ecuyer, Random Number Generation, in Handbook of Simulation, edited by Jerry Banks, Wiley, 1998, ISBN: 0471134031, LC: T57.62.H37. Peter Lewis, Allen Goodman, James Miller, A Pseudo-Random Number Generator for the System/360, IBM Systems Journal, Volume 8, Number 2, 1969, pages 136-143. Parameters: Input, int N, the number of entries in the vector. Input, double B, C, the lower and upper limits of the pseudorandom values. Input/output, int *SEED, a seed for the random number generator. Output, double R8VEC_UNIFORM_AB_NEW[N], the vector of pseudorandom values. */ { int i; int i4_huge = 2147483647; int k; double *r; if ( *seed == 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "R8VEC_UNIFORM_AB_NEW(): Fatal error!\n" ); fprintf ( stderr, " Input value of SEED = 0.\n" ); exit ( 1 ); } r = ( double * ) malloc ( n * sizeof ( double ) ); for ( i = 0; i < n; i++ ) { k = *seed / 127773; *seed = 16807 * ( *seed - k * 127773 ) - k * 2836; if ( *seed < 0 ) { *seed = *seed + i4_huge; } r[i] = b + ( c - b ) * ( double ) ( *seed ) * 4.656612875E-10; } return r; } /******************************************************************************/ void r8vec_uniform_01 ( int n, int *seed, double r[] ) /******************************************************************************/ /* Purpose: r8vec_uniform_01() returns a unit pseudorandom R8VEC. Discussion: This routine implements the recursion seed = 16807 * seed mod ( 2^31 - 1 ) unif = seed / ( 2^31 - 1 ) The integer arithmetic never requires more than 32 bits, including a sign bit. Licensing: This code is distributed under the MIT license. Modified: 19 August 2004 Author: John Burkardt Reference: Paul Bratley, Bennett Fox, Linus Schrage, A Guide to Simulation, Second Edition, Springer, 1987, ISBN: 0387964673, LC: QA76.9.C65.B73. Bennett Fox, Algorithm 647: Implementation and Relative Efficiency of Quasirandom Sequence Generators, ACM Transactions on Mathematical Software, Volume 12, Number 4, December 1986, pages 362-376. Pierre L'Ecuyer, Random Number Generation, in Handbook of Simulation, edited by Jerry Banks, Wiley, 1998, ISBN: 0471134031, LC: T57.62.H37. Peter Lewis, Allen Goodman, James Miller, A Pseudo-Random Number Generator for the System/360, IBM Systems Journal, Volume 8, Number 2, 1969, pages 136-143. Parameters: Input, int N, the number of entries in the vector. Input/output, int *SEED, a seed for the random number generator. Output, double R[N], the vector of pseudorandom values. */ { int i; int i4_huge = 2147483647; int k; if ( *seed == 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "R8VEC_UNIFORM_01(): Fatal error!\n" ); fprintf ( stderr, " Input value of SEED = 0.\n" ); exit ( 1 ); } for ( i = 0; i < n; i++ ) { k = *seed / 127773; *seed = 16807 * ( *seed - k * 127773 ) - k * 2836; if ( *seed < 0 ) { *seed = *seed + i4_huge; } r[i] = ( double ) ( *seed ) * 4.656612875E-10; } return; } /******************************************************************************/ void rat_add ( int itop1, int ibot1, int itop2, int ibot2, int *itop, int *ibot, int *error ) /******************************************************************************/ /* Purpose: rat_add() adds two rational values. Discussion: The routine computes ITOP/IBOT = ITOP1/IBOT1 + ITOP2/IBOT2 while trying to avoid int overflow. Licensing: This code is distributed under the MIT license. Modified: 29 March 2009 Author: John Burkardt Parameters: Input, int ITOP1, IBOT1, the first value to add. Input, int ITOP2, IBOT2, the second value to add. Output, int *ITOP, *IBOT, the sum. Output, int *ERROR, is TRUE if an error occurred. */ { int i_max; int itemp; int ibot3; i_max = i4_huge ( ); *error = 0; if ( itop1 == 0 ) { *itop = itop2; *ibot = ibot2; return; } else if ( itop2 == 0 ) { *itop = itop1; *ibot = ibot1; return; } /* Divide out the greatest common factor of the two denominators. */ ibot3 = i4_gcd ( ibot1, ibot2 ); ibot1 = ibot1 / ibot3; ibot2 = ibot2 / ibot3; /* The fraction may now be formally written as: (itop1*ibot2 + itop2*ibot1) / (ibot1*ibot2*ibot3) Check the tops for overflow. */ if ( ( double ) ( i_max ) < fabs ( ( double ) ( itop1 ) * ( double ) ( ibot2 ) ) ) { *error = 1; fprintf ( stderr, "\n" ); fprintf ( stderr, "RAT_ADD(): Fatal error!\n" ); fprintf ( stderr, " Overflow of top of rational sum.\n" ); *itop = 0; *ibot = 1; exit ( 1 ); } itop1 = itop1 * ibot2; if ( ( double ) ( i_max ) < fabs ( ( double ) ( itop2 ) * ( double ) ( ibot1 ) ) ) { *error = 1; fprintf ( stderr, "\n" ); fprintf ( stderr, "RAT_ADD(): Fatal error!\n" ); fprintf ( stderr, " Overflow of top of rational sum.\n" ); *itop = 0; *ibot = 1; exit ( 1 ); } itop2 = itop2 * ibot1; if ( ( double ) ( i_max ) < fabs ( ( double ) ( itop1 ) + ( double ) ( itop2 ) ) ) { *error = 1; fprintf ( stderr, "\n" ); fprintf ( stderr, "RAT_ADD(): Fatal error!\n" ); fprintf ( stderr, " Overflow of top of rational sum.\n" ); *itop = 0; *ibot = 1; exit ( 1 ); } *itop = itop1 + itop2; /* Check the bottom for overflow. */ if ( ( double ) ( i_max ) < fabs ( ( double ) ( ibot1 ) * ( double ) ( ibot2 ) * ( double ) ( ibot3 ) ) ) { *error = 1; fprintf ( stderr, "\n" ); fprintf ( stderr, "RAT_ADD(): Fatal error!\n" ); fprintf ( stderr, " Overflow of bottom of rational sum.\n" ); *itop = 0; *ibot = 1; exit ( 1 ); } *ibot = ibot1 * ibot2 * ibot3; /* Put the fraction in lowest terms. */ itemp = i4_gcd ( *itop, *ibot ); *itop = *itop / itemp; *ibot = *ibot / itemp; /* The bottom should be positive. */ if ( *ibot < 0 ) { *ibot = -(*ibot); *itop = -(*itop); } return; } /******************************************************************************/ void rat_div ( int itop1, int ibot1, int itop2, int ibot2, int *itop, int *ibot, int *error ) /******************************************************************************/ /* Purpose: rat_div() divides one rational value by another. Discussion: The routine computes ITOP / IBOT = ( ITOP1 / IBOT1 ) / ( ITOP2 / IBOT2 ). while avoiding integer overflow. Licensing: This code is distributed under the MIT license. Modified: 29 March 2009 Author: John Burkardt Parameters: Input, int ITOP1, IBOT1, the numerator. Input, int ITOP2, IBOT2, the denominator. Output, int *ITOP, *IBOT, the result. Output, int *ERROR, is TRUE if an error occurred. */ { int i_max; int itemp; *error = 0; i_max = i4_huge ( ); if ( ibot1 == 0 || itop2 == 0 || ibot2 == 0 ) { *error = 1; return; } if ( itop1 == 0 ) { *itop = 0; *ibot = 1; return; } /* Get rid of all common factors in top and bottom. */ itemp = i4_gcd ( itop1, ibot1 ); itop1 = itop1 / itemp; ibot1 = ibot1 / itemp; itemp = i4_gcd ( itop1, itop2 ); itop1 = itop1 / itemp; itop2 = itop2 / itemp; itemp = i4_gcd ( ibot2, ibot1 ); ibot2 = ibot2 / itemp; ibot1 = ibot1 / itemp; itemp = i4_gcd ( ibot2, itop2 ); ibot2 = ibot2 / itemp; itop2 = itop2 / itemp; /* The fraction (ITOP1*IBOT2)/(IBOT1*ITOP2) is in lowest terms. Check the top for overflow. */ if ( ( double ) i_max < fabs ( ( double ) itop1 * ( double ) ibot2 ) ) { *error = 1; printf ( "\n" ); printf ( "RAT_DIV - Warning!\n" ); printf ( " Overflow of top of rational fraction.\n" ); *itop = 0; *ibot = 0; return; } *itop = itop1 * ibot2; /* Check the bottom IBOT1*ITOP2 for overflow. */ if ( ( double ) i_max < fabs ( ( double ) ibot1 * ( double ) itop2 ) ) { *error = 1; printf ( "\n" ); printf ( "RAT_DIV - Warning!\n" ); printf ( " Overflow of bottom of rational fraction.\n" ); *itop = 0; *ibot = 1; return; } *ibot = ibot1 * itop2; /* The bottom should be positive. */ if ( *ibot < 0 ) { *ibot = - (*ibot); *itop = - (*itop); } /* The fraction is ITOP/IBOT with no loss of accuracy. */ return; } /******************************************************************************/ void rat_farey ( int n, int max_frac, int *num_frac, int a[], int b[] ) /******************************************************************************/ /* Purpose: rat_farey() computes the N-th row of the Farey fraction table. Example: N = 5 NUM_FRAC = 11 A = 0 1 1 1 2 1 3 2 3 4 1 B = 1 5 4 3 5 2 5 3 4 5 1 Discussion: In this form of the Farey fraction table, fractions in row N lie between 0 and 1, are in lowest terms, and have a denominator that is no greater than N. Row N is computed directly, and does not require the computation of previous rows. The data satisfy the relationship: A(K+1) * B(K) - A(K) * B(K+1) = 1 The number of items in the N-th row is roughly N^2 / PI^2. Licensing: This code is distributed under the MIT license. Modified: 29 March 2009 Author: John Burkardt Reference: Donald Knuth, The Art of Computer Programming, Volume 1, Fundamental Algorithms, Addison Wesley, 1968, page 157. Parameters: Input, int N, the desired row number. N must be positive. Input, int MAX_FRAC, the maximum number of fractions to compute. Output, int NUM_FRAC, the number of fractions computed. Output, int A[MAX_FRAC], B[MAX_FRAC], contains the NUM_FRAC numerators and denominators of the N-th row of the Farey fraction table. */ { int c; int k; if ( n <= 0 ) { *num_frac = 0; return; } k = 0; if ( max_frac <= 0 ) { *num_frac = k; return; } a[k] = 0; b[k] = 1; k = 1; if ( max_frac <= 1 ) { *num_frac = k; return; } a[k] = 1; b[k] = n; k = 2; while ( k < max_frac ) { if ( a[k-1] == 1 && b[k-1] == 1 ) { break; } c = ( b[k-2] + n ) / b[k-1]; a[k] = c * a[k-1] - a[k-2]; b[k] = c * b[k-1] - b[k-2]; k = k + 1; } *num_frac = k; return; } /******************************************************************************/ void rat_farey2 ( int n, int a[], int b[] ) /******************************************************************************/ /* Purpose: rat_farey2() computes the next row of the Farey fraction table. Example: Input: N = 3 A = 0 1 1 2 1 B = 1 3 2 3 1 Output: A = 0 1 1 2 1 3 2 3 1 B = 1 4 3 5 2 5 3 4 1 Discussion: In this form of the Farey fraction table, fractions in row N lie between 0 and 1, and are in lowest terms. For every adjacent pair of input fractions, A1/B1 and A2/B2, the mediant (A1+A2)/(B1+B2) is computed and inserted between them. The number of items in the N-th row is 1+2^(N-1). Licensing: This code is distributed under the MIT license. Modified: 29 March 2009 Author: John Burkardt Parameters: Input, int N, the input row number. N must be nonnegative. If N is zero, then the input is ignored, and the entries of row 1 are computed directly. Input/output, int A[1+2^N], B[1+2^N]. On input, entries 1 through 1+2^(N-1) contain the entries of row N. On output, entries 1 through 1+2^N contain the entries of row N+1. */ { int i; int ihi; if ( n == 0 ) { a[0] = 0; b[0] = 1; a[1] = 1; b[1] = 1; return; } /* Shift the current data. */ ihi = i4_power ( 2, n - 1 ); for ( i = ihi; 0 <= i; i-- ) { a[2*i] = a[i]; b[2*i] = b[i]; } /* Compute the mediants. */ ihi = i4_power ( 2, n ) - 1; for ( i = 1; i <= ihi; i = i + 2 ) { a[i] = a[i-1] + a[i+1]; b[i] = b[i-1] + b[i+1]; } return; } /******************************************************************************/ void rat_mul ( int itop1, int ibot1, int itop2, int ibot2, int *itop, int *ibot, int *error ) /******************************************************************************/ /* Purpose: rat_mul() multiplies two fractions. Discussion: The routine computes ITOP / IBOT = ( ITOP1 / IBOT1 ) * ( ITOP2 / IBOT2 ). while avoiding int overflow. Licensing: This code is distributed under the MIT license. Modified: 29 March 2009 Author: John Burkardt Parameters: Input, int ITOP1, IBOT1, the first factor. Input, int ITOP2, IBOT2, the second factor. Output, int *ITOP, *IBOT, the product. Output, int *ERROR, is TRUE if an error occurred. */ { int i_max; int itemp; *error = 0; i_max = i4_huge ( ); if ( itop1 == 0 || itop2 == 0 ) { *itop = 0; *ibot = 1; return; } /* Get rid of all common factors in top and bottom. */ itemp = i4_gcd ( itop1, ibot1 ); itop1 = itop1 / itemp; ibot1 = ibot1 / itemp; itemp = i4_gcd ( itop1, ibot2 ); itop1 = itop1 / itemp; ibot2 = ibot2 / itemp; itemp = i4_gcd ( itop2, ibot1 ); itop2 = itop2 / itemp; ibot1 = ibot1 / itemp; itemp = i4_gcd ( itop2, ibot2 ); itop2 = itop2 / itemp; ibot2 = ibot2 / itemp; /* The fraction (ITOP1 * ITOP2)/(IBOT1 * IBOT2) is in lowest terms. Check the top ITOP1 * ITOP2 for overflow. */ if ( ( double ) ( i_max ) < fabs ( ( double ) itop1 * ( double ) itop2 ) ) { *error = 1; fprintf ( stderr, "\n" ); fprintf ( stderr, "RAT_MUL(): Fatal error!\n" ); fprintf ( stderr, " Overflow of top of rational product.\n" ); *itop = 0; exit ( 1 ); } *itop = itop1 * itop2; /* Check the bottom IBOT1*IBOT2 for overflow. */ if ( ( double ) ( i_max ) < fabs ( ( double ) ibot1 * ( double ) ibot2 ) ) { *error = 1; printf ( "\n" ); printf ( "RAT_MUL - Warning!\n" ); printf ( " Overflow of bottom of rational product.\n" ); *ibot = 1; return; } *ibot = ibot1 * ibot2; /* The bottom should be positive. */ if ( *ibot < 0 ) { *ibot = -(*ibot); *itop = -(*itop); } return; } /******************************************************************************/ void rat_normalize ( int *a, int *b ) /******************************************************************************/ /* Purpose: rat_normalize() normalizes a rational number. Discussion: If A = B = 0, return. If A = 0 (and B nonzero) set B => 1 and return. If A nonzero, and B = 0, then A => 1 and return. If A = B, then set A => 1, B => 1 and return. If B < 0, then A => -A, B => -B. If 1 < C = GCD(|A|,|B|), A => A/C, B => B/C. Licensing: This code is distributed under the MIT license. Modified: 29 March 2009 Author: John Burkardt Parameters: Input/output, int *A, *B, the rational number. */ { int c; /* Cases where one or both is 0. */ if ( *a == 0 && *b == 0 ) { return; } else if ( *a == 0 && *b != 0 ) { *b = 1; return; } else if ( *a != 0 && *b == 0 ) { *a = 1; return; } if ( *a == *b ) { *a = 1; *b = 1; return; } if ( *b < 0 ) { *a = -(*a); *b = -(*b); } c = i4_gcd ( abs ( *a ), abs ( *b ) ); if ( 1 < c ) { *a = *a / c; *b = *b / c; } return; } /******************************************************************************/ void rat_sum_formula ( int n, int a[], int b[] ) /******************************************************************************/ /* Purpose: rat_sum_formula() computes the formulas for sums of powers of integers. Example: N = 6 1 2 3 4 5 6 7 ----------------------------------- 0 | 1 0 0 0 0 0 0 | 1 | 1 1 0 0 0 0 0 | 2 2 | 2 | 1 1 1 0 0 0 0 | 3 2 6 | 3 | 1 1 1 0 0 0 0 | 4 2 4 | 4 | 1 1 1 0 -1 0 0 | 5 2 3 30 | 5 | 1 1 5 0 -1 0 0 | 6 2 12 12 | 6 | 1 1 1 0 -1 0 1 | 7 2 2 6 42 The interpretation of row 2, for instance, is: sum ( 1 <= I <= N ) I^2 = 1/3 N^3 + 1/2 N^2 + 1/6 N This suggests that a more sensible way to display the table is to reverse the order of the entries in the row, so that the entry in column J is the coeficient of N^J, which is not the case now. Licensing: This code is distributed under the MIT license. Modified: 29 March 2009 Author: John Burkardt Reference: Robert Owens, Sums of Powers of Integers, Mathematics Magazine, Volume 65, Number 1, February 1992, pages 38-40. Parameters: Input, int N, the number of rows of coefficients to compute. Output, int A[(N+1)*(N+1)], B[(N+1)*(N+1)], the numerator and denominator of the coefficients. */ { int asum; int aval; int bsum; int bval; int error; int i; int j; a[0+0*(n+1)] = 1; for ( j = 1; j < n+1; j++ ) { a[0+j*(n+1)] = 0; } b[0+0*(n+1)] = 1; for ( j = 1; j < n+1; j++ ) { b[0+j*(n+1)] = 1; } for ( i = 1; i <= n; i++ ) { asum = 0; bsum = 0; /* Subdiagonal entries are multiples of entries above them. */ for ( j = 0; j < i; j++ ) { aval = a[i-1+j*(n+1)]; bval = b[i-1+j*(n+1)]; rat_mul ( aval, bval, i, i+1-j, &aval, &bval, &error ); a[i+j*(n+1)] = aval; b[i+j*(n+1)] = bval; rat_add ( asum, bsum, aval, bval, &asum, &bsum, &error ); } /* Diagonal entry is 1 - sum of previous entries in row. */ asum = -asum; rat_add ( 1, 1, asum, bsum, &aval, &bval, &error ); a[i+i*(n+1)] = aval; b[i+i*(n+1)] = bval; /* Superdiagonal entries are zero. */ for ( j = i+1; j < n+1; j++ ) { a[i+j*(n+1)] = 0; } for ( j = i+1; j <= n; j++ ) { b[i+j*(n+1)] = 1; } } return; } /******************************************************************************/ void rat_to_cfrac ( int ip, int iq, int m, int *n, int a[], int *error ) /******************************************************************************/ /* Purpose: rat_to_cfrac() converts a rational value to a continued fraction. Discussion: The routine is given a rational number represented by IP/IQ, and computes the monic or "simple" continued fraction representation with int coefficients of the number: A(1) + 1/ (A(2) + 1/ (A(3) + ... + 1/A(N) ...)) The user must dimension A to a value M which is "large enough". The actual number of terms needed in the continued fraction representation cannot be known beforehand. Licensing: This code is distributed under the MIT license. Modified: 29 March 2009 Author: FORTRAN77 version by John Hart, Ward Cheney, Charles Lawson, Hans Maehly, Charles Mesztenyi, John Rice, Henry Thatcher, Christoph Witzgall. This version by John Burkardt Reference: John Hart, Ward Cheney, Charles Lawson, Hans Maehly, Charles Mesztenyi, John Rice, Henry Thatcher, Christoph Witzgall, Computer Approximations, Wiley, 1968. Parameters: Input, int IP, IQ, the numerator and denominator of the rational value whose continued fraction representation is desired. Input, int M, the dimension of A. If M is not great enough, the algorithm may run out of space. Output, int *N, the actual number of entries used in A. Output, int A[M], contains the continued fraction representation of the number. Output, int *ERROR, is TRUE if an error occurred. */ { *error = 0; *n = 0; for ( ; ; ) { if ( m <= *n ) { *error = 1; return; } a[*n] = ip / iq; *n = *n + 1; ip = ip % iq; if ( ip == 0 ) { return; } if ( m <= *n ) { *error = 1; return; } a[*n] = iq / ip; *n = *n + 1; iq = iq % ip; if ( iq == 0 ) { break; } } return; } /******************************************************************************/ void rat_to_dec ( int rat_top, int rat_bot, int *mantissa, int *exponent ) /******************************************************************************/ /* Purpose: rat_to_dec() converts a rational to a decimal representation. Discussion: A rational value is represented by RAT_TOP / RAT_BOT. A decimal value is represented as MANTISSA * 10^EXPONENT. Licensing: This code is distributed under the MIT license. Modified: 29 March 2009 Author: John Burkardt Parameters: Input, int RAT_TOP, RAT_BOT, the rational value. Output, int *MANTISSA, *EXPONENT, the decimal number. */ { int gcd; double r; double r_max; int s; /* Handle an input value of 0. */ if ( rat_top == 0 ) { *mantissa = 0; *exponent = 0; return; } /* Take out any common factor. */ gcd = i4_gcd ( rat_top, rat_bot ); rat_top = rat_top / gcd; rat_bot = rat_bot / gcd; /* Force the bottom of the fraction to be positive. */ if ( rat_bot < 0 ) { rat_top = -rat_top; rat_bot = -rat_bot; } /* If the fraction is a whole number, we can finish now. */ if ( rat_bot == 1 ) { *mantissa = rat_top; *exponent = 0; return; } /* Whole factors of 10 in the bottom or top go into the decimal exponent. */ *exponent = 0; while ( ( rat_bot % 10 ) == 0 ) { *exponent = *exponent - 1; rat_bot = rat_bot / 10; } while ( ( rat_top % 10 ) == 0 ) { *exponent = *exponent + 1; rat_top = rat_top / 10; } /* Convert to a real value. */ r = ( double ) rat_top / ( double ) rat_bot; if ( r < 0 ) { s = -1; r = -r; } else { s = 1; } r_max = ( ( double ) i4_huge ( ) ) / 10.0; while ( r != ( double ) ( ( int ) r ) && r < r_max ) { r = r * 10.0; *exponent = *exponent - 1; } *mantissa = s * ( int ) r; return; } /******************************************************************************/ double rat_to_r8 ( int top, int bot ) /******************************************************************************/ /* Purpose: rat_to_r8() converts rational values to R8's. Licensing: This code is distributed under the MIT license. Modified: 29 March 2009 Author: John Burkardt Parameters: Input, int TOP, BOT, the rational quantity (TOP/BOT) that is to be converted. Output, double RAT_TO_R8, the real value of the fraction. */ { double value; value = ( double ) top / ( double ) bot; return value; } /******************************************************************************/ char *rat_to_s ( int a, int b ) /******************************************************************************/ /* Purpose: rat_to_s() converts an integer ratio A/B to a string. Discussion: Note that if A is nonzero and B is 0, S will be returned as "Inf" or "-Inf" (Infinity), and if both A and B are zero, S will be returned as "NaN" (Not-a-Number). Licensing: This code is distributed under the MIT license. Modified: 01 June 2015 Author: John Burkardt Parameters: Input, int A, B, the numerator and denominator. Output, char *RAT_TO_S, the representation of the ratio. */ { int n1; int n2; char *sa; char *sb; char *s; if ( b == 0 ) { if ( a == 0 ) { s = ( char * ) malloc ( 4 * sizeof ( char ) ); strcpy ( s, "NaN" ); } else if ( a < 0 ) { s = ( char * ) malloc ( 5 * sizeof ( char ) ); strcpy ( s, "-Inf" ); } else { s = ( char * ) malloc ( 4 * sizeof ( char ) ); strcpy ( s, "Inf" ); } } else { n1 = i4_width ( a ); n2 = i4_width ( b ); s = ( char * ) malloc ( ( n1 + 1 + n2 + 1 ) * sizeof ( char ) ); sa = i4_to_s ( a ); strcpy ( s, sa ); strcat ( s, "/" ); sb = i4_to_s ( b ); strcat ( s, sb ); free ( sa ); free ( sb ); } return s; } /******************************************************************************/ int rat_width ( int a, int b ) /******************************************************************************/ /* Purpose: rat_width() returns the "width" of a rational number. Licensing: This code is distributed under the MIT license. Modified: 29 March 2009 Author: John Burkardt Parameters: Input, int A, B, the rational number. Output, int RAT_WIDTH, the "width" of the rational number. */ { int abs_a; int abs_b; int ten_pow; int value; value = 1; ten_pow = 10; if ( a == 0 ) { return value; } abs_a = abs ( a ); while ( ten_pow <= abs_a ) { value = value + 1; ten_pow = ten_pow * 10; } /* If the fraction is negative, a minus sign will be prepended to the numerator. */ if ( a * b < 0 ) { value = value + 1; ten_pow = ten_pow * 10; } abs_b = abs ( b ); while ( ten_pow <= abs_b ) { value = value + 1; ten_pow = ten_pow * 10; } return value; } /******************************************************************************/ void ratmat_det ( int n, int iatop[], int iabot[], int *idtop, int *idbot, int *error ) /******************************************************************************/ /* Purpose: ratmat_det() finds the determinant of an N by N matrix of rational entries. Discussion: The brute force method is used. This routine should only be used for small matrices, since this calculation requires the summation of N! products of N numbers. Licensing: This code is distributed under the MIT license. Modified: 01 April 2009 Author: John Burkardt Parameters: Input, int N, the number of rows and columns of A. Input, int IATOP[N*N], IABOT[N*N], the numerators and denominators of the entries of the matrix. Output, int *IDTOP, *IDBOT, the determinant of the matrix, expressed as IDTOP/IDBOT. Output, int *ERROR, is TRUE if an error occurred. */ { int even; int i; int *iarray; int ibot; int ibot2; int itop; int itop2; int more; *error = 0; more = 0; *idtop = 0; *idbot = 1; iarray = ( int * ) malloc ( n * sizeof ( int ) ); for ( ; ; ) { perm0_next ( n, iarray, &more, &even ); if ( even ) { itop = 1; } else { itop = -1; } ibot = 1; for ( i = 0; i < n; i++ ) { itop2 = iatop[i+iarray[i]*n]; ibot2 = iabot[i+iarray[i]*n]; rat_mul ( itop, ibot, itop2, ibot2, &itop, &ibot, error ); if ( *error ) { printf ( "\n" ); printf ( "RATMAT_DET - Warning!\n" ); printf ( " An overflow occurred.\n" ); printf ( " The determinant calculation cannot be done\n" ); printf ( " for this matrix.\n" ); *idtop = 0; *idbot = 1; free ( iarray ); return; } } rat_add ( itop, ibot, *idtop, *idbot, idtop, idbot, error ); if ( *error ) { printf ( "\n" ); printf ( "RATMAT_DET - Warning!\n" ); printf ( " An overflow occurred.\n" ); printf ( " The determinant calculation cannot be done\n" ); printf ( " for this matrix.\n" ); *idtop = 0; *idbot = 1; free ( iarray ); return; } if ( !more ) { break; } } free ( iarray ); /* The bottom should be positive. */ if ( *idbot < 0 ) { *idbot = -(*idbot); *idtop = -(*idtop); } return; } /******************************************************************************/ void ratmat_print ( int m, int n, int a[], int b[], char *title ) /******************************************************************************/ /* Purpose: ratmat_print() prints out a rational matrix. Licensing: This code is distributed under the MIT license. Modified: 01 April 2009 Author: John Burkardt Parameters: Input, int M, N, the number of rows and columns in the matrix. Input, int A[M*N], B[M*N], the rational matrix. Input, char *TITLE, a label for the object being printed. */ { int all_ones; int i; int j; int jmax; int jmin; int kmax; int ncolum = 80; int npline; /* Figure out how many rationals we can get in NCOLUM columns. Can I pass the VALUE of these entries this way? */ kmax = 0; for ( i = 0; i < m; i++ ) { for ( j = 0; j < n; j++ ) { kmax = i4_max ( kmax, rat_width ( a[i+j*m], b[i+j*m] ) ); } } kmax = kmax + 2; npline = ncolum / kmax; /* Now do the printing. */ for ( jmin = 0; jmin < n; jmin = jmin + npline ) { jmax = i4_min ( jmin+npline-1, n-1 ); printf ( "\n" ); if ( jmin == 0 ) { printf ( "%s\n", title ); printf ( "\n" ); } if ( 0 < jmin || jmax < n-1 ) { printf ( "Columns %d to %d\n", jmin, jmax ); printf ( "\n" ); } for ( i = 0; i < m; i++ ) { for ( j = jmin; j <= jmax; j++ ) { printf ( "%8d ", a[i+j*m] ); } printf ( "\n" ); /* Delete each denominator that is 1. If all are 1, don't even print out the line. */ all_ones = 1; for ( j = jmin; j <= jmax; j++ ) { if ( b[i+j*m] != 1 ) { all_ones = 0; } } if ( !all_ones ) { for ( j = jmin; j <= jmax; j++ ) { printf ( "%8d ", b[i+j*m] ); } printf ( "\n" ); } if ( jmax == n-1 && i == m-1 ) { } else { printf ( "\n" ); } } } return; } /******************************************************************************/ void regro_next ( int *done, int n, int v[], int vmax[] ) /******************************************************************************/ /* Purpose: regro_next() computes restricted growth functions one at a time. Discussion: A restricted growth function on N is a vector (V(1), ..., V(N) ) of values V(I) between 1 and N, satisfying the requirements: V(1) = 1; V(I) <= 1 + max ( V(1), V(2), ..., V(I-1) ). The number of restricted growth functions on N is equal to the Bell number B(N). There is a bijection between restricted growth functions on N and set partitions of N. Example: The 15 restricted growth functions for N = 4 are: (1111), (1112), (1121), (1122), (1123), (1211), (1212), (1213), (1221), (1222), (1223), (1231), (1232), (1233), (1234). Licensing: This code is distributed under the MIT license. Modified: 01 April 2009 Author: John Burkardt. Reference: Dennis Stanton, Dennis White, Constructive Combinatorics, Springer, 1986, ISBN: 0387963472, LC: QA164.S79. Parameters: Input/output, int *DONE. On first call, set DONE to TRUE, and then do not alter it. On output, DONE will be FALSE if the routine has computed another restricted growth function, or TRUE if all the restricted growth functions have been returned. Input, int N, the number of components in the restricted growth function. Input/output, int V[N]. The user need not set this quantity before the initial call, and should not alter it between successive calls. On each return from the routine, with DONE = .FALSE., V will contain the componentwise values of the next restricted growth function. Input/output, int VMAX[N]. The user need not set this quantity before the initial call, and should not alter it between calls. VMAX(I) records the largest value that component V(I) could take, given the values of components 1 through I-1. */ { int i; int j; /* First call: */ if ( *done ) { for ( i = 0; i < n; i++ ) { v[i] = 1; } vmax[0] = 1; for ( i = 1; i < n; i++ ) { vmax[i] = 2; } *done = 0; } /* Later calls. */ else { j = n; for ( ; ; ) { if ( j == 1 ) { *done = 1; return; } if ( v[j-1] != vmax[j-1] ) { break; } j = j - 1; } v[j-1] = v[j-1] + 1; for ( i = j+1; i <= n; i++ ) { v[i-1] = 1; if ( v[j-1] == vmax[j-1] ) { vmax[i-1] = vmax[j-1] + 1; } else { vmax[i-1] = vmax[j-1]; } } } return; } /******************************************************************************/ void rfrac_to_cfrac ( int m, double p[], double q[], double t[], int *error ) /******************************************************************************/ /* Purpose: rfrac_to_cfrac() convert rational polynomial fraction to continued fraction. Discussion: That is, it accepts P(1) + P(2) * X + ... + P(M) * X^(M-1) ------------------------------------------------------- Q(1) + Q(2) * X + ... + Q(M) * X^(M-1) + Q(M+1) * X^M and returns the equivalent continued fraction: 1 / (T(1) + X/(T(2) + X/(...T(2*M-1)+X/(T(2*M) ... ))) Licensing: This code is distributed under the MIT license. Modified: 01 April 2009 Author: Original FORTRAN77 version by John Hart, Ward Cheney, Charles Lawson, Hans Maehly, Charles Mesztenyi, John Rice, Henry Thatcher, Christoph Witzgall. This version by John Burkardt. Reference: John Hart, Ward Cheney, Charles Lawson, Hans Maehly, Charles Mesztenyi, John Rice, Henry Thatcher, Christoph Witzgall, Computer Approximations, Wiley, 1968. Parameters: Input, int M, defines the number of P coefficients, and is one less than the number of Q coefficients, and one half the number of T coefficients. Input, double P[M], Q[M+1], the coefficients defining the rational polynomial fraction. Output, double T[2*M], the coefficients defining the continued fraction. Output, int *ERROR, is TRUE if an error occurred. */ { double *a; int i; int k; double ta; a = ( double * ) malloc ( (m+1)*(2*m+1) * sizeof ( double ) ); *error = 0; for ( i = 0; i <= m; i++ ) { a[i+0*(m+1)] = q[i]; } for ( i = 0; i < m; i++ ) { a[i+1*(m+1)] = p[i]; } t[0] = a[0+0*(m+1)] / a[0+1*(m+1)]; ta = a[m+0*(m+1)]; for ( i = 1; i <= m; i++ ) { a[m-i+(2*i)*(m+1)] = ta; } for ( k = 1; k <= 2*m-2; k++ ) { for ( i = 1; i <= (2*m-k)/2; i++ ) { a[i-1+(k+1)*(m+1)] = a[i+(k-1)*(m+1)] - t[k-1] * a[i+k*(m+1)]; } if ( a[0+(k+1)*(m+1)] == 0.0 ) { *error = 1; printf ( "\n" ); printf ( "RFRAC_TO_CFRAC - Warning!\n" ); printf ( " A[0,K+1] is zero for K = %d\n", k ); return; } t[k] = a[0+k*(m+1)] / a[0+(k+1)*(m+1)]; } t[2*m-1] = a[0+(2*m-1)*(m+1)] / a[0+(2*m)*(m+1)]; free ( a ); return; } /******************************************************************************/ void rfrac_to_jfrac ( int m, double p[], double q[], double r[], double s[] ) /******************************************************************************/ /* Purpose: rfrac_to_jfrac() converts a rational polynomial fraction to a J fraction. Discussion: The routine accepts P(1) + P(2) * X + ... + P(M) * X^(M-1) ------------------------------------------------------- Q(1) + Q(2) * X + ... + Q(M) * X^(M-1) + Q(M+1) * X^M and returns the equivalent J-fraction: R(1) / ( X + S(1) + R(2) / ( X + S(2) + R(3) / ... + R(M) / ( X + S(M) )... )) Thanks to Henry Amuasi for noticing and correcting an error in a previous formulation of this routine, 02 October 2010. Licensing: This code is distributed under the MIT license. Modified: 02 October 2010 Author: Original FORTRAN77 version by John Hart, Ward Cheney, Charles Lawson, Hans Maehly, Charles Mesztenyi, John Rice, Henry Thatcher, Christoph Witzgall. This version by John Burkardt. Reference: John Hart, Ward Cheney, Charles Lawson, Hans Maehly, Charles Mesztenyi, John Rice, Henry Thatcher, Christoph Witzgall, Computer Approximations, Wiley, 1968. Parameters: Input, int M, defines the number of P, R, and S coefficients, and is one less than the number of Q coefficients. 1 <= M. Input, double P[M], Q[M+1], the coefficients defining the rational polynomial fraction. Output, double R[M], S[M], the coefficients defining the J-fraction. */ { double *a; int i; int k; if ( m < 1 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "RFRAC_TO_JFRAC(): Fatal error!\n" ); fprintf ( stderr, " Input M < 1.\n" ); exit ( 1 ); } a = ( double * ) malloc ( (m+1) * (m+1) * sizeof ( double ) ); for ( i = 0; i <= m; i++ ) { a[i+0*(m+1)] = q[i]; } for ( i = 0; i < m; i++ ) { a[i+1*(m+1)] = p[i]; } if ( 1 < m ) { r[0] = a[m-1+1*(m+1)] / a[m+0*(m+1)]; s[0] = ( r[0] * a[m-1+0*(m+1)] - a[m-2+1*(m+1)] ) / a[m-1+1*(m+1)]; for ( k = 0; k < m - 2; k++ ) { a[0+(k+2)*(m+1)] = r[k] * a[0+k*(m+1)] - s[k] * a[0+(k+1)*(m+1)]; /* Not sure about upper limit here... */ for ( i = 1; i < m - k; i++ ) { a[i+(k+2)*(m+1)] = r[k] * a[i+k*(m+1)] - a[i-1+(k+1)*(m+1)] - s[k] * a[i+(k+1)*(m+1)]; } if ( a[m-2-k+(k+2)*(m+1)] == 0.0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "RFRAC_TO_JFRAC(): Fatal error!\n" ); fprintf ( stderr, " A[M-2-K,K+2] = 0 for K = %d\n", k ); exit ( 1 ); } r[k+1] = a[m-k-2+(k+2)*(m+1)] / a[m-2-k+1+(k+1)*(m+1)]; s[k+1] = ( r[k+1] * a[m-2-k+(k+1)*(m+1)] - a[m-2-k-1+(k+2)*(m+1)] ) / a[m-2-k+(k+2)*(m+1)]; } a[0+m*(m+1)] = r[m-2] * a[0+(m-2)*(m+1)] - s[m-2] * a[0+(m-1)*(m+1)]; } r[m-1] = a[0+m*(m+1)] / a[1+(m-1)*(m+1)]; s[m-1] = a[0+(m-1)*(m+1)] / a[1+(m-1)*(m+1)]; free ( a ); return; } /******************************************************************************/ int s_len_trim ( char *s ) /******************************************************************************/ /* Purpose: s_len_trim() returns the length of a string to the last nonblank. Discussion: It turns out that I also want to ignore the '\n' character! Licensing: This code is distributed under the MIT license. Modified: 05 October 2014 Author: John Burkardt Parameters: Input, char *S, a pointer to a string. Output, int S_LEN_TRIM, the length of the string to the last nonblank. If S_LEN_TRIM is 0, then the string is entirely blank. */ { int n; char *t; n = strlen ( s ); t = s + strlen ( s ) - 1; while ( 0 < n ) { if ( *t != ' ' && *t != '\n' ) { return n; } t--; n--; } return n; } /******************************************************************************/ void schroeder ( int n, int s[] ) /******************************************************************************/ /* Purpose: schroeder() generates the Schroeder numbers. Discussion: The Schroeder number S(N) counts the number of ways to insert parentheses into an expression of N items, with two or more items within a parenthesis. The Catalan number C(N) counts the number of ways to legally arrange a set of N left and N right parentheses. The formula is: S(N) = ( P(N)(3.0) - 3 P(N-1)(3.0) ) / ( 4 * ( N - 1 ) ) where P(N)(X) is the N-th Legendre polynomial. Example: N = 4 1234 12(34) 1(234) 1(2(34)) 1(23)4 1((23)4) (123)4 (12)34 (12)(34) (1(23))4 ((12)3)4 First Values: 1 1 3 11 45 197 903 4279 20793 103049 518859 2646723 13648869 71039373 Recursion: S(1) = 1 S(2) = 1 S(N) = ( ( 6 * N - 9 ) * S(N-1) - ( N - 3 ) * S(N-2) ) / N Licensing: This code is distributed under the MIT license. Modified: 27 March 2009 Author: John Burkardt Reference: R P Stanley, Hipparchus, Plutarch, Schroeder, and Hough, American Mathematical Monthly, Volume 104, Number 4, 1997, pages 344-350. Laurent Habsieger, Maxim Kazarian, Sergei Lando, On the Second Number of Plutarch, American Mathematical Monthly, May 1998, page 446. Parameters: Input, int N, the number of Schroeder numbers desired. Output, int S[N], the Schroeder numbers. */ { int i; if ( n <= 0 ) { return; } s[0] = 1; if ( n <= 1 ) { return; } s[1] = 1; if ( n <= 2 ) { return; } for ( i = 3; i <= n; i++ ) { s[i-1] = ( ( 6 * i - 9 ) * s[i-2] - ( i - 3 ) * s[i-3] ) / i; } return; } /******************************************************************************/ void sort_heap_external ( int n, int *indx, int *i, int *j, int isgn, int *i1, int *j1, int *k0, int *k1, int *n1 ) /******************************************************************************/ /* Purpose: sort_heap_external() externally sorts a list of items into ascending order. Discussion: The actual list is not passed to the routine. Hence it may consist of integers, reals, numbers, names, etc. The user, after each return from the routine, will be asked to compare or interchange two items. The current version of this code mimics the FORTRAN version, so the values of I and J, in particular, are FORTRAN indices. Licensing: This code is distributed under the MIT license. Modified: 15 June 2015 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the length of the input list. Input/output, int *INDX. The user must set INDX to 0 before the first call. On return, if INDX is greater than 0, the user must interchange items I and J and recall the routine. If INDX is less than 0, the user is to compare items I and J and return in ISGN a negative value if I is to precede J, and a positive value otherwise. If INDX is 0, the sorting is done. Output, int *I, *J. On return with INDX positive, elements I and J of the user's list should be interchanged. On return with INDX negative, elements I and J are to be compared by the user. Input, int ISGN. On return with INDX negative, the user should compare elements I and J of the list. If item I is to precede item J, set ISGN negative, otherwise set ISGN positive. Input/output, int I1, J1, K0, K1, N1, variables that are used for bookkeeping. The user should declare them, and pass the output values from one call as input values on the next call. The user should not change these variables. */ { /* INDX = 0: This is the first call. */ if ( *indx == 0 ) { *i1 = 0; *j1 = 0; *k0 = n / 2; *k1 = n / 2; *n1 = n; } /* INDX < 0: The user is returning the results of a comparison. */ else if ( *indx < 0 ) { if ( *indx == -2 ) { if ( isgn < 0 ) { *i1 = *i1 + 1; } *j1 = *k1; *k1 = *i1; *indx = -1; *i = *i1; *j = *j1; return; } if ( 0 < isgn ) { *indx = 2; *i = *i1; *j = *j1; return; } if ( *k0 <= 1 ) { if ( *n1 == 1 ) { *i1 = 0; *j1 = 0; *indx = 0; } else { *i1 = *n1; *j1 = 1; *n1 = *n1 - 1; *indx = 1; } *i = *i1; *j = *j1; return; } *k0 = *k0 - 1; *k1 = *k0; } /* 0 < INDX: the user was asked to make an interchange. */ else if ( *indx == 1 ) { *k1 = *k0; } for ( ; ; ) { *i1 = 2 * ( *k1 ); if ( *i1 == *n1 ) { *j1 = *k1; *k1 = *i1; *indx = -1; *i = *i1; *j = *j1; return; } else if ( *i1 < *n1 ) { *j1 = *i1 + 1; *indx = -2; *i = *i1; *j = *j1; return; } if ( *k0 <= 1 ) { break; } *k0 = *k0 - 1; *k1 = *k0; } if ( *n1 == 1 ) { *i1 = 0; *j1 = 0; *indx = 0; *i = *i1; *j = *j1; } else { *i1 = *n1; *j1 = 1; *n1 = *n1 - 1; *indx = 1; *i = *i1; *j = *j1; } return; } /******************************************************************************/ void subcomp_next ( int n, int k, int a[], int *more, int *h, int *t, int *n2, int *more2 ) /******************************************************************************/ /* Purpose: subcomp_next() computes the next subcomposition of N into K parts. Discussion: A composition of the integer N into K parts is an ordered sequence of K nonnegative integers which sum to a value of N. A subcomposition of the integer N into K parts is a composition of M into K parts, where 0 <= M <= N. Licensing: This code is distributed under the MIT license. Modified: 07 June 2015 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the integer whose subcompositions are desired. Input, int K, the number of parts in the subcomposition. Input/output, int A[K], the parts of the subcomposition. Input/output, int *MORE, set by the user to start the computation, and by the routine to terminate it. Input/output, int *H, *T, *N2, internal parameters needed for the computation. The user should allocate space for these in the calling program, include them in the calling sequence, but never alter them! */ { int i; /* The first computation. */ if ( !( *more ) ) { for ( i = 0; i < k; i++ ) { a[i] = 0; } *more = 1; *h = 0; *t = 0; *n2 = 0; *more2 = 0; } /* Do the next element at the current value of N. */ else if ( *more2 ) { comp_next ( *n2, k, a, more2, h, t ); } else { *more2 = 0; *n2 = *n2 + 1; comp_next ( *n2, k, a, more2, h, t ); } /* Termination occurs if MORE2 = FALSE and N2 = N. */ if ( ! ( *more2 ) && *n2 == n ) { *more = 0; } return; } /******************************************************************************/ void subcompnz_next ( int n, int k, int a[], int *more, int *h, int *t, int *n2, int *more2 ) /******************************************************************************/ /* Purpose: subcompnz_next() computes the next subcomposition of N into K nonzero parts. Discussion: A composition of the integer N into K nonzero parts is an ordered sequence of K positive integers which sum to a value of N. A subcomposition of the integer N into K nonzero parts is a composition of M into K nonzero parts, where 0 < M <= N. Licensing: This code is distributed under the MIT license. Modified: 07 June 2015 Author: John Burkardt Parameters: Input, int N, the integer whose subcompositions are desired. Input, int K, the number of parts in the subcomposition. K must be no greater than N. Input/output, int A[K], the parts of the subcomposition. Input/output, int *MORE, set by the user to start the computation, and by the routine to terminate it. Input/output, int *H, *T, *N2, internal parameters needed for the computation. The user should allocate space for these in the calling program, include them in the calling sequence, but never alter them! */ { int i; if ( n < k ) { for ( i = 0; i < k; i++ ) { a[i] = -1; } return; } /* The first computation. */ if ( !( *more ) ) { for ( i = 0; i < k; i++ ) { a[i] = 1; } *more = 1; *h = 0; *t = 0; *n2 = k; *more2 = 0; } /* Do the next element at the current value of N. */ else if ( *more2 ) { compnz_next ( *n2, k, a, more2, h, t ); } else { *more2 = 0; *n2 = *n2 + 1; compnz_next ( *n2, k, a, more2, h, t ); } /* Termination occurs if MORE2 = FALSE and N2 = N. */ if ( ! ( *more2 ) && *n2 == n ) { *more = 0; } return; } /******************************************************************************/ void subcompnz2_next ( int n_lo, int n_hi, int k, int a[], int *more, int *h, int *t, int *n2, int *more2 ) /******************************************************************************/ /* Purpose: subcompnz2_next() computes the next subcomposition of N into K nonzero parts. Discussion: A composition of the integer N into K nonzero parts is an ordered sequence of K positive integers which sum to a value of N. A subcomposition of the integer N into K nonzero parts is a composition of M into K nonzero parts, where 0 < M <= N. This routine computes all compositions of K into nonzero parts which sum to values between N_LO and N_HI. The routine subcompnz_next() can be regarded as a special case where N_LO = K. Licensing: This code is distributed under the MIT license. Modified: 07 June 2015 Author: John Burkardt Parameters: Input, int N_LO, N_HI, the range of values of N for which compositions are desired. N_LO must be no greater than N_HI. Input, int K, the number of parts in the subcomposition. K must be no greater than N_HI. Input/output, int A[K], the parts of the subcomposition. Input/output, int *MORE, set by the user to start the computation, and by the routine to terminate it. Input/output, int *H, *T, *N2, internal parameters needed for the computation. The user should allocate space for these in the calling program, include them in the calling sequence, but never alter them! Input/output, int *MORE2, an internal parameter needed for the computation. The user should allocate space for it in the calling program, include it in the calling sequence, but never alter it! */ { int i; if ( n_hi < k ) { for ( i = 0; i < k; i++ ) { a[i] = -1; } return; } if ( n_hi < n_lo ) { for ( i = 0; i < k; i++ ) { a[i] = -1; } return; } /* The first computation. */ if ( !(*more) ) { *more = 1; *h = 0; *t = 0; *n2 = i4_max ( k, n_lo ); *more2 = 0; compnz_next ( *n2, k, a, more2, h, t ); } /* Do the next element at the current value of N. */ else if ( *more2 ) { compnz_next ( *n2, k, a, more2, h, t ); } else { *n2 = *n2 + 1; compnz_next ( *n2, k, a, more2, h, t ); } /* Termination occurs if MORE2 = FALSE and N2 = N_HI. */ if ( ! ( *more2 ) && *n2 == n_hi ) { *more = 0; } return; } /******************************************************************************/ void subset_by_size_next ( int n, int a[], int *subsize, int *more, int *more2, int *m, int *m2 ) /******************************************************************************/ /* Purpose: subset_by_size_next() returns all subsets of an N set, in order of size. Example: N = 4: 1 2 3 4 1 2 3 1 2 4 1 3 4 1 3 1 4 2 3 1 2 3 (the empty set) Discussion: The subsets are returned in decreasing order of size, with the empty set last. For a given size K, the K subsets are returned in lexicographic order. Licensing: This code is distributed under the MIT license. Modified: 09 June 2015 Author: John Burkardt Parameters: Input, int N, the size of the set. Input/output, int A[N]. The entries A(1:SUBSIZE) contain the elements of the subset. The elements are given in ascending order. Output, int *SUBSIZE, the number of elements in the subset. Input/output, int *MORE. Set MORE = FALSE before first call for a new sequence of subsets. It then is set and remains TRUE as long as the subset computed on this call is not the final one. When the final subset is computed, MORE is set to FALSE as a signal that the computation is done. Input/output, int *MORE2, a variable for bookkeeping. The user should declare this variable, but need not initialize it. The output value from one call must be the input value for the next. Input/output, int *M, *M2, variables for bookkeeping. The user should declare this variable, but need not initialize it. The output value from one call must be the input value for the next. */ { if ( ! ( *more ) ) { *subsize = n; *more = 1; *more2 = 0; *m = 0; *m2 = 0; } else if ( ! ( *more2 ) ) { *subsize = *subsize - 1; } /* Compute the next subset of size SUBSIZE. */ if ( 0 < *subsize ) { ksub_next ( n, *subsize, a, more2, m, m2 ); } else if ( *subsize == 0 ) { *more = 0; } return; } /******************************************************************************/ void subset_gray_next ( int n, int a[], int *more, int *ncard, int *iadd ) /******************************************************************************/ /* Purpose: subset_gray_next() generates all subsets of a set of order N, one at a time. Discussion: It generates the subsets one at a time, by adding or subtracting exactly one element on each step. The user should set MORE = .FALSE. and the value of N before the first call. On return, the user may examine A which contains the definition of the new subset, and must check .MORE., because as soon as it is .FALSE. on return, all the subsets have been generated and the user probably should cease calling. The first set returned is the empty set. Licensing: This code is distributed under the MIT license. Modified: 01 April 2009 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the order of the total set from which subsets will be drawn. Input/output, int A[N]. On each return, the Gray code for the newly generated subset. A[I] = 0 if element I is in the subset, 1 otherwise. Input/output, int *MORE. Set this variable FALSE before the first call. Normally, MORE will be returned TRUE but once all the subsets have been generated, MORE will be reset FALSE on return and you should stop calling the program. Input/output, int *NCARD, the cardinality of the set returned, which may be any value between 0 (the empty set) and N (the whole set). Output, int *IADD, the element which was added or removed to the previous subset to generate the current one. Exception: the empty set is returned on the first call, and IADD is set to -1. */ { int i; /* First set returned is the empty set. */ if ( !(*more) ) { for ( i = 0; i < n; i++ ) { a[i] = 0; } *more = 1; *ncard = 0; *iadd = -1; } else { *iadd = 1; if ( ( *ncard % 2 ) != 0 ) { for ( ; ; ) { *iadd = *iadd + 1; if ( a[*iadd-2] != 0 ) { break; } } } a[*iadd-1] = 1 - a[*iadd-1]; *ncard = *ncard + 2 * a[*iadd-1] - 1; /* Last set returned is the singleton A(N). */ if ( *ncard == a[n-1] ) { *more = 0; } } return; } /******************************************************************************/ int subset_gray_rank ( int n, int a[] ) /******************************************************************************/ /* Purpose: subset_gray_rank() ranks a subset of an N set, using the Gray code ordering. Example: N = 4 A Rank ------- ----- 0 0 0 0 1 0 0 0 1 2 0 0 1 1 3 0 0 1 0 4 0 1 1 0 5 0 1 1 1 6 0 1 0 1 7 0 1 0 0 8 1 1 0 0 9 1 1 0 1 10 1 1 1 1 11 1 1 1 0 12 1 0 1 0 13 1 0 1 1 14 1 0 0 1 15 1 0 0 0 16 Licensing: This code is distributed under the MIT license. Modified: 01 April 2009 Author: John Burkardt Parameters: Input, int N, the order of the total set from which subsets will be drawn. Input, int A[N]; A(I) is 1 if element I is in the set, and 0 otherwise. Output, int SUBSET_GRAY_RANK, the rank of the subset in the Gray code ordering. */ { unsigned int ugray; int rank; ugray = ubvec_to_ui4 ( n, a ); rank = gray_rank ( ( int ) ugray ); rank = rank + 1; return rank; } /******************************************************************************/ void subset_gray_unrank ( int rank, int n, int a[] ) /******************************************************************************/ /* Purpose: subset_gray_unrank() produces a subset of an N set of the given Gray code rank. Example: N = 4 Rank A ----- ------- 1 0 0 0 0 2 0 0 0 1 3 0 0 1 1 4 0 0 1 0 5 0 1 1 0 6 0 1 1 1 7 0 1 0 1 8 0 1 0 0 9 1 1 0 0 10 1 1 0 1 11 1 1 1 1 12 1 1 1 0 13 1 0 1 0 14 1 0 1 1 15 1 0 0 1 16 1 0 0 0 Licensing: This code is distributed under the MIT license. Modified: 30 December 2014 Author: John Burkardt Parameters: Input, int RANK, the rank of the subset in the Gray code ordering. Input, int N, the order of the total set from which subsets will be drawn. Output, int A[N]; A(I) is 1 if element I is in the set, and 0 otherwise. */ { unsigned int gray; gray = ( unsigned int ) gray_unrank ( rank - 1 ); ui4_to_ubvec ( gray, n, a ); return; } /******************************************************************************/ void subset_lex_next ( int n, int jmp, int ndim, int *k, int a[] ) /******************************************************************************/ /* Purpose: subset_lex_next() generates the subsets of a set of N elements, one at a time. Discussion: The subsets are generated in lexicographical order. The routine can also be forced to generate only those subsets whose size is no greater than some user-specified maximum. Example: N = 5, JMP = ( K == 3 ) 1 1 2 1 2 3 1 2 4 1 2 5 1 3 1 3 4 1 3 5 1 4 1 4 5 1 5 2 2 3 2 3 4 2 3 5 2 4 2 4 5 2 5 3 3 4 3 4 5 3 5 4 4 5 5 empty set. Licensing: This code is distributed under the MIT license. Modified: 01 April 2009 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the order of the main set from which subsets are chosen. Input, int JMP. In the simplest case, set JMP = .FALSE. for a normal computation. But to jump over supersets of the input set, set JMP = TRUE. Setting JMP = ( K == 3 ) before every new call will, for example, force all the subsets returned to have cardinality 3 or less. Input, int NDIM, the allowed storage for A. If NDIM < N, JMP must be used to avoid creation of a subset too large to store in A. Input/output, int *K. On first call, the user must set K = 0 as a startup signal to the program. Thereafter, the routine returns the size of the computed subset in K. On the last return, the empty set is returned and K is 0, which is a signal to the user that the computation is complete. Input/output, int A[NDIM]. A(I) is the I-th element of the subset, listed in increasing order, with 0's in entries beyond entry K. */ { int is; if ( *k <= 0 ) { if ( jmp ) { return; } is = 0; *k = 1; a[0] = 1; } else if ( a[*k-1] != n ) { is = a[*k-1]; if ( !jmp ) { *k = *k + 1; } a[*k-1] = is + 1; } else { *k = *k - 1; if ( *k != 0 ) { a[*k-1] = a[*k-1] + 1; } } return; } /******************************************************************************/ void subset_random ( int n, int *seed, int a[] ) /******************************************************************************/ /* Purpose: subset_random() selects a random subset of an N-set. Licensing: This code is distributed under the MIT license. Modified: 02 May 2003 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the size of the full set. Input/output, int *SEED, a seed for the random number generator. Output, int A[N]. A vector to hold the information about the set chosen. On return, if A[I] = 1, then I is in the random subset, otherwise, A[I] = 0 and I is not in the random subset. */ { int i; for ( i = 0; i < n; i++ ) { a[i] = i4_uniform_ab ( 0, 1, seed ); } return; } /******************************************************************************/ void subtriangle_next ( int n, int *more, int *i1, int *j1, int *i2, int *j2, int *i3, int *j3 ) /******************************************************************************/ /* Purpose: subtriangle_next() computes the next subtriangle of a triangle. Discussion: The three sides of a triangle have been subdivided into N segments, inducing a natural subdivision of the triangle into N*N subtriangles. It is desired to consider each subtriangle, one at a time, in some definite order. This routine can produce information defining each of the subtriangles, one after another. The subtriangles are described in terms of the integer coordinates (I,J) of their vertices. These coordinates both range from 0 to N, with the additional restriction that I + J <= N. The vertices of each triangle are listed in counterclockwise order. Example: N = 4 4 * |\ 16\ 3 *--* |14|\ 13\15\ 2 *--*--* |\9|11|\ |8\10\12\ 1 *--*--*--* |\2|\4|\6|\ |1\|3\|5\|7\ 0 *--*--*--*--* 0 1 2 3 4 Rank I1 J1 I2 J2 I3 J3 ---- ----- ----- ----- 1 0 0 1 0 0 1 2 1 1 0 1 1 0 3 1 0 2 0 1 1 4 2 1 1 1 2 0 5 2 0 3 0 2 1 6 3 1 1 1 3 0 7 3 0 4 0 3 1 8 0 1 1 1 0 2 9 1 2 0 2 1 1 10 1 1 2 1 1 2 11 2 2 1 2 2 1 12 2 1 3 1 2 2 13 0 2 1 2 0 3 14 1 3 0 3 1 2 15 1 2 2 2 1 3 16 0 3 1 3 0 4 Licensing: This code is distributed under the MIT license. Modified: 01 April 2009 Author: John Burkardt Parameters: Input, int N, indicates the number of subdivisions of each side of the original triangle. Input/output, int *MORE. On first call, set MORE to FALSE. Thereafter, the output value of MORE will be TRUE if there are more subtriangles that can be generated by further calls. However, if MORE is returned as FALSE, the accompanying subtriangle information refers to the last subtriangle that can be generated. Input/output, int *I1, *J1, *I2, *J2, *I3, *J3, the indices of the vertices of the subtriangle. */ { if ( n <= 0 ) { *more = 0; return; } if ( ! ( *more ) ) { *i1 = 0; *j1 = 0; *i2 = 1; *j2 = 0; *i3 = 0; *j3 = 1; if ( n == 1 ) { *more = 0; } else { *more = 1; } } /* We last generated a triangle like: 2---1 \ | \ | \| 3 */ else if ( *i2 < *i3 ) { *i1 = *i3; *j1 = *j3; *i2 = *i1 + 1; *j2 = *j1; *i3 = *i1; *j3 = *j1 + 1; } /* We last generated a triangle like 3 |\ | \ | \ 1---2 */ else if ( *i1 + 1 + *j1 + 1 <= n ) { *i1 = *i1 + 1; *j1 = *j1 + 1; *i2 = *i1 - 1; *j2 = *j1; *i3 = *i1; *j3 = *j1 - 1; } /* We must be at the end of a row. */ else { *i1 = 0; *j1 = *j1 + 1; *i2 = *i1 + 1; *j2 = *j1; *i3 = *i1; *j3 = *j1 + 1; if ( n <= *j1 + 1 ) { *more = 0; } } return; } /******************************************************************************/ void thue_binary_next ( int *n, int thue[] ) /******************************************************************************/ /* Purpose: thue_binary_next() returns the next element in a binary Thue sequence. Discussion: Thue demonstrated that arbitrarily long sequences of 0's and 1's could be generated which had the "cubefree" property. In other words, for a given string S, there was no substring W such that S contained "WWW". In fact, a stronger result holds: if "a" is the first letter of W, it is never the case that S contains the substring "WWa". In this example, the digits allowed are binary, that is, just "0" and "1". The replacement rules are: "0" -> "01" "1" -> "10" This routine produces the next binary Thue sequence in a given series. However, the input sequence must be a Thue sequence in order for us to guarantee that the output sequence will also have the cubic nonrepetition property. Also, enough space must be set aside in THUE to hold the output sequence. This will always be twice the input value of N. Licensing: This code is distributed under the MIT license. Modified: 23 March 2009 Author: John Burkardt Parameters: Input/output, int *N. On input, the length of the input sequence. On output, the length of the output sequence. Input, int THUE[*N]. On input, the initial Thue sequence, and on output, the result of applying the substitution rules once. */ { int i; int n_out; int *thue_out; n_out = 0; thue_out = ( int * ) malloc ( 2 * (*n) * sizeof ( int ) ); for ( i = 0; i < *n; i++ ) { if ( thue[i] == 0 ) { thue_out[n_out] = 0; n_out = n_out + 1; thue_out[n_out] = 1; n_out = n_out + 1; } else if ( thue[i] == 1 ) { thue_out[n_out] = 1; n_out = n_out + 1; thue_out[n_out] = 0; n_out = n_out + 1; } else { fprintf ( stderr, "\n" ); fprintf ( stderr, "THUE_BINARY_NEXT(): Fatal error!\n" ); fprintf ( stderr, " The input sequence contains a non-binary digit\n" ); fprintf ( stderr, " THUE[%d] = %d\n", i, thue[i] ); exit ( 1 ); } } *n = n_out; for ( i = 0; i < *n; i++ ) { thue[i] = thue_out[i]; } free ( thue_out ); return; } /******************************************************************************/ void thue_ternary_next ( int *n, int thue[] ) /******************************************************************************/ /* Purpose: thue_ternary_next() returns the next element in a ternary Thue sequence. Discussion: Thue was interested in showing that there were arbitrarily long sequences of digits which never displayed a pair of contiguous repetitions of any length. That is, there was no occurrence of "00" or "1010" or "121121", anywhere in the string. This makes the string "squarefree". To do this, he demonstrated a way to start with a single digit, and to repeatedly apply a series of transformation rules to each digit of the sequence, deriving nonrepeating sequences of ever greater length. In this example, the digits allowed are ternary, that is, just "0", "1" and "2". The replacement rules are: "0" -> "12" "1" -> "102" "2" -> "0" This routine produces the next Thue sequence in a given series. However, the input sequence must be a Thue sequence in order for us to guarantee that the output sequence will also have the nonrepetition property. Also, enough space must be set aside in THUE to hold the output sequence. This will never be more than 3 times the input value of N. Licensing: This code is distributed under the MIT license. Modified: 23 March 2009 Author: John Burkardt Reference: Brian Hayes, Third Base, American Scientist, Volume 89, Number 6, pages 490-494, November-December 2001. Parameters: Input/output, int *N. On input, the length of the input sequence. On output, the length of the output sequence. Input, int THUE[*N]. On input, the initial Thue sequence, and on output, the result of applying the substitution rules once. */ { int i; int n_out; int *thue_out; n_out = 0; thue_out = ( int * ) malloc ( 3 * (*n) * sizeof ( int ) ); for ( i = 0; i < *n; i++ ) { if ( thue[i] == 0 ) { thue_out[n_out] = 1; n_out = n_out + 1; thue_out[n_out] = 2; n_out = n_out + 1; } else if ( thue[i] == 1 ) { thue_out[n_out] = 1; n_out = n_out + 1; thue_out[n_out] = 0; n_out = n_out + 1; thue_out[n_out] = 2; n_out = n_out + 1; } else if ( thue[i] == 2 ) { thue_out[n_out] = 0; n_out = n_out + 1; } else { fprintf ( stderr, "\n" ); fprintf ( stderr, "THUE_TERNARY_NEXT(): Fatal error!\n" ); fprintf ( stderr, " The input sequence contains a non-ternary digit\n" ); fprintf ( stderr, " THUE[%d] = %d\n", i, thue[i] ); exit ( 1 ); } } *n = n_out; for ( i = 0; i < n_out; i++ ) { thue[i] = thue_out[i]; } free ( thue_out ); return; } /******************************************************************************/ void triang ( int n, int zeta[], int p[] ) /******************************************************************************/ /* Purpose: triang() renumbers elements in accordance with a partial ordering. Discussion: TRIANG is given a partially ordered set. The partial ordering is defined by a matrix ZETA, where element I is partially less than or equal to element J if and only if ZETA(I,J) = 1. TRIANG renumbers the elements with a permutation P so that if element I is partially less than element J in the partial ordering, then P(I) < P(J) in the usual, numerical ordering. In other words, the elements are relabeled so that their labels reflect their ordering. This is equivalent to relabeling the matrix so that, on unscrambling it, the matrix would be upper triangular. Calling I4MAT_2PERM0 or R8MAT_2PERM0 with P used for both the row and column permutations applied to matrix ZETA will result in an upper triangular matrix. Licensing: This code is distributed under the MIT license. Modified: 11 June 2015 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int N, the number of elements in the set. Input, int ZETA[N*N], describes the partial ordering. ZETA[I,J] =: 0, for diagonal elements (I = J), or for unrelated elements, or if J << I. 1, if I << J. Output, int P[N], a permutation of the elements that reflects their partial ordering. P[I] is the new label of element I, with the property that if ZETA[I,J] = 1, that is, I << J, then P[I] < P[J] (in the usual ordering). */ { int i; int error; int iq; int ir; int it; int l; int m; /* Make sure ZETA represents a partially ordered set. In other words, if ZETA(I,J) = 1, then ZETA(J,I) must NOT be 1. */ error = pord_check ( n, zeta ); if ( error ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "TRIANG(): Fatal error!\n" ); fprintf ( stderr, " The matrix ZETA does not represent a\n" ); fprintf ( stderr, " partial ordering.\n" ); exit ( 1 ); } m = 1; l = 0; for ( i = 0; i < n; i++ ) { p[i] = 0; } it = m + 1; ir = m + 1; for ( ; ; ) { if ( ir <= n ) { if ( p[ir-1] == 0 && zeta[(ir-1)+(m-1)*n] != 0 ) { p[ir-1] = m; m = ir; ir = it; } else { ir = ir + 1; } } else { l = l + 1; iq = p[m-1]; p[m-1] = l; if ( iq != 0 ) { ir = m + 1; m = iq; } else if ( m == n ) { break; } else { for ( ; ; ) { m = m + 1; if ( p[m-1] == 0 ) { break; } if ( m == n ) { for ( i = 0; i < n; i++ ) { p[i] = p[i] - 1; } return; } } it = m + 1; ir = m + 1; } } } /* Decrement the elements of the permutation. */ for ( i = 0; i < n; i++ ) { p[i] = p[i] - 1; } return; } /******************************************************************************/ void tuple_next ( int m1, int m2, int n, int *rank, int x[] ) /******************************************************************************/ /* Purpose: tuple_next() computes the next element of a tuple space. Discussion: The elements are N vectors. Each entry is constrained to lie between M1 and M2. The elements are produced one at a time. The first element is (M1,M1,...,M1), the second element is (M1,M1,...,M1+1), and the last element is (M2,M2,...,M2) Intermediate elements are produced in lexicographic order. Example: N = 2, M1 = 1, M2 = 3 INPUT OUTPUT ------- ------- Rank X Rank X ---- --- ----- --- 0 * * 1 1 1 1 1 1 2 1 2 2 1 2 3 1 3 3 1 3 4 2 1 4 2 1 5 2 2 5 2 2 6 2 3 6 2 3 7 3 1 7 3 1 8 3 2 8 3 2 9 3 3 9 3 3 0 0 0 Licensing: This code is distributed under the MIT license. Modified: 29 April 2003 Author: John Burkardt Parameters: Input, int M1, M2, the minimum and maximum entries. Input, int N, the number of components. Input/output, int *RANK, counts the elements. On first call, set RANK to 0. Thereafter, the output value of RANK will indicate the order of the element returned. When there are no more elements, RANK will be returned as 0. Input/output, int X[N], on input the previous tuple. On output, the next tuple. */ { int i; int j; if ( m2 < m1 ) { *rank = 0; return; } if ( *rank <= 0 ) { for ( i = 0; i < n; i++ ) { x[i] = m1; } *rank = 1; } else { *rank = *rank + 1; i = n - 1; for ( ; ; ) { if ( x[i] < m2 ) { x[i] = x[i] + 1; break; } x[i] = m1; if ( i == 0 ) { *rank = 0; for ( j = 0; j < n; j++ ) { x[j] = m1; } break; } i = i - 1; } } return; } /******************************************************************************/ void tuple_next_fast ( int m, int n, int rank, int base[], int x[] ) /******************************************************************************/ /* Purpose: tuple_next_fast() computes the next element of a tuple space, "fast". Discussion: The elements are N vectors. Each entry is constrained to lie between 1 and M. The elements are produced one at a time. The first element is (1,1,...,1) and the last element is (M,M,...,M) Intermediate elements are produced in lexicographic order. Example: N = 2, M = 3 INPUT OUTPUT ------- ------- Rank X ---- ---- -1 -1 -1 0 1 1 1 1 2 2 1 3 3 2 1 4 2 2 5 2 3 6 3 1 7 3 2 8 3 3 9 1 1 Licensing: This code is distributed under the MIT license. Modified: 04 June 2015 Author: John Burkardt Parameters: Input, int M, the maximum entry in each component. M must be greater than 0. Input, int N, the number of components. N must be greater than 0. Input, int RANK, indicates the rank of the tuples. Typically, 0 <= RANK < N^M; values larger than this are legal and meaningful, and are equivalent to the corresponding value MOD N^M. If RANK < 0, this indicates that this is the first call for the given values of (M,N). Initialization is done, and X is set to a dummy value. Input/output, int BASE[N], a bookkeeping array needed by this procedure. The user should allocate space for this array, but should not alter it between successive calls. Output, int X[N], the next tuple, or a dummy value if initialization is being done. */ { int i; if ( rank < 0 ) { if ( m <= 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "tuple_next_fast(): Fatal error!\n" ); fprintf ( stderr, " The value M <= 0 is not legal.\n" ); fprintf ( stderr, " M = %d\n", m ); exit ( 1 ); } if ( n <= 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "tuple_next_fast(): Fatal error!\n" ); fprintf ( stderr, " The value N <= 0 is not legal.\n" ); fprintf ( stderr, " N = %d\n", n ); exit ( 1 ); } base[n-1] = 1; for ( i = n - 2; 0 <= i; i-- ) { base[i] = base[i+1] * m; } for ( i = 0; i < n; i++ ) { x[i] = -1; } } else { for ( i = 0; i < n; i++ ) { x[i] = ( ( rank / base[i] ) % m ) + 1; } } return; } /******************************************************************************/ void tuple_next_ge ( int m, int n, int *k, int x[] ) /******************************************************************************/ /* Purpose: tuple_next_ge() computes the next "nondecreasing" element of a tuple space. Discussion: The elements are N vectors. Each element is constrained to lie between 1 and M, and to have components that are nondecreasing. That is, for an element X, and any positive K, X(I) <= X(I+K) The elements are produced one at a time. The first element is (1,1,...,1) and the last element is (M,M,...,M) Intermediate elements are produced in lexicographic order. Example: N = 3, M = 3 K X -- ----- 1 1 1 1 2 1 1 2 3 1 1 3 4 1 2 2 5 1 2 3 6 1 3 3 7 2 2 2 8 2 2 3 9 2 3 3 10 3 3 3 Licensing: This code is distributed under the MIT license. Modified: 29 April 2003 Author: Original FORTRAN77 version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt. Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms for Computers and Calculators, Second Edition, Academic Press, 1978, ISBN: 0-12-519260-6, LC: QA164.N54. Parameters: Input, int M, the maximum entry. Input, int N, the number of components. Input/output, int *K, counts the elements. On first call, set K to 0. Thereafter, K will indicate the order of the element returned. When there are no more elements, K will be returned as 0. Input/output, int X[N], on input the previous tuple. On output, the next tuple. */ { int i; int j; if ( m < 1 ) { return; } if ( *k <= 0 ) { for ( j = 0; j < n; j++ ) { x[j] = 1; } *k = 1; return; } for ( i = n-1; 0 <= i; i-- ) { if ( x[i] < m ) { x[i] = x[i] + 1; for ( j = i+1; j < n; j++ ) { x[j] = x[i]; } *k = *k + 1; return; } } *k = 0; for ( j = 0; j < n; j++ ) { x[j] = 0; } return; } /******************************************************************************/ void tuple_next2 ( int n, int xmin[], int xmax[], int x[], int *rank ) /******************************************************************************/ /* Purpose: tuple_next2() computes the next element of an integer tuple space. Discussion: The elements X are N vectors. Each entry X(I) is constrained to lie between XMIN(I) and XMAX(I). The elements are produced one at a time. The first element is (XMIN(1), XMIN(2), ..., XMIN(N)), the second is (probably) (XMIN(1), XMIN(2), ..., XMIN(N)+1), and the last element is (XMAX(1), XMAX(2), ..., XMAX(N)) Intermediate elements are produced in a lexicographic order, with the first index more important than the last, and the ordering of values at a fixed index implicitly defined by the sign of XMAX(I) - XMIN(I). Examples: N = 2, XMIN = (/ 1, 10 /) XMAX = (/ 3, 8 /) RANK X ---- ----- 1 1 10 2 1 9 3 1 8 4 2 10 5 2 9 6 2 8 7 3 10 8 3 9 9 3 8 Licensing: This code is distributed under the MIT license. Modified: 07 June 2008 Author: John Burkardt Parameters: Input, int N, the number of components. Input, int XMIN[N], XMAX[N], the "minimum" and "maximum" entry values. These values are minimum and maximum only in the sense of the lexicographic ordering. In fact, XMIN(I) may be less than, equal to, or greater than XMAX(I). Input/output, int X[N], on input the previous tuple. On output, the next tuple. Input/output, int *RANK, the rank of the item. On first call, set RANK to 0 to start up the sequence. On return, if RANK is zero, there are no more items in the sequence. */ { int i; int test; if ( *rank < 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "tuple_next2(): Fatal error!\n" ); fprintf ( stderr, " Illegal value of RANK = %d\n", *rank ); exit ( 1 ); } test = 1; for ( i = 0; i < n; i++ ) { test = test * ( 1 + abs ( xmax[i] - xmin[i] ) ); } if ( test < *rank ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "tuple_next2(): Fatal error!\n" ); fprintf ( stderr, " Illegal value of RANK = %d\n", *rank ); exit ( 1 ); } if ( *rank == 0 ) { for ( i = 0; i < n; i++ ) { x[i] = xmin[i]; } *rank = 1; return; } *rank = *rank + 1; i = n - 1; for ( ; ; ) { if ( x[i] != xmax[i] ) { if ( xmin[i] < xmax[i] ) { x[i] = x[i] + 1; } else { x[i] = x[i] - 1; } break; } x[i] = xmin[i]; if ( i == 0 ) { *rank = 0; break; } i = i - 1; } return; } /******************************************************************************/ int ubvec_add ( int n, int bvec1[], int bvec2[], int bvec3[] ) /******************************************************************************/ /* Purpose: ubvec_add() adds two unsigned binary vectors. Discussion: A UBVEC is a vector of binary digits representing an unsigned integer. UBVEC[N-1] contains the units digit, UBVEC[N-2] the coefficient of 2, UBVEC[N-3] the coefficient of 4 and so on, so that printing the digits in order gives the binary form of the number. Example: N = 4 UBVEC1 + UBVEC2 = UBVEC3 ( 0 0 0 1 ) + ( 0 0 1 1 ) = ( 0 1 0 0 ) 1 + 3 = 4 Licensing: This code is distributed under the MIT license. Modified: 21 March 2009 Author: John Burkardt Parameters: Input, int N, the length of the vectors. Input, int BVEC1[N], BVEC2[N], the vectors to be added. Output, int BVEC3[N], the sum of the two input vectors. Output, int UBVEC_ADD, is TRUE if an error occurred. */ { int base = 2; int i; int overflow; overflow = 0; for ( i = 0; i < n; i++ ) { bvec3[i] = bvec1[i] + bvec2[i]; } for ( i = n - 1; 0 <= i; i-- ) { while ( base <= bvec3[i] ) { bvec3[i] = bvec3[i] - base; if ( 0 < i ) { bvec3[i-1] = bvec3[i-1] + 1; } else { overflow = 1; } } } return overflow; } /******************************************************************************/ void ubvec_print ( int n, int bvec[], char *title ) /******************************************************************************/ /* Purpose: ubvec_print() prints a UBVEC, with an optional title. Discussion: A UBVEC is a vector of binary digits representing an unsigned integer. UBVEC[N-1] contains the units digit, UBVEC[N-2] the coefficient of 2, UBVEC[N-3] the coefficient of 4 and so on, so that printing the digits in order gives the binary form of the number. Licensing: This code is distributed under the MIT license. Modified: 01 December 2006 Author: John Burkardt Parameters: Input, int N, the number of components of the vector. Input, int BVEC[N], the vector to be printed. Input, char *TITLE, a title to be printed first. TITLE may be blank. */ { int i; int ihi; int ilo; if ( 0 < strlen ( title ) ) { printf ( "\n" ); printf ( "%s\n", title ); } for ( ilo = 0; ilo < n; ilo = ilo + 70 ) { ihi = i4_min ( ilo + 70 - 1, n - 1 ); printf ( " " ); for ( i = ilo; i <= ihi; i++ ) { printf ( "%d", bvec[i] ); } printf ( "\n" ); } return; } /******************************************************************************/ unsigned int ubvec_to_ui4 ( int n, int bvec[] ) /******************************************************************************/ /* Purpose: ubvec_to_ui4() makes an unsigned integer from an unsigned binary vector. Discussion: A UBVEC is a vector of binary digits representing an unsigned integer. UBVEC[N-1] contains the units digit, UBVEC[N-2] the coefficient of 2, UBVEC[N-3] the coefficient of 4 and so on, so that printing the digits in order gives the binary form of the number. Example: N = 4 BVEC binary I ---------- ----- -- 1 2 3 4 ---------- 0 0 0 1 1 1 0 0 1 0 10 2 0 0 1 1 11 3 0 1 0 0 100 4 1 0 0 1 1001 9 1 1 1 1 1111 15 Licensing: This code is distributed under the MIT license. Modified: 21 March 2009 Author: John Burkardt Parameters: Input, int N, the dimension of the vector. Input, int BVEC[N], the binary representation. Input, unsigned int UBVEC_TO_UI4, the integer value. */ { const unsigned int base = 2; int i; unsigned int ui4; ui4 = 0; for ( i = 0; i < n; i++ ) { ui4 = base * ui4 + ( unsigned int ) bvec[i]; } return ui4; } /******************************************************************************/ void ubvec_xor ( int n, int bvec1[], int bvec2[], int bvec3[] ) /******************************************************************************/ /* Purpose: ubvec_xor() computes the exclusive OR of two UBVECs. Discussion: A UBVEC is a vector of binary digits representing an unsigned integer. UBVEC[N-1] contains the units digit, UBVEC[N-2] the coefficient of 2, UBVEC[N-3] the coefficient of 4 and so on, so that printing the digits in order gives the binary form of the number. Licensing: This code is distributed under the MIT license. Modified: 01 December 2006 Author: John Burkardt Parameters: Input, int N, the length of the vectors. Input, int BVEC1[N], BVEC2[N], the vectors to be XOR'ed. Input, int BVEC3[N], the exclusive OR of the two vectors. */ { int i; for ( i = 0; i < n; i++ ) { bvec3[i] = ( bvec1[i] + bvec2[i] ) % 2; } return; } /******************************************************************************/ void ui4_to_ubvec ( unsigned int ui4, int n, int bvec[] ) /******************************************************************************/ /* Purpose: ui4_to_ubvec() makes a unsigned binary vector from an integer. Discussion: A UBVEC is a vector of binary digits representing an unsigned integer. UBVEC[N-1] contains the units digit, UBVEC[N-2] the coefficient of 2, UBVEC[N-3] the coefficient of 4 and so on, so that printing the digits in order gives the binary form of the number. To guarantee that there will be enough space for any value of I, it would be necessary to set N = 32. Example: UI4 BVEC binary 0 1 2 3 4 5 1 2 4 8 16 32 -- ---------------- ------ 1 1 0 0 0 0 1 1 2 0 1 0 0 1 0 10 3 1 1 0 0 1 1 11 4 0 0 0 1 0 0 100 9 0 0 1 0 0 1 1001 57 1 1 1 0 1 1 110111 Licensing: This code is distributed under the MIT license. Modified: 21 March 2009 Author: John Burkardt Parameters: Input, unsigned int UI4, an integer to be represented. Input, int N, the dimension of the vector. Output, int BVEC[N], the binary representation. */ { const unsigned int base = 2; int i; for ( i = n - 1; 0 <= i; i-- ) { bvec[i] = ui4 % base; ui4 = ui4 / base; } return; } /******************************************************************************/ void vec_colex_next ( int dim_num, int base, int a[], int *more ) /******************************************************************************/ /* Purpose: vec_colex_next() generates vectors in colex order. Discussion: The vectors are produced in colexical order, starting with (0,0,...,0), (1,0,...,0), ... (BASE-1,BASE-1,...,BASE-1). Example: DIM_NUM = 2, BASE = 3 0 0 1 0 2 0 0 1 1 1 2 1 0 2 1 2 2 2 Licensing: This code is distributed under the MIT license. Modified: 21 March 2009 Author: John Burkardt Parameters: Input, int DIM_NUM, the spatial dimension. Input, int BASE, the base to be used. BASE = 2 will give vectors of 0's and 1's, for instance. Output, int A[DIM_NUM], the next vector. Input/output, int *MORE. Set this variable false before the first call. On return, MORE is TRUE if another vector has been computed. If MORE is returned FALSE, ignore the output vector and stop calling the routine. */ { int i; if ( !( *more ) ) { for ( i = 0; i < dim_num; i++ ) { a[i] = 0; } *more = 1; } else { for ( i = 0; i < dim_num; i++ ) { a[i] = a[i] + 1; if ( a[i] < base ) { return; } a[i] = 0; } *more = 0; } return; } /******************************************************************************/ void vec_colex_next2 ( int dim_num, int base[], int a[], int *more ) /******************************************************************************/ /* Purpose: vec_colex_next2() generates vectors in colex order. Discussion: The vectors are produced in colexical order, starting with (0, 0, ...,0), (1, 0, ...,0), ... (BASE(1)-1,0, ...,0) (0, 1, ...,0) (1, 1, ...,0) ... (BASE(1)-1,1, ...,0) (0, 2, ...,0) (1, 2, ...,0) ... (BASE(1)-1,BASE(2)-1,...,BASE(DIM_NUM)-1). Example: DIM_NUM = 2, BASE = { 3, 3 } 0 0 1 0 2 0 0 1 1 1 2 1 0 2 1 2 2 2 Licensing: This code is distributed under the MIT license. Modified: 22 March 2009 Author: John Burkardt Parameters: Input, int DIM_NUM, the spatial dimension. Input, int BASE[DIM_NUM], the bases to be used in each dimension. In dimension I, entries will range from 0 to BASE[I]-1. Output, int A[DIM_NUM], the next vector. Input/output, int *MORE. Set this variable 0 before the first call. On return, MORE is TRUE if another vector has been computed. If MORE is returned FALSE, ignore the output vector and stop calling the routine. */ { int i; if ( !( *more ) ) { for ( i = 0; i < dim_num; i++ ) { a[i] = 0; } *more = 1; } else { for ( i = 0; i < dim_num; i++ ) { a[i] = a[i] + 1; if ( a[i] < base[i] ) { return; } a[i] = 0; } *more = 0; } return; } /******************************************************************************/ void vec_colex_next3 ( int dim_num, int base[], int a[], int *more ) /******************************************************************************/ /* Purpose: vec_colex_next3() generates vectors in colex order. Discussion: The vectors are produced in colexical order, starting with (1, 1, ...,1), (2, 1, ...,1), ... (BASE(1), 1, ...,1) (1, 2, ...,1) (2, 2, ...,1) ... (BASE(1), 2, ...,1) (1, 3, ...,1) (2, 3, ...,1) ... (BASE(1), BASE(2), ...,BASE(DIM_NUM)). Example: DIM_NUM = 2, BASE = { 3, 3 } 1 1 2 1 3 1 1 2 2 2 3 2 1 3 2 3 3 3 Licensing: This code is distributed under the MIT license. Modified: 22 March 2009 Author: John Burkardt Parameters: Input, int DIM_NUM, the spatial dimension. Input, int BASE[DIM_NUM], the bases to be used in each dimension. In dimension I, entries will range from 1 to BASE[I]. Output, int A[DIM_NUM], the next vector. Input/output, int *MORE. Set this variable 0 before the first call. On return, MORE is TRUE if another vector has been computed. If MORE is returned FALSE, ignore the output vector and stop calling the routine. */ { int i; if ( !( *more ) ) { for ( i = 0; i < dim_num; i++ ) { a[i] = 1; } *more = 1; } else { for ( i = 0; i < dim_num; i++ ) { a[i] = a[i] + 1; if ( a[i] <= base[i] ) { return; } a[i] = 1; } *more = 0; } return; } /******************************************************************************/ void vec_gray_next ( int n, int base[], int a[], int *done, int active[], int dir[], int *change ) /******************************************************************************/ /* Purpose: vec_gray_next() computes the next vector in Gray order. Discussion: The elements are produced one at a time. This routine handles the case where the number of degrees of freedom may differ from one component to the next. A method similar to the Gray code is used, so that successive elements returned by this routine differ by only a single element. A previous version of this routine used internal static memory. Example: N = 2, BASE = ( 2, 3 ), DONE = TRUE A DONE CHANGE --- ----- ------ 0 0 FALSE 0 (1) <-- C routine returns 0-based CHANGE. 0 1 FALSE 1 (2) 0 2 FALSE 1 (2) 1 2 FALSE 0 (1) 1 1 FALSE 1 (2) 1 0 FALSE 1 (2) 1 0 TRUE -1 Licensing: This code is distributed under the MIT license. Modified: 16 May 2015 Author: John Burkardt Reference: Dennis Stanton, Dennis White, Constructive Combinatorics, Springer, 1986, ISBN: 0387963472, LC: QA164.S79. Parameters: Input, int N, the number of components. Input, int BASE[N], contains the number of degrees of freedom of each component. The output values of A will satisfy 0 <= A[I] < BASE[I]. Input/output, int A[N]. On the first call, the input value of A doesn't matter. Thereafter, it should be the same as its output value from the previous call. On output, if DONE is FALSE, then A contains the next element of the space. Input/output, int *DONE. On the first call, the user must set DONE to TRUE. This signals the program to initialize data. On every return, if DONE is FALSE, the program has computed another entry, which is contained in A. If DONE is TRUE, then there are no more entries, and the program should not be called for any more. Input/output, int ACTIVE[N], DIR[N], two work arrays needed by this procedure. The user should allocate memory for them before the first call. Their values should not be altered by the user. Output, int *CHANGE, is set to the index of the element whose value was changed. On return from the first call, CHANGE is 0, even though all the elements have been "changed". On return with DONE equal to TRUE, CHANGE is -1. (Note that CHANGE is a vector index. In this C version, it is zero-based.) */ { int i; /* The user is calling for the first time. */ if ( *done ) { *done = 0; for ( i = 0; i < n; i++ ) { a[i] = 0; } for ( i = 0; i < n; i++ ) { dir[i] = 1; } for ( i = 0; i < n; i++ ) { active[i] = 1; } for ( i = 0; i < n; i++ ) { if ( base[i] < 1 ) { printf ( "\n" ); printf ( "VEC_GRAY_NEXT - Warning!\n" ); printf ( " For index I = %d\n", i ); printf ( " the nonpositive value of BASE[I] = %d\n", base[i] ); printf ( " which was reset to 1!\n" ); base[i] = 1; active[i] = 0; } else if ( base[i] == 1 ) { active[i] = 0; } } *change = 0; return; } /* Find the maximum active index. */ *change = -1; for ( i = 0; i < n; i++ ) { if ( active[i] != 0 ) { *change = i; } } /* If there are NO active indices, we have generated all vectors. */ if ( *change == -1 ) { *done = 1; return; } /* Increment the element with maximum active index. */ a[*change] = a[*change] + dir[*change]; /* If we attained a minimum or maximum value, reverse the direction vector, and deactivate the index. */ if ( a[*change] == 0 || a[*change] == base[*change] - 1 ) { dir[*change] = -dir[*change]; active[*change] = 0; } /* Activate all subsequent indices. */ for ( i = *change + 1; i < n; i++ ) { if ( 1 < base[i] ) { active[i] = 1; } } return; } /******************************************************************************/ int vec_gray_rank ( int n, int base[], int a[] ) /******************************************************************************/ /* Purpose: vec_gray_rank() computes the rank of a product space element. Discussion: The rank applies only to the elements as produced by the routine VEC_GRAY_NEXT. Example: N = 2, BASE = ( 2, 3 ), A = ( 1, 2 ), RANK = 4. Licensing: This code is distributed under the MIT license. Modified: 22 March 2009 Author: John Burkardt. Reference: Dennis Stanton, Dennis White, Constructive Combinatorics, Springer, 1986, ISBN: 0387963472, LC: QA164.S79. Parameters: Input, int N, the number of components. Input, int BASE[N], contains the number of degrees of freedom of each component. The output values of A will satisfy 0 <= A[I] < BASE[I]. Input, int A[N], the product space element, with the property that 0 <= A[I] < BASE[I] for each entry I. Output, int VEC_RANK, the rank, or order, of the element in the list of all elements. The rank count begins at 1. */ { int c; int i; int rank; rank = 0; for ( i = 0; i < n; i++ ) { if ( ( rank % 2 ) == 1 ) { c = base[i] - a[i] - 1; } else { c = a[i]; } rank = base[i] * rank + c; } rank = rank + 1; return rank; } /******************************************************************************/ void vec_gray_unrank ( int n, int base[], int rank, int a[] ) /******************************************************************************/ /* Purpose: vec_gray_unrank() computes the product space element of a given rank. Discussion: The rank applies only to the elements as produced by the routine VEC_GRAY_NEXT. Example: N = 2, BASE = ( 2, 3 ), RANK = 4. A = ( 1, 2 ). Licensing: This code is distributed under the MIT license. Modified: 22 March 2009 Author: John Burkardt Reference: Dennis Stanton, Dennis White, Constructive Combinatorics, Springer, 1986, ISBN: 0387963472, LC: QA164.S79. Parameters: Input, int N, the number of components. Input, int BASE[N], contains the number of degrees of freedom of each component. The output values of A will satisfy 0 <= A[I] < BASE[I]. Input, int RANK, the desired rank, or order, of the element in the list of all elements. The rank count begins at 1 and extends to MAXRANK = Product ( 0 <= I <= N ) BASE[I]. Output, int A[N], the product space element of the given rank. */ { int i; int s; s = rank - 1; for ( i = n-1; 0 <= i; i-- ) { a[i] = s % base[i]; s = s / base[i]; if ( ( s % 2 ) == 1 ) { a[i] = base[i] - a[i] - 1; } } return; } /******************************************************************************/ void vec_lex_next ( int dim_num, int base, int a[], int *more ) /******************************************************************************/ /* Purpose: vec_lex_next() generates vectors in lex order. Discussion: The vectors are produced in lexical order, starting with (0,0,...,0), (0,0,...,1), ... (BASE-1,BASE-1,...,BASE-1). Example: DIM_NUM = 2, BASE = 3 0 0 0 1 0 2 1 0 1 1 1 2 2 0 2 1 2 2 Licensing: This code is distributed under the MIT license. Modified: 21 March 2009 Author: John Burkardt Parameters: Input, int DIM_NUM, the size of the vectors to be used. Input, int BASE, the base to be used. BASE = 2 will give vectors of 0's and 1's, for instance. Output, int A[DIM_NUM], the next vector. Input/output, int *MORE. Set this variable false before the first call. On return, MORE is TRUE if another vector has been computed. If MORE is returned FALSE, ignore the output vector and stop calling the routine. */ { int i; if ( !( *more ) ) { for ( i = 0; i < dim_num; i++ ) { a[i] = 0; } *more = 1; } else { for ( i = dim_num - 1; 0 <= i; i-- ) { a[i] = a[i] + 1; if ( a[i] < base ) { return; } a[i] = 0; } *more = 0; } return; } /******************************************************************************/ void vec_random ( int n, int base, int *seed, int a[] ) /******************************************************************************/ /* Purpose: vec_random() selects a random N-vector of integers modulo a given base. Licensing: This code is distributed under the MIT license. Modified: 21 March 2009 Author: John Burkardt Parameters: Input, int N, the size of the vector to be generated. Input, int BASE, the base to be used. Input/output, int *SEED, a random number seed. Output, int A[N], a list of N random values between 0 and BASE-1. */ { int i; for ( i = 0; i < n; i++ ) { a[i] = i4_uniform_ab ( 0, base-1, seed ); } return; } /******************************************************************************/ void vector_constrained_next ( int n, int x_min[], int x_max[], int x[], int *constraint, int *more ) /******************************************************************************/ /* Purpose: vector_constrained_next() returns the "next" constrained vector. Discussion: We consider all vectors of dimension N whose components satisfy X_MIN(1:N) <= X(1:N) <= X_MAX(1:N). We are only interested in the subset of these vectors which satisfy the following constraint: sum ( 1 <= I <= N ) ( ( X(I) - 1 ) / X_MAX(I) ) <= 1 We can carry out this check using integer arithmetic if we multiply through by P = product ( X_MAX(1:N) ): sum ( 1 <= I <= N ) ( ( X(I) - 1 ) * ( P / X_MAX(I) ) ) <= P. This routine returns, one at a time, and in right-to-left lexicographic order, exactly those vectors which satisfy the constraint. Example: N = 3 X_MIN: 2 2 1 X_MAX: 4 5 3 P = 60 # X(1) X(2) X(3) CONSTRAINT 1 2 2 1 27 2 3 2 1 42 3 4 2 1 57 4 2 3 1 39 5 3 3 1 54 6 2 4 1 51 7 2 2 2 47 8 2 3 2 59 Licensing: This code is distributed under the MIT license. Modified: 20 May 2015 Author: John Burkardt Parameters: Input, int N, the number of components in the vector. Input, int X_MIN[N], X_MAX[N], the minimum and maximum values allowed in each component. Input/output, int X[N]. On first call (with MORE = FALSE), the input value of X is not important. On subsequent calls, the input value of X should be the output value from the previous call. On output, (with MORE = TRUE), the value of X will be the "next" vector in the reverse lexicographical list of vectors that satisfy the condition. However, on output with MORE = FALSE, the vector X is meaningless, because there are no more vectors in the list. Output, int *CONSTRAINT, the constraint value for X. Valid vectors X will have a CONSTRAINT value between product(X_MIN(1:N)) (automatically) and product(X_MAX(1:N)) (because we skip over vectors with a constraint larger than this value). Input/output, int *MORE. On input, if the user has set MORE FALSE, the user is requesting the initiation of a new sequence of values. If MORE is TRUE, then the user is requesting "more" values in the current sequence. On output, if MORE is TRUE, then another value was found and returned in X, but if MORE is FALSE, then there are no more values in the sequence, and X is NOT the next value. */ { int i; int j; int x_prod; x_prod = 1; for ( j = 0; j < n; j++ ) { x_prod = x_prod * x_max[j]; } if ( !( *more ) ) { for ( j = 0; j < n; j++ ) { x[j] = x_min[j]; } *constraint = 0; for ( j = 0; j < n; j++ ) { *constraint = *constraint + ( ( x[j] - 1 ) * ( x_prod / x_max[j] ) ); } if ( x_prod < *constraint ) { *more = 0; } else { *more = 1; } return; } else { i = 0; for ( ; ; ) { if ( x[i] < x_max[i] ) { x[i] = x[i] + 1; *constraint = 0; for ( j = 0; j < n; j++ ) { *constraint = *constraint + ( ( x[j] - 1 ) * ( x_prod / x_max[j] ) ); } if ( *constraint <= x_prod ) { break; } } x[i] = x_min[i]; i = i + 1; if ( n <= i ) { *more = 0; break; } } } return; } /******************************************************************************/ void vector_constrained_next2 ( int n, int x_min[], int x_max[], int x[], int *constraint, int *more ) /******************************************************************************/ /* Purpose: vector_constrained_next2() returns the "next" constrained vector. Discussion: We consider all vectors of dimension N whose components satisfy X_MIN(1:N) <= X(1:N) <= X_MAX(1:N). We are only interested in the subset of these vectors which satisfy the following constraint: sum ( 1 <= I <= N ) ( X(I) / X_MAX(I) ) <= 1 We can carry out this check using integer arithmetic if we multiply through by P = product ( X_MAX(1:N) ): sum ( 1 <= I <= N ) ( X(I) * ( P / X_MAX(I) ) ) <= P. This routine returns, one at a time, and in right-to-left lexicographic order, exactly those vectors which satisfy the constraint. Example: N = 3 X_MIN: 1 1 1 X_MAX: 5 6 4 P = 120 # X(1) X(2) X(3) CONSTRAINT 1 1 1 1 74 2 2 1 1 98 3 1 2 1 94 4 2 2 1 119 5 1 3 1 114 6 1 1 2 104 Licensing: This code is distributed under the MIT license. Modified: 20 May 2015 Author: John Burkardt Parameters: Input, int N, the number of components in the vector. Input, int X_MIN[N], X_MAX[N], the minimum and maximum values allowed in each component. Input/output, int X[N]. On first call (with MORE = FALSE), the input value of X is not important. On subsequent calls, the input value of X should be the output value from the previous call. On output, (with MORE = TRUE), the value of X will be the "next" vector in the reverse lexicographical list of vectors that satisfy the condition. However, on output with MORE = FALSE, the vector X is meaningless, because there are no more vectors in the list. Output, int *CONSTRAINT, the constraint value for X. Valid vectors X will have a CONSTRAINT value between product(X_MIN(1:N)) (automatically) and product(X_MAX(1:N)) (because we skip over vectors with a constraint larger than this value). Input/output, int *MORE. On input, if the user has set MORE FALSE, the user is requesting the initiation of a new sequence of values. If MORE is TRUE, then the user is requesting "more" values in the current sequence. On output, if MORE is TRUE, then another value was found and returned in X, but if MORE is FALSE, then there are no more values in the sequence, and X is NOT the next value. */ { int i; int j; int x_prod; x_prod = 1; for ( j = 0; j < n; j++ ) { x_prod = x_prod * x_max[j]; } if ( !(*more) ) { for ( j = 0; j < n; j++ ) { x[j] = x_min[j]; } *constraint = 0; for ( j = 0; j < n; j++ ) { *constraint = *constraint + ( x[j] * ( x_prod / x_max[j] ) ); } if ( x_prod < *constraint ) { *more = 0; } else { *more = 1; } return; } else { i = 0; for ( ; ; ) { if ( x[i] < x_max[i] ) { x[i] = x[i] + 1; *constraint = 0; for ( j = 0; j < n; j++ ) { *constraint = *constraint + ( x[j] * ( x_prod / x_max[j] ) ); } if ( *constraint <= x_prod ) { break; } } x[i] = x_min[i]; i = i + 1; if ( n <= i ) { *more = 0; break; } } } return; } /******************************************************************************/ void vector_constrained_next3 ( int n, int x_min[], int x_max[], int x[], double *constraint, int *more ) /******************************************************************************/ /* Purpose: vector_constrained_next3() returns the "next" constrained vector. Discussion: This routine addresses the same problem as VECTOR_CONSTRAINED_NEXT2, and differs only in that real arithmetic is used, rather than integer arithmetic. Integer arithmetic allows us to do an exact calculation, but we run into overflow problems in simple cases where N is 10 and the X_MAX entries are of order 10, for instance. We consider all vectors of dimension N whose components satisfy X_MIN(1:N) <= X(1:N) <= X_MAX(1:N). We are only interested in the subset of these vectors which satisfy the following constraint: sum ( 1 <= I <= N ) ( X(I) / X_MAX(I) ) <= 1 Example: N = 3 X_MIN: 1 1 1 X_MAX: 5 6 4 P = 120 # X(1) X(2) X(3) CONSTRAINT 1 1 1 1 0.62 2 2 1 1 0.82 3 1 2 1 0.78 4 2 2 1 0.98 5 1 3 1 0.95 6 1 1 2 0.87 Licensing: This code is distributed under the MIT license. Modified: 22 March 2009 Author: John Burkardt Parameters: Input, int N, the number of components in the vector. Input, int X_MIN[N], X_MAX[N], the minimum and maximum values allowed in each component. Input/output, int X[N]. On first call (with MORE = FALSE), the input value of X is not important. On subsequent calls, the input value of X should be the output value from the previous call. On output, (with MORE = TRUE), the value of X will be the "next" vector in the reverse lexicographical list of vectors that satisfy the condition. However, on output with MORE = FALSE, the vector X is meaningless, because there are no more vectors in the list. Output, double *CONSTRAINT, the constraint value for X. Valid vectors X will have a CONSTRAINT value between product(X_MIN(1:N)) / product(X_MAX(1:N)) and 1.0. Input/output, int *MORE. On input, if the user has set MORE FALSE, the user is requesting the initiation of a new sequence of values. If MORE is TRUE, then the user is requesting "more" values in the current sequence. On output, if MORE is TRUE, then another value was found and returned in X, but if MORE is FALSE, then there are no more values in the sequence, and X is NOT the next value. */ { int i; int j; if ( !( *more ) ) { for ( j = 0; j < n; j++ ) { x[j] = x_min[j]; } *constraint = 0.0; for ( j = 0; j < n; j++ ) { *constraint = *constraint + ( double ) x[j] / ( double ) x_max[j]; } if ( 1.0 < *constraint ) { *more = 0; } else { *more = 1; } return; } else { i = 0; for ( ; ; ) { if ( x[i] < x_max[i] ) { x[i] = x[i] + 1; *constraint = 0; for ( j = 0; j < n; j++ ) { *constraint = *constraint + ( double ) x[j] / ( double ) x_max[j]; } if ( *constraint <= 1.0 ) { break; } } x[i] = x_min[i]; i = i + 1; if ( n <= i ) { *more = 0; break; } } } return; } /******************************************************************************/ void vector_constrained_next4 ( int n, double alpha[], int x_min[], int x_max[], int x[], double q, int *more ) /******************************************************************************/ /* Purpose: vector_constrained_next4() returns the "next" constrained vector. Discussion: This routine is similar to VECTOR_CONSTRAINED_NEXT2 and VECTOR_CONSTRAINED_NEXT3. We consider all vectors X of dimension N whose components satisfy X_MIN(1:N) <= X(1:N) <= X_MAX(1:N). We are only interested in the subset of these vectors which satisfy the following constraint: sum ( 1 <= I <= N ) ( ALPHA(I) * X(I) ) <= Q Example: N = 3 ALPHA 4.0 3.0 5.0 Q 20.0 X_MIN: 1 1 1 X_MAX: 5 6 4 P = 120 # X(1) X(2) X(3) Total 1 1 1 1 12.0 2 2 1 1 20.0 3 1 2 1 15.0 4 2 2 1 19.0 5 1 3 1 18.0 6 1 1 2 17.0 Licensing: This code is distributed under the MIT license. Modified: 22 March 2009 Author: John Burkardt Parameters: Input, int N, the number of components in the vector. Input, double ALPHA[N], the coefficient vector. Input, int X_MIN[N], X_MAX[N], the minimum and maximum values allowed in each component. Input/output, int X[N]. On first call (with MORE = FALSE), the input value of X is not important. On subsequent calls, the input value of X should be the output value from the previous call. On output, (with MORE = TRUE), the value of X will be the "next" vector in the reverse lexicographical list of vectors that satisfy the condition. However, on output with MORE = FALSE, the vector X is meaningless, because there are no more vectors in the list. Input, double Q, the limit on the sum. Input/output, int *MORE. On input, if the user has set MORE FALSE, the user is requesting the initiation of a new sequence of values. If MORE is TRUE, then the user is requesting "more" values in the current sequence. On output, if MORE is TRUE, then another value was found and returned in X, but if MORE is FALSE, then there are no more values in the sequence, and X is NOT the next value. */ { int i; int j; double total; if ( ! (*more) ) { for ( j = 0; j < n; j++ ) { x[j] = x_min[j]; } total = 0.0; for ( j = 0; j < n; j++ ) { total = total + alpha[j] * ( double ) x[j]; } if ( q < total ) { *more = 0; } else { *more = 1; } return; } else { i = 0; for ( ; ; ) { if ( x[i] < x_max[i] ) { x[i] = x[i] + 1; total = 0; for ( j = 0; j < n; j++ ) { total = total + alpha[j] * ( double ) x[j]; } if ( total <= q ) { break; } } x[i] = x_min[i]; i = i + 1; if ( n <= i ) { *more = 0; break; } } } return; } /******************************************************************************/ void vector_constrained_next5 ( int n, int x[], int sum_min, int sum_max, int *base, int *more ) /******************************************************************************/ /* Purpose: vector_constrained_next5() returns the "next" constrained vector. Discussion: We consider all positive integer vectors of dimension N whose components satisfy SUM_MIN <= X(1:N) <= SUM_MAX. This routine returns, one at a time, and in right-to-left lexicographic order, exactly those vectors which satisfy the constraint. Example: N = 3 SUM_MIN = 5 SUM_MAX = 6 # X(1) X(2) X(3) SUM 1 3 1 1 5 2 2 2 1 5 3 2 1 2 5 4 1 3 1 5 5 1 2 2 5 6 1 1 3 5 7 4 1 1 6 8 3 2 1 6 9 3 1 2 6 10 2 3 1 6 11 2 2 2 6 12 2 1 3 6 13 1 4 1 6 14 1 3 2 6 15 1 2 3 6 16 1 1 4 6 Licensing: This code is distributed under the MIT license. Modified: 20 May 2015 Author: John Burkardt Parameters: Input, int N, the number of components in the vector. Input, int SUM_MIN, SUM_MAX, the minimum and maximum sums.. Input/output, int X(N). On first call (with MORE = FALSE), the input value of X is not important. On subsequent calls, the input value of X should be the output value from the previous call. On output, (with MORE = TRUE), the value of X will be the "next" vector in the reverse lexicographical list of vectors that satisfy the condition. However, on output with MORE = FALSE, the vector X is meaningless, because there are no more vectors in the list. Input/output, int *BASE, a value controlled by this function. The user must declare this variable in the calling program, and should pass the output value from one call as input to the next, but should not alter its value. Input/output, int *MORE. On input, if the user has set MORE FALSE, the user is requesting the initiation of a new sequence of values. If MORE is TRUE, then the user is requesting "more" values in the current sequence. On output, if MORE is TRUE, then another value was found and returned in X, but if MORE is FALSE, then there are no more values in the sequence, and X is NOT the next value. */ { int i; int j; /* Initialization. */ if ( !( *more ) ) { if ( sum_max < n ) { *more = 0; return; } if ( sum_max < sum_min ) { *more = 0; return; } *more = 1; *base = sum_min; if ( *base < n ) { *base = n; } x[0] = *base - n + 1; for ( i = 1; i < n; i++ ) { x[i] = 1; } return; } /* Next element. */ else { /* Search from the right, seeking an index I < N for which 1 < X(I). */ for ( i = n-2; 0 <= i; i-- ) { /* If you find such an I, decrease X(I) by 1, and add that to X(I+1). */ if ( 1 < x[i] ) { x[i] = x[i] - 1; x[i+1] = x[i+1] + 1; /* Now grab all the "excess" 1's from the entries to the right of X(I+1). */ for ( j = i+2; j < n; j++ ) { if ( 1 < x[j] ) { x[i+1] = x[i+1] + x[j] - 1; x[j] = 1; } } return; } } /* The current vector is (1,1,1,...BASE-N+1). If BASE < SUM_MAX, then increase BASE by 1, and start the new series. */ if ( *base < sum_max ) { *base = *base + 1; x[0] = *base - n + 1; for ( i = 1; i < n; i++ ) { x[i] = 1; } return; } /* We returned the last legal vector on the previouis call. The calculation is done. */ *more = 0; } return; } /******************************************************************************/ void vector_constrained_next6 ( int n, double alpha[], int x_min[], int x_max[], int x[], double q_min, double q_max, int *more ) /******************************************************************************/ /* Purpose: vector_constrained_next6() returns the "next" constrained vector. Discussion: This routine is similar to VECTOR_CONSTRAINED_NEXT2, VECTOR_CONSTRAINED_NEXT3, and VECTOR_CONSTRAINED_NEXT4. We consider all vectors X of dimension N whose components satisfy X_MIN(1:N) <= X(1:N) <= X_MAX(1:N). We are only interested in the subset of these vectors which satisfy the following constraint: Q_MIN <= sum ( 1 <= I <= N ) ALPHA(I) * X(I) <= Q_MAX This routine returns, one at a time, and in right-to-left lexicographic order, exactly those vectors which satisfy the constraint. Example: N = 3 ALPHA 4.0 3.0 5.0 Q_MIN 16.0 Q_MAX 20.0 X_MIN: 1 1 1 X_MAX: 5 6 4 # X(1) X(2) X(3) Total 1 2 1 1 20.0 2 2 2 1 19.0 3 1 3 1 18.0 4 1 1 2 17.0 Licensing: This code is distributed under the MIT license. Modified: 22 March 2009 Author: John Burkardt Parameters: Input, int N, the number of components in the vector. Input, double ALPHA[N], the coefficient vector. Input, int X_MIN[N], X_MAX[N], the minimum and maximum values allowed in each component. Input/output, int X[N]. On first call (with MORE = FALSE), the input value of X is not important. On subsequent calls, the input value of X should be the output value from the previous call. On output, (with MORE = TRUE), the value of X will be the "next" vector in the reverse lexicographical list of vectors that satisfy the condition. However, on output with MORE = FALSE, the vector X is meaningless, because there are no more vectors in the list. Input, double Q_MIN, Q_MAX, the lower and upper limits on the sum. Input/output, int *MORE. On input, if the user has set MORE FALSE, the user is requesting the initiation of a new sequence of values. If MORE is TRUE, then the user is requesting "more" values in the current sequence. On output, if MORE is TRUE, then another value was found and returned in X, but if MORE is FALSE, then there are no more values in the sequence, and X is NOT the next value. */ { int i; int j; double total; if ( ! ( *more ) ) { *more = 1; for ( i = 0; i < n; i++ ) { x[i] = x_min[i]; } total = 0.0; for ( i = 0; i < n; i++ ) { total = total + alpha[i] * ( double ) ( x[i] ); } if ( q_min <= total && total <= q_max ) { return; } } for ( ; ; ) { j = n - 1; for ( ; ; ) { if ( x[j] < x_max[j] ) { break; } if ( j <= 0 ) { *more = 0; return; } j = j - 1; } x[j] = x[j] + 1; for ( i = j + 1; i < n; i++ ) { x[i] = x_min[i]; } total = 0.0; for ( i = 0; i < n; i++ ) { total = total + alpha[i] * ( double ) ( x[i] ); } if ( q_min <= total && total <= q_max ) { break; } } return; } /******************************************************************************/ void vector_constrained_next7 ( int n, double level_weight[], int x_max[], int x[], double q_min, double q_max, int *more ) /******************************************************************************/ /* Purpose: vector_constrained_next7() returns the "next" constrained vector. Discussion: We consider vectors X of dimension N satisfying: 0 <= X(1:N) <= X_MAX(1:N). We are only interested in the subset of these vectors which satisfy the following constraint: Q_MIN < sum ( 1 <= I <= N ) LEVEL_WEIGHT(I) * X(I) <= Q_MAX This routine returns, one at a time, and in right-to-left lexicographic order, exactly those vectors which satisfy the constraint. Example: N = 3 LEVEL_WEIGHT 4.0 3.0 5.0 Q_MIN 16.0 Q_MAX 20.0 X_MAX: 5 6 4 # X(1) X(2) X(3) Total 1 2 1 1 20.0 2 2 2 1 19.0 3 1 3 1 18.0 4 1 1 2 17.0 Licensing: This code is distributed under the MIT license. Modified: 01 July 2010 Author: John Burkardt Parameters: Input, int N, the number of components in the vector. Input, double LEVEL_WEIGHT[N], the coefficient vector. Input, int X_MAX[N], the maximum values allowed in each component. Input/output, int X[N]. On first call (with MORE = FALSE), the input value of X is not important. On subsequent calls, the input value of X should be the output value from the previous call. On output, (with MORE = TRUE), the value of X will be the "next" vector in the reverse lexicographical list of vectors that satisfy the condition. However, on output with MORE = FALSE, the vector X is meaningless, because there are no more vectors in the list. Input, double Q_MIN, Q_MAX, the lower and upper limits on the sum. Input/output, int *MORE. On input, if the user has set MORE FALSE, the user is requesting the initiation of a new sequence of values. If MORE is TRUE, then the user is requesting "more" values in the current sequence. On output, if MORE is TRUE, then another value was found and returned in X, but if MORE is FALSE, then there are no more values in the sequence, and X is NOT the next value. */ { int i; int j; double total; if ( ! ( *more ) ) { *more = 1; for ( i = 0; i < n; i++ ) { x[i] = 0; } total = 0.0; for ( i = 0; i < n; i++ ) { total = total + level_weight[i] * ( double ) ( x[i] ); } if ( q_min < total && total <= q_max ) { return; } } for ( ; ; ) { j = n - 1; for ( ; ; ) { if ( x[j] < x_max[j] ) { break; } if ( j <= 0 ) { *more = 0; return; } j = j - 1; } x[j] = x[j] + 1; for ( i = j + 1; i < n; i++ ) { x[i] = 0; } total = 0.0; for ( i = 0; i < n; i++ ) { total = total + level_weight[i] * ( double ) ( x[i] ); } if ( q_min < total && total <= q_max ) { break; } } return; } /******************************************************************************/ void vector_next ( int n, int x_min[], int x_max[], int x[], int *more ) /******************************************************************************/ /* Purpose: vector_next() returns the "next" integer vector between two ranges. Discussion: We consider all integer vectors of dimension N satisfying: X_MIN(1:N) <= X(1:N) <= X_MAX(1:N). This routine returns, one at a time, and in right-to-left lexicographic order, all these vectors. Example: N = 3 X_MIN: 2 2 0 X_MAX: 4 3 1 # X(1) X(2) X(3) 1 2 2 0 2 3 2 0 3 4 2 0 4 2 3 0 5 3 3 0 6 4 3 0 7 2 2 1 8 3 2 1 9 4 2 1 10 2 3 1 11 3 3 1 12 4 3 1 Licensing: This code is distributed under the MIT license. Modified: 01 July 2010 Author: John Burkardt Parameters: Input, int N, the number of components in the vector. Input, int X_MIN[N], X_MAX[N], the minimum and maximum values allowed in each component. Input/output, int X[N]. On first call, with MORE = FALSE, the input value of X is not important. On subsequent calls, the input value of X should be the output value from the previous call. On output, with MORE = TRUE, the value of X will be the "next" vector in the reverse lexicographical list of vectors. However, on output with MORE = FALSE, the vector X is meaningless, because there are no more vectors in the list. Input/output, int *MORE. On input, if the user has set MORE FALSE, the user is requesting the initiation of a new sequence of values. If MORE is TRUE, then the user is requesting "more" values in the current sequence. On output, if MORE is TRUE, then another value was found and returned in X, but if MORE is FALSE, then there are no more values in the sequence, and X is NOT the next value. */ { int i; if ( !( *more ) ) { for ( i = 0; i < n; i++ ) { x[i] = x_min[i]; } *more = 1; } else { i = 0; for ( ; ; ) { if ( x[i] < x_max[i] ) { x[i] = x[i] + 1; break; } x[i] = x_min[i]; i = i + 1; if ( n <= i ) { *more = 0; break; } } } return; } /******************************************************************************/ void vector_sumlex_next ( int n, int *x ) /******************************************************************************/ /* Purpose: vector_sumlex_next() returns the next integer vector in sumlex order. Discussion: Consider integer vectors of length N, ordered by their sum. Vectors of equal sum are ordered lexically. Licensing: This code is distributed under the MIT license. Modified: 17 September 2022 Author: John Burkardt Input: int N: the length of the vector. int X(N), the current vector. Output: int X(N), the next vector. */ { int j; int s; int t; s = i4vec_sum ( n, x ); /* Case: (0,0,0,...0,S) -> (S+1,0,0,...,0) */ if ( x[0] == s ) { x[0] = 0; x[n-1] = s + 1; } /* Case: Rightmost nonzero sends one unit left, and the rest to last position. */ else { t = 0; for ( j = n - 1; 1 <= j; j-- ) { if ( x[j] != 0 ) { t = x[j]; x[j] = 0; x[j-1] = x[j-1] + 1; x[n-1] = t - 1; break; } } if ( t == 0 ) { printf ( "\n" ); printf ( "vector_sumlex_next(): Fatal error!\n" ); printf ( " Could not find an entry to borrow from.\n" ); exit ( 1 ); } } return; } /******************************************************************************/ int ytb_enum ( int n ) /******************************************************************************/ /* Purpose: ytb_enum() enumerates the Young tableau of size N. Discussion: If A(N) is the number of Young tableau of size N, then A(1) = 1, A(2) = 2, and A(N) = A(N-1) + (N-1) * A(N-2). Licensing: This code is distributed under the MIT license. Modified: 31 May 2008 Author: John Burkardt Parameters: Input, int N, the integer which is to be partitioned. Output, int YTB_ENUM, the number of Young tableau of N. */ { int a1; int a2; int a3; int i; int num; if ( n <= 0 ) { num = 0; } else if ( n == 1 ) { num = 1; } else if ( n == 2 ) { num = 2; } else { a2 = 1; a3 = 2; for ( i = 3; i <= n; i++ ) { a1 = a2; a2 = a3; a3 = a2 + ( i - 1 ) * a1; } num = a3; } return num; } /******************************************************************************/ void ytb_next ( int n, int lambda[], int a[], int *more ) /******************************************************************************/ /* Purpose: ytb_next() computes the next Young tableau for a given shape. Discussion: When the routine is called with MORE = .FALSE. (the first time), and if LAMBDA on this call has M parts, with M