package doglet;
import nova.Machine;
import nova.Store;
import nova.special;
import java.math.BigInteger;
/**
* Warranty & Liability
* To the extent permitted by applicable law and unless explicitly
* otherwise agreed upon, XLOG Technologies AG makes no warranties
* regarding the provided information. XLOG Technologies AG assumes
* no liability that any problems might be solved with the information
* provided by XLOG Technologies AG.
*
* Rights & License
* All industrial property rights regarding the information - copyright
* and patent rights in particular - are the sole property of XLOG
* Technologies AG. If the company was not the originator of some
* excerpts, XLOG Technologies AG has at least obtained the right to
* reproduce, change and translate the information.
*
* Reproduction is restricted to the whole unaltered document. Reproduction
* of the information is only allowed for non-commercial uses. Selling,
* giving away or letting of the execution of the library is prohibited.
* The library can be distributed as part of your applications and libraries
* for execution provided this comment remains unchanged.
*
* Restrictions
* Only to be distributed with programs that add significant and primary
* functionality to the library. Not to be distributed with additional
* software intended to replace any components of the library.
*
* Trademarks
* Jekejeke is a registered trademark of XLOG Technologies AG.
*/
public final class bitlib {
/******************************************************************/
/* Random Numbers */
/******************************************************************/
/**
* random(F):
* The predicate succeeds in F with a uniform random 64-bit
* floating point value in the interval [0..1).
*/
private static boolean test_random(Object[] args) {
Object alpha = Double.valueOf(Math.random());
return Machine.exec_unify(args[0], alpha);
}
/******************************************************************/
/* msb/2, lsb/2 and popcount/2 */
/******************************************************************/
/**
* msb(X):
* If X is an integer, then the function returns the most significant bit.
*/
private static Number arit_msb(Object[] args) {
Number alpha = Machine.exec_eval(args[0]);
special.check_integer(alpha);
int result;
if (alpha instanceof Integer) {
int x = alpha.intValue();
result = 31 - Integer.numberOfLeadingZeros((x < 0 ? ~x : x));
} else {
result = ((BigInteger) alpha).bitLength() - 1;
}
return Integer.valueOf(result);
}
/**
* lsb(X):
* If X is an integer, then the function returns the least significant bit.
*/
private static Number arit_lsb(Object[] args) {
Number alpha = Machine.exec_eval(args[0]);
special.check_integer(alpha);
int result;
if (alpha instanceof Integer) {
int x = alpha.intValue();
if (x == 0) {
result = -1;
} else {
result = Integer.numberOfTrailingZeros(x);
}
} else {
result = ((BigInteger) alpha).getLowestSetBit();
}
return Integer.valueOf(result);
}
/**
* popcount(X):
* If X is an integer, then the function returns the number of ones.
*/
private static Number arit_popcount(Object[] args) {
Number alpha = Machine.exec_eval(args[0]);
special.check_integer(alpha);
int result;
if (alpha instanceof Integer) {
int x = alpha.intValue();
if (x < 0) {
x = -x;
result = Integer.bitCount(x) + Integer.numberOfTrailingZeros(x) - 1;
} else {
result = Integer.bitCount(x);
}
} else {
result = ((BigInteger) alpha).bitCount();
}
return Integer.valueOf(result);
}
/******************************************************************/
/* testbit/2, sqrtrem/3 and isqrt/3 */
/******************************************************************/
/**
* testbit(X, Y):
* The predicate succeeds when X /\ (1 << Y) =\= 0.
*/
private static boolean test_testbit(Object[] args) {
Object alpha = Machine.exec_build(args[0]);
special.check_integer(alpha);
Object beta = Machine.exec_build(args[1]);
special.check_integer(beta);
if (beta instanceof BigInteger)
throw Machine.make_error(new Store.Compound("representation_error",
new Object[]{"int"}));
int k = ((Number) beta).intValue();
if (k < 0)
throw Machine.make_error(new Store.Compound("domain_error",
new Object[]{"not_less_than_zero", beta}));
if (alpha instanceof Integer) {
if (k < 31) {
return (((Number) alpha).intValue() & (1 << k)) != 0;
} else {
return ((Number) alpha).intValue() < 0;
}
} else {
return ((BigInteger)alpha).testBit(k);
}
}
/**
* sqrtrem(X, Y, Z):
* If X is an integer then the predicate succeeds in Y with the
* integer square root of X, and in Z with the remainder X-Y*Y.
*/
private static boolean test_sqrtrem(Object[] args) {
Object alpha = Machine.exec_build(args[0]);
special.check_integer(alpha);
Number ressqrt;
Number resrem;
if (alpha instanceof Integer) {
int k = ((Integer)alpha).intValue();
if (k < 0)
throw Machine.make_error(new Store.Compound("domain_error",
new Object[]{"not_less_than_zero", alpha}));
int j = (int)Math.floor(Math.sqrt(k));
ressqrt = Integer.valueOf(j);
resrem = Integer.valueOf(k-j*j);
} else {
if (((BigInteger)alpha).signum() < 0)
throw Machine.make_error(new Store.Compound("domain_error",
new Object[]{"not_less_than_zero", alpha}));
BigInteger[] res2 = ((BigInteger)alpha).sqrtAndRemainder();
ressqrt = special.norm_bigint(res2[0]);
resrem = special.norm_bigint(res2[1]);
}
if (!Machine.exec_unify(args[1],ressqrt))
return false;
return Machine.exec_unify(args[2],resrem);
}
/**
* isqrt(X, Y):
* If X is an integer then the predicate succeeds in Y with the
* integer square root of X.
*/
private static Number arit_isqrt(Object[] args) {
Number alpha = Machine.exec_eval(args[0]);
special.check_integer(alpha);
Number ressqrt;
if (alpha instanceof Integer) {
int k = alpha.intValue();
if (k < 0)
throw Machine.make_error(new Store.Compound("domain_error",
new Object[]{"not_less_than_zero", alpha}));
int j = (int)Math.floor(Math.sqrt(k));
ressqrt = Integer.valueOf(j);
} else {
if (((BigInteger)alpha).signum() < 0)
throw Machine.make_error(new Store.Compound("domain_error",
new Object[]{"not_less_than_zero", alpha}));
BigInteger res2 = ((BigInteger)alpha).sqrt();
ressqrt = special.norm_bigint(res2);
}
return ressqrt;
}
/******************************************************************/
/* Bit Lib Init */
/******************************************************************/
public static void main() {
Store.set("random", 1, special.make_check(bitlib::test_random));
Store.set("msb", 2, special.make_arithmetic(bitlib::arit_msb));
Store.set("lsb", 2, special.make_arithmetic(bitlib::arit_lsb));
Store.set("popcount", 2, special.make_arithmetic(bitlib::arit_popcount));
Store.set("testbit", 2, special.make_check(bitlib::test_testbit));
Store.set("sqrtrem", 3, special.make_check(bitlib::test_sqrtrem));
Store.set("isqrt", 2, special.make_arithmetic(bitlib::arit_isqrt));
}
}