/*
 *  @author Ranides Atterwim <ranides@gmail.com>
 *  @copyright Ranides Atterwim
 *  @license WTFPL
 *  @url http://ranides.net/projects/assira
 */

package net.ranides.assira.math;

/**
 * Klasa pomocnicza realizująca częste operacje bitowe.
 * @author ranides
 */
public final class Bitwise {

    private Bitwise() { }

    /**
     * Sprawdza, czy wartość {@code value} ma ustawione wszystkie bity podane
     * w masce {@code mask}, lub na odwrót: czy {@code mask} ma ustawione bity
     * {@code value}.
     * @param value
     * @param mask
     * @return
     */
    public static boolean match(int value, int mask) {
        return mask==(value & mask) || value==(value & mask);
    }

    /**
     * Sprawdza, czy wartość {@code value} ma ustawione wszystkie bity podane
     * w masce {@code mask}, lub na odwrót: czy {@code mask} ma ustawione bity
     * {@code value}.
     * @param value
     * @param mask
     * @return
     */
    public static boolean match(long value, long mask) {
        return mask==(value & mask) || value==(value & mask);
    }
    
    /**
     * Sprawdza, czy wartość {@code value} ma ustawione wszystkie bity podane
     * w masce {@code mask}. Bity, które nie są ustawione w masce, mogą mieć
     * dowolną wartość.
     * @param value
     * @param mask
     * @return
     */
    public static boolean has(int value, int mask) {
        return mask==(value & mask);
    }
    
    /**
     * Sprawdza, czy wartość {@code value} ma ustawione wszystkie bity podane
     * w masce {@code mask}. Bity, które nie są ustawione w masce, mogą mieć
     * dowolną wartość.
     * @param value
     * @param mask
     * @return
     */
    public static boolean has(long value, long mask) {
        return mask==(value & mask);
    }
    
    /**
     * Sprawdza, czy w zmiennej {@code value} jest ustawiony bit o numerze 
     * {@code index}. Bity są indeksowane o zera.
     * @param value
     * @param index
     * @return
     */
    public static boolean at(int value, int index) {
        return 0!=(value & (1 << index));
    }
    
    /**
     * Sprawdza, czy w zmiennej {@code value} jest ustawiony bit o numerze 
     * {@code index}. Bity są indeksowane o zera.
     * @param value
     * @param index
     * @return
     */
    public static boolean at(long value, int index) {
        return 0!=(value & (1 << index));
    }
    
    /**
     * Oblicza sumę logiczną (or) wszystkich podanych wartości.
     * @param values
     * @return
     */
    public static int or(int... values) {
        int sum = 0;
        for(int value : values) { sum |= value; }
        return sum;
    }
    
    /**
     * Oblicza sumę logiczną (or) wszystkich podanych wartości.
     * @param values
     * @return
     */
    public static long or(long... values) {
        long sum = 0;
        for(long value : values) { sum |= value; }
        return sum;
    }
    
    /**
     * Oblicza koniunkcję logiczną (and) wszystkich podanych wartości.
     * @param values
     * @return
     */
    public static int and(int... values) {
        int sum = ~0;
        for(int value : values) { sum &= value; }
        return sum;
    }
    
    /**
     * Oblicza koniunkcję logiczną (and) wszystkich podanych wartości.
     * @param values
     * @return
     */
    public static long and(long... values) {
        long sum = ~0;
        for(long value : values) { sum &= value; }
        return sum;
    }

}
