001package org.clafer.ir; 002 003import gnu.trove.TIntCollection; 004import gnu.trove.iterator.TIntIterator; 005import org.clafer.collection.BoundIntIterator; 006import org.clafer.collection.ReverseBoundIntIterator; 007import org.clafer.collection.SingleIntIterator; 008 009/** 010 * Boolean domain. 011 * 012 * @author jimmy 013 */ 014public enum IrBoolDomain implements IrDomain { 015 016 TrueDomain(true, false), 017 FalseDomain(false, true), 018 BoolDomain(true, true); 019 private final boolean hasTrue, hasFalse; 020 021 private IrBoolDomain(boolean hasTrue, boolean hasFalse) { 022 assert hasTrue || hasFalse; 023 // At least one has to be true. 024 this.hasTrue = hasTrue; 025 this.hasFalse = hasFalse; 026 } 027 028 @Override 029 public boolean isBounded() { 030 return true; 031 } 032 033 /** 034 * @param value test this value 035 * @return {@code true} if and only if the domain contains the {@code value}, 036 * {@code false} otherwise 037 */ 038 public boolean contains(boolean value) { 039 return value ? hasTrue : hasFalse; 040 } 041 042 @Override 043 public boolean contains(int value) { 044 switch (value) { 045 case 0: 046 return hasFalse; 047 case 1: 048 return hasTrue; 049 default: 050 return false; 051 } 052 } 053 054 @Override 055 public int getLowBound() { 056 return hasFalse ? 0 : 1; 057 } 058 059 @Override 060 public int getHighBound() { 061 return hasTrue ? 1 : 0; 062 } 063 064 @Override 065 public boolean isEmpty() { 066 return false; 067 } 068 069 @Override 070 public int size() { 071 return hasTrue && hasFalse ? 2 : 1; 072 } 073 074 /** 075 * Reverse the domain. Maps {0}->{1}, {1}->{0}, and {0,1}->{0,1}. 076 * 077 * @return the inverted domain 078 */ 079 public IrBoolDomain invert() { 080 switch (this) { 081 case TrueDomain: 082 return FalseDomain; 083 case FalseDomain: 084 return TrueDomain; 085 case BoolDomain: 086 return BoolDomain; 087 default: 088 throw new IllegalStateException(); 089 } 090 } 091 092 @Override 093 public int[] getValues() { 094 switch (this) { 095 case TrueDomain: 096 return new int[]{1}; 097 case FalseDomain: 098 return new int[]{0}; 099 case BoolDomain: 100 return new int[]{0, 1}; 101 default: 102 throw new IllegalStateException(); 103 } 104 } 105 106 @Override 107 public TIntIterator iterator() { 108 return iterator(true); 109 } 110 111 @Override 112 public TIntIterator iterator(boolean increasing) { 113 switch (this) { 114 case TrueDomain: 115 return new SingleIntIterator(1); 116 case FalseDomain: 117 return new SingleIntIterator(0); 118 case BoolDomain: 119 return increasing ? new BoundIntIterator(0, 1) : new ReverseBoundIntIterator(0, 1); 120 default: 121 throw new IllegalStateException(); 122 } 123 } 124 125 @Override 126 public void transferTo(TIntCollection collection) { 127 if (hasTrue) { 128 collection.add(1); 129 } 130 if (hasFalse) { 131 collection.add(0); 132 } 133 } 134 135 @Override 136 public String toString() { 137 switch (this) { 138 case TrueDomain: 139 return "{1}"; 140 case FalseDomain: 141 return "{0}"; 142 case BoolDomain: 143 return "{0,1}"; 144 default: 145 throw new IllegalStateException(); 146 } 147 } 148}