atl_rand.c
来自「基于Blas CLapck的.用过的人知道是干啥的」· C语言 代码 · 共 292 行
C
292 行
/* * Automatically Tuned Linear Algebra Software v3.8.0 * (C) Copyright 2000 Antoine P. Petitet * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions, and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the ATLAS group or the names of its contributers may * not be used to endorse or promote products derived from this * software without specific written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ATLAS GROUP OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */#include "atlas_misc.h"#include "atlas_tst.h"static void ATL_ladd( int * J, int * K, int * I){/* * Purpose * ======= * * ATL_ladd adds without carry two long positive integers K and J an * put the result into I. The long integers I, J, K are encoded on 31 * bits using an array of 2 integers. The 16-lower bits are stored i * the first entry of each array, the 15-higher bits in the second * entry. * * Arguments * ========= * * J (local input) int * * On entry, J is an integer array of dimension 2 containing the * encoded long integer J. * * K (local input) int * * On entry, K is an integer array of dimension 2 containing the * encoded long integer K. * * I (local output) int * * On entry, I is an integer array of dimension 2. On exit, this * array contains the encoded long integer result. * * --------------------------------------------------------------------- */ int itmp0 = K[0] + J[0], itmp1;/* * K[1] K[0] K I[0] = (K[0]+J[0]) % 2^16 * 0XXX XXXX carry = (K[0]+J[0]) / 2^16 * * + J[1] J[0] J I[1] = K[1] + J[1] + carry * 0XXX XXXX I[1] = I[1] % 2^15 * ------------- * I[1] I[0] * 0XXX XXXX I */ itmp1 = itmp0 >> 16; I[0] = itmp0 - ( itmp1 << 16 ); itmp0 = itmp1 + K[1] + J[1]; I[1] = itmp0 - (( itmp0 >> 15 ) << 15);}static void ATL_lmul( int * K, int * J, int * I){/* * Purpose * ======= * * ATL_lmul multiplies without carry two long positive integers K and J * and put the result into I. The long integers I, J, K are encoded on * 31 bits using an array of 2 integers. The 16-lower bits are stored in * the first entry of each array, the 15-higher bits in the second entry * of each array. For efficiency purposes, the intrisic modulo function * is inlined. * * Arguments * ========= * * K (local input) int * * On entry, K is an integer array of dimension 2 containing the * encoded long integer K. * * J (local input) int * * On entry, J is an integer array of dimension 2 containing the * encoded long integer J. * * I (local output) int * * On entry, I is an integer array of dimension 2. On exit, this * array contains the encoded long integer result. * * --------------------------------------------------------------------- */ static int ipow30 = ( 1 << 30 ); int kt, lt;/* * K[1] K[0] K kt = K[0]*J[0] * 0XXX XXXX if(kt < 0) kt += 2^31 * x I[0] = kt % 2^16 * lt = K[0]*J[1] + K[1]*J[0] * J[1] J[0] J if(lt < 0) lt += 2^31 * 0XXX XXXX kt = (kt / 2^16) + lt * -------------- if(kt < 0) kt += 2^31 * I[1] I[0] I[1] = kt % 2^15 * 0XXX XXXX I */ kt = K[0] * J[0]; if( kt < 0 ) kt = ( kt + ipow30 ) + ipow30; I[0] = kt - ( ( kt >> 16 ) << 16 ); lt = K[0] * J[1] + K[1] * J[0]; if( lt < 0 ) lt = ( lt + ipow30 ) + ipow30; kt = ( kt >> 16 ) + lt; if( kt < 0 ) kt = ( kt + ipow30 ) + ipow30; I[1] = kt - ( ( kt >> 15 ) << 15 );}static void ATL_setran( const int OPTION, int * IRAN){/* * Purpose * ======= * * ATL_setran initializes the random generator with the encoding of the * first number X(0) in the sequence, and the constants a and c used to * compute the next element in the sequence: X(n+1) = a*X(n) + c. X(0), * a and c are stored in the static variables irand, ias and ics. When * OPTION is 0 (resp. 1 and 2), irand (resp. ia and ic) is set to the * values of the input array IRAN. When OPTION is 3, IRAN is set to the * current value of irand, and irand is then incremented. * * Arguments * ========= * * OPTION (local input) const int * On entry, OPTION is an integer that specifies the operations * to be performed on the random generator as specified above. * * IRAN (local input/output) int * * On entry, IRAN is an array of dimension 2, that contains the * 16-lower and 15-higher bits of a random number. * * --------------------------------------------------------------------- */ static int ias[2], ics[2], irand[2]; int j[2]; if( OPTION == 3 ) { /* return current value */ IRAN[0] = irand[0]; IRAN[1] = irand[1]; ATL_lmul( irand, ias, j ); /* j = irand * ias; */ ATL_ladd( j, ics, irand ); /* irand = j + ics; */ } else if( OPTION == 0 ) { irand[0] = IRAN[0]; irand[1] = IRAN[1]; } else if( OPTION == 1 ) { ias [0] = IRAN[0]; ias [1] = IRAN[1]; } else if( OPTION == 2 ) { ics [0] = IRAN[0]; ics [1] = IRAN[1]; }}static void ATL_xjumpm( const int JUMPM, int * MULT, int * IADD, int * IRANN, int * IRANM, int * IAM, int * ICM){/* * Purpose * ======= * * ATL_xjumpm computes the constants A and C to jump JUMPM numbers in * the random sequence: X(n+JUMPM) = A*X(n)+C. The constants encoded in * MULT and IADD specify how to jump from one entry in the sequence to * the next. * * Arguments * ========= * * JUMPM (local input) const int * On entry, JUMPM specifies the number of entries in the * sequence to jump over. When JUMPM is less or equal than zero, * A and C are not computed, IRANM is set to IRANN corresponding * to a jump of size zero. * * MULT (local input) int * * On entry, MULT is an array of dimension 2, that contains the * 16-lower and 15-higher bits of the constant a to jump from * X(n) to X(n+1) = a*X(n) + c in the random sequence. * * IADD (local input) int * * On entry, IADD is an array of dimension 2, that contains the * 16-lower and 15-higher bits of the constant c to jump from * X(n) to X(n+1) = a*X(n) + c in the random sequence. * * IRANN (local input) int * * On entry, IRANN is an array of dimension 2. that contains the * 16-lower and 15-higher bits of the encoding of X(n). * * IRANM (local output) int * * On entry, IRANM is an array of dimension 2. On exit, this * array contains respectively the 16-lower and 15-higher bits * of the encoding of X(n+JUMPM). * * IAM (local output) int * * On entry, IAM is an array of dimension 2. On exit, when JUMPM * is greater than zero, this array contains the encoded * constant A to jump from X(n) to X(n+JUMPM) in the random * sequence. IAM(0:1) contains respectively the 16-lower and * 15-higher bits of this constant A. When JUMPM is less or * equal than zero, this array is not referenced. * * ICM (local output) int * * On entry, ICM is an array of dimension 2. On exit, when JUMPM * is greater than zero, this array contains the encoded * constant C to jump from X(n) to X(n+JUMPM) in the random * sequence. ICM(0:1) contains respectively the 16-lower and * 15-higher bits of this constant C. When JUMPM is less or * equal than zero, this array is not referenced. * * --------------------------------------------------------------------- */ int j[2], k; if( JUMPM > 0 ) { IAM[0] = MULT[0]; IAM[1] = MULT[1]; /* IAM = MULT; */ ICM[0] = IADD[0]; ICM[1] = IADD[1]; /* ICM = IADD; */ for( k = 1; k <= JUMPM-1; k++ ) { ATL_lmul( IAM, MULT, j ); /* j = IAM * MULT; */ IAM[0] = j[0]; IAM[1] = j[1]; /* IAM = j; */ ATL_lmul( ICM, MULT, j ); /* j = ICM * MULT; */ ATL_ladd( IADD, j, ICM ); /* ICM = IADD + j; */ } ATL_lmul( IRANN, IAM, j ); /* j = IRANN * IAM; */ ATL_ladd( j, ICM, IRANM ); /* IRANM = j + ICM; */ } else { /* IRANM = IRANN */ IRANM[0] = IRANN[0]; IRANM[1] = IRANN[1]; }}void ATL_srand(int iseed){ int iadd[2], ia1[2], ic1[2], iran1[2], jseed[2], mult[2]; mult [0] = 20077; mult[1] = 16838; iadd [0] = 12345; iadd [1] = 0; jseed[0] = iseed; jseed[1] = (iseed>>16); ATL_xjumpm( 1, mult, iadd, jseed, iran1, ia1, ic1 ); ATL_setran( 0, iran1 ); ATL_setran( 1, ia1 ); ATL_setran( 2, ic1 );}int ATL_rand(void){ int j[2]; ATL_setran( 3, j ); return(j[0] + ((j[1])<<16));}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?