/* Find all squares with a single digit allowed -- do not mutate board */ static void singles( int el, int (*idx_fn)( int, int ), int hintcode ) { int i, j, idx; count_set_digits( el, idx_fn ); for( i = 0 ; i < 9 ; ++i ) { if( 1 == counts[ i ] ) { /* Digit 'i+1' appears just once in the element */ for( j = 0 ; j < 9 ; ++j ) { idx = (*idx_fn)( el, j ); if( !DISALLOWED( idx, i + 1 ) && idx_possible < 81 ) possible[ idx_possible++ ] = SET_INDEX( idx ) | SET_DIGIT( i + 1 ) | hintcode; } } if( 8 == digits[ i ] ) { /* 8 digits are masked at this position - just one remaining */ idx = (*idx_fn)( el, i ); for( j = 1 ; j <= 9 ; ++j ) if( 0 == ( STATE( idx ) & DIGIT_STATE( j ) ) && idx_possible < 81 ) possible[ idx_possible++ ] = SET_INDEX( idx ) | SET_DIGIT( j ) | hintcode; } } }
/* * big integer unsigned multiplication * * operands in bip.op1 and bip.op2 * result in bip.res */ static void bigUmul(void) { int nd1; int nd2; int i, j, k; unsigned short carry; unsigned short aux; /* get sizes of operands */ nd1 = GET_ND(bip.op1); nd2 = GET_ND(bip.op2); /* allocate result */ bip.res = newBig(nd1 + nd2); /* reset lower nd1 digits of result */ for (i = 0; i < nd1; i++) { SET_DIGIT(bip.res, i, 0); } /* res = op1 * op2 */ for (j = 0; j < nd2; j++) { carry = 0x00; for (k = j, i = 0; i < nd1; k++, i++) { aux = (unsigned short) GET_DIGIT(bip.op1, i) * (unsigned short) GET_DIGIT(bip.op2, j) + (unsigned short) GET_DIGIT(bip.res, k) + carry; SET_DIGIT(bip.res, k, aux & 0xFF); carry = aux >> 8; } SET_DIGIT(bip.res, k, carry); } /* determine actual size of result */ i = nd1 + nd2; while (--i >= 0 && GET_DIGIT(bip.res, i) == 0) ; SET_ND(bip.res, i + 1); }
/* * big integer unsigned addition * * operands in bip.op1 and bip.op2 * result in bip.res */ static void bigUadd(void) { int nd1; int nd2; int i; unsigned short carry; unsigned short aux; int xchgFlag; /* make sure op1 has at least as many digits as op2 */ nd1 = GET_ND(bip.op1); nd2 = GET_ND(bip.op2); if (nd1 < nd2) { /* exchange operands */ bigXchg(); i = nd1; nd1 = nd2; nd2 = i; xchgFlag = 1; } else { /* don't exchange operands */ xchgFlag = 0; } /* allocate result */ bip.res = newBig(nd1 + 1); /* copy op2 to result */ for (i = 0; i < nd2; i++) { SET_DIGIT(bip.res, i, GET_DIGIT(bip.op2, i)); } /* fill result with 0 up to size of op1 */ for (; i < nd1; i++) { SET_DIGIT(bip.res, i, 0); } /* res = op1 + res */ carry = 0x00; for (i = 0; i < nd1; i++) { aux = (unsigned short) GET_DIGIT(bip.op1, i) + (unsigned short) GET_DIGIT(bip.res, i) + carry; SET_DIGIT(bip.res, i, aux & 0xFF); carry = aux >> 8; } SET_DIGIT(bip.res, i, carry); /* determine actual size of result */ i = nd1 + 1; while (--i >= 0 && GET_DIGIT(bip.res, i) == 0) ; SET_ND(bip.res, i + 1); /* restore operands */ if (xchgFlag) { bigXchg(); } }
static int choice( void ) { int i, n; rb->yield(); for( n = i = 0 ; i < 81 ; ++i ) if( IS_EMPTY( i ) ) { possible[ n ] = SET_INDEX( i ) | SET_DIGIT( numset( board[ i ] ) ); /* Inconsistency if square unknown, but nothing possible */ if( 9 == GET_DIGIT( possible[ n ] ) ) return -2; ++n; } if( 0 == n ) return -1; /* All squares known */ rb->qsort( possible, n, sizeof( possible[ 0 ] ), cmp ); return GET_INDEX( possible[ 0 ] ); }
/* init a new mp_int */ int mp_init (mp_int * a) { #ifdef __UHC_BUILDS_RTS__ // all allocation is assumed to be done outside library mp_zero(a) ; printf( "WARNING: mp_init (%p used=%x alc=%x)\n", a, USED(a), ALLOC(a) ) ; // prLTM(a,"mp_init") ; #else int i; /* allocate memory required and clear it */ SET_DIGITS(a, OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * MP_PREC)); if (DIGITS(a) == NULL) { return MP_MEM; } /* set the digits to zero */ for (i = 0; i < MP_PREC; i++) { SET_DIGIT(a,i,0); } /* set the used to zero, allocated digits to the default precision * and sign to positive */ SET_USED(a,0); SET_ALLOC(a,MP_PREC); SET_SIGN(a,MP_ZPOS); #endif return MP_OKAY; }
/* * big integer unsigned division by single digit divisor * * dividend in bip.rem, divisor in parameter * quotient in bip.rem, remainder is returned */ static unsigned char bigUdiv1(unsigned char divisor) { ObjRef tmp; int nd; int i; unsigned short d, r; unsigned short aux; /* get size of dividend */ nd = GET_ND(bip.rem); /* check for division by zero */ d = (unsigned short) divisor; if (d == 0) { fatalError("internal library error #3 - THIS SHOULD NEVER HAPPEN!"); } /* allocate result */ tmp = newBig(nd); /* tmp = dividend / divisor, r = dividend % divisor */ r = 0; for (i = nd - 1; i >= 0; i--) { aux = (r << 8) | (unsigned short) GET_DIGIT(bip.rem, i); SET_DIGIT(tmp, i, aux / d); r = aux % d; } /* determine actual size of quotient */ i = nd; while (--i >= 0 && GET_DIGIT(tmp, i) == 0) ; SET_ND(tmp, i + 1); /* store quotient */ bip.rem = tmp; /* return remainder */ return (unsigned char) r; }
/* * big integer unsigned subtraction * * operands in bip.op1 and bip.op2 * result in bip.res, must not be negative */ static void bigUsub(void) { int nd1; int nd2; int i; unsigned short carry; unsigned short aux; /* op1 must have at least as many digits as op2 */ nd1 = GET_ND(bip.op1); nd2 = GET_ND(bip.op2); if (nd1 < nd2) { /* unsigned subtraction would yield negative result */ fatalError("internal library error #1 - THIS SHOULD NEVER HAPPEN!"); } /* allocate result */ bip.res = newBig(nd1); /* copy op2 to result */ for (i = 0; i < nd2; i++) { SET_DIGIT(bip.res, i, GET_DIGIT(bip.op2, i)); } /* fill result with 0 up to size of op1 */ for (; i < nd1; i++) { SET_DIGIT(bip.res, i, 0); } /* res = op1 - res */ carry = 0x01; for (i = 0; i < nd1; i++) { aux = (unsigned short) GET_DIGIT(bip.op1, i) - (unsigned short) GET_DIGIT(bip.res, i) + carry + 0xFF; SET_DIGIT(bip.res, i, aux & 0xFF); carry = aux >> 8; } if (carry != 0x01) { /* unsigned subtraction would yield negative result */ fatalError("internal library error #2 - THIS SHOULD NEVER HAPPEN!"); } /* determine actual size of result */ i = nd1; while (--i >= 0 && GET_DIGIT(bip.res, i) == 0) ; SET_ND(bip.res, i + 1); }
/* Choose a digit for the given square. * The starting digit is passed as a parameter. * Returns -1 if no choice possible. */ static int choose( int idx, int digit ) { rb->yield(); for( ; digit <= 9 ; ++digit ) if( !DISALLOWED( idx, digit ) ) { board[ idx ] = SET_DIGIT( digit ); update( idx ); add_move( idx, digit, CHOICE ); return digit; } return -1; }
/* Fill square with given digit, and update state. * Returns 0 on success, else -1 on error (i.e. invalid fill) */ static int fill( int idx, int digit ) { assert( 0 != digit ); if( !IS_EMPTY( idx ) ) return ( DIGIT( idx ) == digit ) ? 0 : -1; if( DISALLOWED( idx, digit ) ) return -1; board[ idx ] = SET_DIGIT( digit ); update( idx ); add_move( idx, digit, 0 ); return 0; }
int bcd2_add(long *bcd_low, long *bcd_high, long addend) { long tmp_lo, tmp_hi, carry, res; int digit; bin_bcd2(addend, &tmp_lo, &tmp_hi); carry = 0; for (digit=0; digit < 14; digit++) { res = GET_DIGIT(digit, *bcd_low, *bcd_high); res += GET_DIGIT(digit, tmp_lo, tmp_hi); res += carry; carry = res / 10; res %= 10; SET_DIGIT(res, digit, bcd_low, bcd_high); } return(carry); }
/* Management of the move history - adding a move */ static void add_move( int idx, int digit, int choice ) { int i; if( sizeof( history ) / sizeof( int ) == idx_history ) compress( 81 ); /* Never ignore the last move */ history[ idx_history++ ] = SET_INDEX( idx ) | SET_DIGIT( digit ) | choice; /* Ignore all previous references to idx */ for( i = idx_history - 2 ; 0 <= i ; --i ) if( GET_INDEX( history[ i ] ) == idx ) { history[ i ] |= IGNORED; break; } }
int bcd2_div(long *bcd_low, long *bcd_high, long divisor) { long tmp_lo, tmp_hi, carry, d1, res, digit; carry = 0; tmp_lo = *bcd_low; tmp_hi = *bcd_high; *bcd_low = *bcd_high = 0; for (digit=13; digit >= 0; digit--) { d1 = GET_DIGIT(digit, tmp_lo, tmp_hi); d1 += 10 * carry; res = d1 / divisor; carry = d1 % divisor; SET_DIGIT(res, digit, bcd_low, bcd_high); } return(carry); }
/* Refresh board state, given move history. Note that this can yield * an incorrect state if the user has made errors - return -1 if an * incorrect state is generated; else return 0 for a correct state. */ static int reapply( void ) { int digit, idx, j; int allok = 0; rb->memset( board, 0x00, sizeof( board ) ); for( j = 0 ; j < idx_history ; ++j ) if( !( history[ j ] & IGNORED ) && 0 != GET_DIGIT( history[ j ] ) ) { idx = GET_INDEX( history[ j ] ); digit = GET_DIGIT( history[ j ] ); if( !IS_EMPTY( idx ) || DISALLOWED( idx, digit ) ) allok = -1; board[ idx ] = SET_DIGIT( digit ); if( history[ j ] & FIXED ) board[ idx ] |= FIXED; update( idx ); } return allok; }
int bcd2_sub(long *bcd_low, long *bcd_high, long subend) { long tmp_lo, tmp_hi, carry, res; int digit; bin_bcd2(subend, &tmp_lo, &tmp_hi); carry = 0; for (digit=0; digit < 14; digit++) { res = GET_DIGIT(digit, *bcd_low, *bcd_high); res -= GET_DIGIT(digit, tmp_lo, tmp_hi); res -= carry; if (res < 0) { res += 10; carry = 1; } SET_DIGIT(res, digit, bcd_low, bcd_high); } return(carry); }
int bcd2_mul(long *bcd_low, long *bcd_high, long multiplier) { long tmp_lo, tmp_hi, carry, m_lo, m_hi, m1, m2; int udigit, ldigit, res; tmp_lo = *bcd_low; tmp_hi = *bcd_high; bin_bcd2(multiplier, &m_lo, &m_hi); *bcd_low = 0; *bcd_high = 0; carry = 0; for (ldigit=0; ldigit < 14; ldigit++) { m1 = GET_DIGIT(ldigit, m_lo, m_hi); carry = 0; for (udigit=0; udigit < 14; udigit++) { m2 = GET_DIGIT(udigit, tmp_lo, tmp_hi); res = m1 * m2; res += carry; if (udigit + ldigit < 14) { carry = GET_DIGIT(udigit + ldigit, *bcd_low, *bcd_high); res += carry; } carry = res / 10; res %= 10; if (udigit + ldigit < 14) { SET_DIGIT(res, udigit + ldigit, bcd_low, bcd_high); } } } return(carry); }
/* * big integer unsigned division * * dividend in bip.op1, divisor in bip.op2 * quotient in bip.res, remainder in bip.rem */ static void bigUdiv(void) { ObjRef tmp; int nd1; int nd2; int nd3; int i, j, k, l; unsigned char r; unsigned short scale; unsigned short carry; unsigned short aux; unsigned short qhat; unsigned short v1, v2; unsigned short uj0, uj1, uj2, two; /* get sizes of operands */ nd1 = GET_ND(bip.op1); nd2 = GET_ND(bip.op2); /* check for division by zero */ if (nd2 == 0) { fatalError("division by zero"); } /* check for small dividend */ if (bigUcmp() < 0) { /* res = 0 */ bip.res = newBig(0); SET_ND(bip.res, 0); /* rem = op1; BUT THIS HAS TO BE A COPY! */ bip.rem = newBig(nd1); for (i = 0; i < nd1; i++) { SET_DIGIT(bip.rem, i, GET_DIGIT(bip.op1, i)); } SET_ND(bip.rem, nd1); return; } /* check for single digit divisor */ if (nd2 == 1) { /* yes - use simple division by single digit divisor */ bip.rem = bip.op1; r = bigUdiv1(GET_DIGIT(bip.op2, 0)); bip.res = bip.rem; if (r == 0) { bip.rem = newBig(0); SET_ND(bip.rem, 0); } else { bip.rem = newBig(1); SET_ND(bip.rem, 1); SET_DIGIT(bip.rem, 0, r); } return; } /* * now for the general case */ #if DIV_CHK_01 printf("div_chk #01: division, general case\n"); printf(" dividend = "); bigDump(stdout, bip.op1); printf("\n"); printf(" divisor = "); bigDump(stdout, bip.op2); printf("\n"); #endif /* determine scale factor for normalization */ scale = (unsigned short) 256 / ((unsigned short) GET_DIGIT(bip.op2, nd2 - 1) + 1); #if DIV_CHK_02 printf("div_chk #02: scale factor = %02X\n", scale); #endif /* normalize dividend, result is in bip.rem */ bip.rem = newBig(nd1 + 1); carry = 0x00; for (i = 0; i < nd1; i++) { aux = (unsigned short) GET_DIGIT(bip.op1, i) * scale + carry; SET_DIGIT(bip.rem, i, aux & 0xFF); carry = aux >> 8; } SET_DIGIT(bip.rem, i, carry); SET_ND(bip.rem, nd1 + 1); #if DIV_CHK_03 printf("div_chk #03: normalized dividend = "); bigDump(stdout, bip.rem); printf("\n"); #endif /* normalize divisor, result is in bip.res */ bip.res = newBig(nd2); carry = 0x00; for (i = 0; i < nd2; i++) { aux = (unsigned short) GET_DIGIT(bip.op2, i) * scale + carry; SET_DIGIT(bip.res, i, aux & 0xFF); carry = aux >> 8; } if (carry != 0x00) { /* overflow in divisor normalization */ fatalError("internal library error #4 - THIS SHOULD NEVER HAPPEN!"); } SET_ND(bip.res, nd2); #if DIV_CHK_04 printf("div_chk #04: normalized divisor = "); bigDump(stdout, bip.res); printf("\n"); #endif /* allocate quotient */ nd3 = nd1 - nd2 + 1; tmp = newBig(nd3); /* extract the two most significand digits of divisor */ v1 = (unsigned short) GET_DIGIT(bip.res, nd2 - 1); v2 = (unsigned short) GET_DIGIT(bip.res, nd2 - 2); /* loop on digits of dividend and compute digits of quotient */ /* j is index into dividend, k is index into quotient */ for (j = nd1, k = nd3 - 1; k >= 0; j--, k--) { #if DIV_CHK_05 printf("div_chk #05: j = %d, k = %d\n", j, k); #endif /* calculate qhat */ uj0 = (unsigned short) GET_DIGIT(bip.rem, j); uj1 = (unsigned short) GET_DIGIT(bip.rem, j - 1); uj2 = (unsigned short) GET_DIGIT(bip.rem, j - 2); two = (uj0 << 8) | uj1; if (uj0 == v1) { qhat = (unsigned short) 255; #if DIV_CHK_06 printf("div_chk #06a: qhat = %02X\n", qhat); #endif } else { qhat = two / v1; #if DIV_CHK_06 printf("div_chk #06b: qhat = %02X\n", qhat); #endif } while (qhat * v2 > (((two - qhat * v1) << 8) | uj2)) { qhat--; #if DIV_CHK_07 printf("div_chk #07: qhat decremented, is now %02X\n", qhat); #endif } /* multiply and subtract */ /* l is index into dividend, i is index into divisor */ carry = 0xFF; for (l = j - nd2, i = 0; i < nd2; l++, i++) { aux = (unsigned short) GET_DIGIT(bip.rem, l) - (unsigned short) GET_DIGIT(bip.res, i) * qhat + carry + 0xFE01; SET_DIGIT(bip.rem, l, aux & 0xFF); carry = aux >> 8; } aux = (unsigned short) GET_DIGIT(bip.rem, l) + carry + 0xFE01; SET_DIGIT(bip.rem, l, aux & 0xFF); carry = aux >> 8; #if DIV_CHK_08 printf("div_chk #08: remainder = "); bigDump(stdout, bip.rem); printf("\n"); #endif /* test remainder and possibly add back */ if (carry != 0xFF) { /* qhat is one too large */ qhat--; #if DIV_CHK_09 printf("div_chk #09: qhat final correction, is now %02X\n", qhat); #endif /* add back */ /* l is index into dividend, i is index into divisor */ carry = 0x00; for (l = j - nd2, i = 0; i < nd2; l++, i++) { aux = (unsigned short) GET_DIGIT(bip.rem, l) + (unsigned short) GET_DIGIT(bip.res, i) + carry; SET_DIGIT(bip.rem, l, aux & 0xFF); carry = aux >> 8; } aux = (unsigned short) GET_DIGIT(bip.rem, l) + carry; SET_DIGIT(bip.rem, l, aux & 0xFF); carry = aux >> 8; if (carry != 0x01) { /* missing carry in add-back sum */ fatalError("internal library error #5 - THIS SHOULD NEVER HAPPEN!"); } #if DIV_CHK_10 printf("div_chk #10: remainder = "); bigDump(stdout, bip.rem); printf("\n"); #endif } /* store quotient digit */ SET_DIGIT(tmp, k, qhat); #if DIV_CHK_11 printf("div_chk #11: quotient digit = %02X\n", qhat); #endif }