├── .gitattributes ├── .gitignore ├── CSharp.BitmapIndex.sln ├── CSharp.BitmapIndex ├── BICriteria.cs ├── BIKey.cs ├── BitmapIndex.cs ├── CSharp.BitmapIndex.csproj ├── Properties │ └── AssemblyInfo.cs └── libs │ └── EWAH.dll └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Visual Studio 3 | ################# 4 | 5 | ## Ignore Visual Studio temporary files, build results, and 6 | ## files generated by popular Visual Studio add-ons. 7 | 8 | # User-specific files 9 | *.suo 10 | *.user 11 | *.sln.docstates 12 | 13 | # Build results 14 | 15 | [Dd]ebug/ 16 | [Rr]elease/ 17 | x64/ 18 | build/ 19 | [Bb]in/ 20 | [Oo]bj/ 21 | 22 | # MSTest test Results 23 | [Tt]est[Rr]esult*/ 24 | [Bb]uild[Ll]og.* 25 | 26 | *_i.c 27 | *_p.c 28 | *.ilk 29 | *.meta 30 | *.obj 31 | *.pch 32 | *.pdb 33 | *.pgc 34 | *.pgd 35 | *.rsp 36 | *.sbr 37 | *.tlb 38 | *.tli 39 | *.tlh 40 | *.tmp 41 | *.tmp_proj 42 | *.log 43 | *.vspscc 44 | *.vssscc 45 | .builds 46 | *.pidb 47 | *.log 48 | *.scc 49 | 50 | # Visual C++ cache files 51 | ipch/ 52 | *.aps 53 | *.ncb 54 | *.opensdf 55 | *.sdf 56 | *.cachefile 57 | 58 | # Visual Studio profiler 59 | *.psess 60 | *.vsp 61 | *.vspx 62 | 63 | # Guidance Automation Toolkit 64 | *.gpState 65 | 66 | # ReSharper is a .NET coding add-in 67 | _ReSharper*/ 68 | *.[Rr]e[Ss]harper 69 | 70 | # TeamCity is a build add-in 71 | _TeamCity* 72 | 73 | # DotCover is a Code Coverage Tool 74 | *.dotCover 75 | 76 | # NCrunch 77 | *.ncrunch* 78 | .*crunch*.local.xml 79 | 80 | # Installshield output folder 81 | [Ee]xpress/ 82 | 83 | # DocProject is a documentation generator add-in 84 | DocProject/buildhelp/ 85 | DocProject/Help/*.HxT 86 | DocProject/Help/*.HxC 87 | DocProject/Help/*.hhc 88 | DocProject/Help/*.hhk 89 | DocProject/Help/*.hhp 90 | DocProject/Help/Html2 91 | DocProject/Help/html 92 | 93 | # Click-Once directory 94 | publish/ 95 | 96 | # Publish Web Output 97 | *.Publish.xml 98 | *.pubxml 99 | 100 | # NuGet Packages Directory 101 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 102 | #packages/ 103 | 104 | # Windows Azure Build Output 105 | csx 106 | *.build.csdef 107 | 108 | # Windows Store app package directory 109 | AppPackages/ 110 | 111 | # Others 112 | sql/ 113 | *.Cache 114 | ClientBin/ 115 | [Ss]tyle[Cc]op.* 116 | ~$* 117 | *~ 118 | *.dbmdl 119 | *.[Pp]ublish.xml 120 | *.pfx 121 | *.publishsettings 122 | 123 | # RIA/Silverlight projects 124 | Generated_Code/ 125 | 126 | # Backup & report files from converting an old project file to a newer 127 | # Visual Studio version. Backup files are not needed, because we have git ;-) 128 | _UpgradeReport_Files/ 129 | Backup*/ 130 | UpgradeLog*.XML 131 | UpgradeLog*.htm 132 | 133 | # SQL Server files 134 | App_Data/*.mdf 135 | App_Data/*.ldf 136 | 137 | ############# 138 | ## Windows detritus 139 | ############# 140 | 141 | # Windows image file caches 142 | Thumbs.db 143 | ehthumbs.db 144 | 145 | # Folder config file 146 | Desktop.ini 147 | 148 | # Recycle Bin used on file shares 149 | $RECYCLE.BIN/ 150 | 151 | # Mac crap 152 | .DS_Store 153 | 154 | 155 | ############# 156 | ## Python 157 | ############# 158 | 159 | *.py[co] 160 | 161 | # Packages 162 | *.egg 163 | *.egg-info 164 | dist/ 165 | build/ 166 | eggs/ 167 | parts/ 168 | var/ 169 | sdist/ 170 | develop-eggs/ 171 | .installed.cfg 172 | 173 | # Installer logs 174 | pip-log.txt 175 | 176 | # Unit test / coverage reports 177 | .coverage 178 | .tox 179 | 180 | #Translations 181 | *.mo 182 | 183 | #Mr Developer 184 | .mr.developer.cfg 185 | -------------------------------------------------------------------------------- /CSharp.BitmapIndex.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharp.BitmapIndex", "CSharp.BitmapIndex\CSharp.BitmapIndex.csproj", "{5E7618C7-CF0D-4E49-BD63-975A6BA8501E}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Any CPU = Debug|Any CPU 9 | Release|Any CPU = Release|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {5E7618C7-CF0D-4E49-BD63-975A6BA8501E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {5E7618C7-CF0D-4E49-BD63-975A6BA8501E}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {5E7618C7-CF0D-4E49-BD63-975A6BA8501E}.Release|Any CPU.ActiveCfg = Release|Any CPU 15 | {5E7618C7-CF0D-4E49-BD63-975A6BA8501E}.Release|Any CPU.Build.0 = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /CSharp.BitmapIndex/BICriteria.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace BitmapIndex 7 | { 8 | public class BICriteria 9 | { 10 | public enum Operator 11 | { 12 | EQUALS = 0, 13 | EQUALS_OR_EMPTY = 1, 14 | NOT_EQUALS = 2, 15 | NOT_EQUALS_OR_EMPTY = 3, 16 | EMPTY_ONLY = 6, 17 | OR = 4, 18 | AND = 5 19 | } 20 | 21 | private BIKey _key; 22 | private Operator _criteriaOperator; 23 | private BICriteria _left; 24 | private BICriteria _right; 25 | 26 | private BICriteria(BIKey key, Operator criteriaOperator) 27 | { 28 | _key = key; 29 | _criteriaOperator = criteriaOperator; 30 | } 31 | 32 | private BICriteria(BICriteria left, BICriteria right, Operator criteriaOperator) 33 | { 34 | _left = left; 35 | _right = right; 36 | _criteriaOperator = criteriaOperator; 37 | } 38 | 39 | public Operator CriteriaOperator 40 | { 41 | get 42 | { 43 | return _criteriaOperator; 44 | } 45 | } 46 | 47 | public BIKey Key 48 | { 49 | get 50 | { 51 | return _key; 52 | } 53 | } 54 | 55 | public BICriteria LeftCriteria 56 | { 57 | get 58 | { 59 | return _left; 60 | } 61 | } 62 | 63 | public BICriteria RightCriteria 64 | { 65 | get 66 | { 67 | return _right; 68 | } 69 | } 70 | 71 | public BICriteria or(BICriteria criteria) 72 | { 73 | return new BICriteria(this, criteria, Operator.OR); 74 | } 75 | 76 | public BICriteria and(BICriteria criteria) 77 | { 78 | return new BICriteria(this, criteria, Operator.AND); 79 | } 80 | 81 | public BICriteria andEquals(BIKey key) 82 | { 83 | return and(new BICriteria(key, Operator.EQUALS)); 84 | } 85 | 86 | public BICriteria andNotEquals(BIKey key) { 87 | return and(new BICriteria(key, Operator.NOT_EQUALS)); 88 | } 89 | 90 | public BICriteria andEqualsOrEmpty(BIKey key) { 91 | return and(new BICriteria(key, Operator.EQUALS_OR_EMPTY)); 92 | } 93 | 94 | public BICriteria andNotEqualsOrEmpty(BIKey key) { 95 | return and(new BICriteria(key, Operator.NOT_EQUALS_OR_EMPTY)); 96 | } 97 | 98 | public BICriteria andEmptyOnly(int group) 99 | { 100 | return and(new BICriteria(new BIKey(group, null), Operator.EMPTY_ONLY)); 101 | } 102 | 103 | public BICriteria andEmptyOnly(BIKey.BIGroup group) 104 | { 105 | return and(new BICriteria(new BIKey(group, null), Operator.EMPTY_ONLY)); 106 | } 107 | 108 | public BICriteria orEquals(BIKey key) { 109 | return or(new BICriteria(key, Operator.EQUALS)); 110 | } 111 | 112 | public BICriteria orNotEquals(BIKey key) { 113 | return or(new BICriteria(key, Operator.NOT_EQUALS)); 114 | } 115 | 116 | public BICriteria orEqualsOrEmpty(BIKey key) { 117 | return or(new BICriteria(key, Operator.EQUALS_OR_EMPTY)); 118 | } 119 | 120 | public BICriteria orNotEqualsOrEmpty(BIKey key) { 121 | return or(new BICriteria(key, Operator.NOT_EQUALS_OR_EMPTY)); 122 | } 123 | 124 | public BICriteria orEmptyOnly(int group) 125 | { 126 | return or(new BICriteria(new BIKey(group, null), Operator.EMPTY_ONLY)); 127 | } 128 | 129 | public BICriteria orEmptyOnly(BIKey.BIGroup group) 130 | { 131 | return or(new BICriteria(new BIKey(group, null), Operator.EMPTY_ONLY)); 132 | } 133 | 134 | public static BICriteria equals(BIKey key) { 135 | return new BICriteria(key, Operator.EQUALS); 136 | } 137 | 138 | public static BICriteria notEquals(BIKey key) { 139 | return new BICriteria(key, Operator.NOT_EQUALS); 140 | } 141 | 142 | public static BICriteria equalsOrEmpty(BIKey key) { 143 | return new BICriteria(key, Operator.EQUALS_OR_EMPTY); 144 | } 145 | 146 | public static BICriteria notEqualsOrEmpty(BIKey key) { 147 | return new BICriteria(key, Operator.NOT_EQUALS_OR_EMPTY); 148 | } 149 | 150 | public static BICriteria emptyOnly(int group) 151 | { 152 | return new BICriteria(new BIKey(group, null), Operator.EMPTY_ONLY); 153 | } 154 | 155 | public static BICriteria emptyOnly(BIKey.BIGroup group) 156 | { 157 | return new BICriteria(new BIKey(group, null), Operator.EMPTY_ONLY); 158 | } 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /CSharp.BitmapIndex/BIKey.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace BitmapIndex 7 | { 8 | public class BIKey 9 | { 10 | public class BIGroup 11 | { 12 | private int _group; 13 | private string _subGroup; 14 | 15 | public BIGroup(int group) 16 | { 17 | _group = group; 18 | _subGroup = string.Empty; 19 | } 20 | 21 | public BIGroup(int group, string subGroup) 22 | { 23 | _group = group; 24 | _subGroup = (subGroup != null ? subGroup : string.Empty); 25 | } 26 | 27 | public int Group 28 | { 29 | get 30 | { 31 | return _group; 32 | } 33 | } 34 | 35 | public string SubGroup 36 | { 37 | get 38 | { 39 | return _subGroup; 40 | } 41 | } 42 | 43 | public override bool Equals(object obj) 44 | { 45 | if (this == obj) 46 | return true; 47 | 48 | BIGroup compare = obj as BIGroup; 49 | 50 | if (compare == null) 51 | return false; 52 | 53 | return (compare._group == _group && compare._subGroup.Equals(_subGroup)); 54 | } 55 | 56 | public override int GetHashCode() 57 | { 58 | int result = 17; 59 | result = 31 * result + _group; 60 | result = (_subGroup.Length > 0 ? 31 * result + _subGroup.GetHashCode() : result); 61 | 62 | return result; 63 | } 64 | } 65 | 66 | private BIGroup _group; 67 | private string _key; 68 | 69 | public BIKey(int group, Object key) 70 | { 71 | _group = new BIGroup(group); 72 | 73 | if (key != null) 74 | _key = key.ToString(); 75 | else 76 | _key = string.Empty; 77 | } 78 | 79 | public BIKey(int group, string subGroup, Object key) 80 | { 81 | _group = new BIGroup(group, subGroup); 82 | 83 | if (key != null) 84 | _key = key.ToString(); 85 | else 86 | _key = string.Empty; 87 | } 88 | 89 | public BIKey(BIGroup group, Object key) 90 | { 91 | _group = group; 92 | 93 | if (key != null) 94 | _key = key.ToString(); 95 | else 96 | _key = string.Empty; 97 | } 98 | 99 | public BIGroup Group 100 | { 101 | get 102 | { 103 | return _group; 104 | } 105 | } 106 | 107 | public string Key 108 | { 109 | get 110 | { 111 | return _key; 112 | } 113 | } 114 | 115 | public override bool Equals(object obj) 116 | { 117 | if (this == obj) 118 | return true; 119 | 120 | BIKey compare = obj as BIKey; 121 | 122 | if (compare == null) 123 | return false; 124 | 125 | return (compare._group.Equals(_group) && compare._key.Equals(_key)); 126 | } 127 | 128 | public override int GetHashCode() 129 | { 130 | int result = _group.GetHashCode(); 131 | result = 31 * result + _key.GetHashCode(); 132 | 133 | return result; 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /CSharp.BitmapIndex/BitmapIndex.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Ewah; 6 | 7 | namespace BitmapIndex 8 | { 9 | public class BitmapIndex 10 | { 11 | private Dictionary _bitmaps; 12 | private Dictionary _emptyBitmaps; 13 | private int _maxBitSize = 0; 14 | 15 | public BitmapIndex() 16 | { 17 | _bitmaps = new Dictionary(); 18 | _emptyBitmaps = new Dictionary(); 19 | } 20 | 21 | public void Set(BIKey key, int bit) 22 | { 23 | EwahCompressedBitArray bitmap; 24 | EwahCompressedBitArray emptyBitmap; 25 | 26 | if (_bitmaps.ContainsKey(key)) 27 | bitmap = _bitmaps[key]; 28 | else 29 | { 30 | bitmap = new EwahCompressedBitArray(); 31 | _bitmaps.Add(key, bitmap); 32 | } 33 | 34 | if (_emptyBitmaps.ContainsKey(key.Group)) 35 | emptyBitmap = _emptyBitmaps[key.Group]; 36 | else 37 | { 38 | emptyBitmap = new EwahCompressedBitArray(); 39 | _emptyBitmaps.Add(key.Group, emptyBitmap); 40 | } 41 | 42 | bitmap.Set(bit); 43 | 44 | emptyBitmap.Not(); 45 | emptyBitmap.Set(bit); 46 | emptyBitmap.Not(); 47 | 48 | _maxBitSize = (_maxBitSize < (bit + 1) ? (bit + 1) : _maxBitSize); 49 | } 50 | 51 | private EwahCompressedBitArray getFilledBitmap(bool fill) 52 | { 53 | EwahCompressedBitArray bitmap = new EwahCompressedBitArray(); 54 | bitmap.SetSizeInBits(_maxBitSize, fill); 55 | 56 | return bitmap; 57 | } 58 | 59 | private EwahCompressedBitArray getCopyBitmap(EwahCompressedBitArray bitmap) 60 | { 61 | var bit = (EwahCompressedBitArray)bitmap.Clone(); 62 | bit.SetSizeInBits(_maxBitSize, false); 63 | 64 | return bit; 65 | } 66 | 67 | private EwahCompressedBitArray getEmptyBitmap(BIKey key) 68 | { 69 | EwahCompressedBitArray bitmap; 70 | 71 | if (_emptyBitmaps.ContainsKey(key.Group)) 72 | { 73 | bitmap = (EwahCompressedBitArray)_emptyBitmaps[key.Group].Clone(); 74 | bitmap.SetSizeInBits(_maxBitSize, true); 75 | } 76 | else 77 | bitmap = getFilledBitmap(true); 78 | 79 | return bitmap; 80 | } 81 | 82 | 83 | private class Snapshot 84 | { 85 | public BICriteria criteria; 86 | public EwahCompressedBitArray left; 87 | public EwahCompressedBitArray right; 88 | public int state; 89 | } 90 | 91 | public EwahCompressedBitArray query(BICriteria criteria) 92 | { 93 | // This method could use recursion which would make it more readable 94 | // For performance reasons, and to avoid StackOverflowException, it 95 | // uses the Snapshot class to avoid recursion 96 | 97 | if (criteria == null) 98 | throw new ArgumentNullException("criteria"); 99 | 100 | EwahCompressedBitArray temp; 101 | Snapshot previous; 102 | Snapshot next; 103 | 104 | Snapshot current = new Snapshot(); 105 | current.criteria = criteria; 106 | current.state = 0; 107 | 108 | Stack stack = new Stack(); 109 | stack.Push(current); 110 | 111 | while (stack.Count > 0) 112 | { 113 | current = stack.Pop(); 114 | 115 | if (stack.Count > 0) 116 | previous = stack.Peek(); 117 | else 118 | previous = null; 119 | 120 | if (current.criteria.CriteriaOperator == BusinessLayer.Uteis.BICriteria.Operator.OR || 121 | current.criteria.CriteriaOperator == BusinessLayer.Uteis.BICriteria.Operator.AND) 122 | { 123 | if (current.state == 0) 124 | { 125 | current.state = 1; 126 | stack.Push(current); 127 | 128 | next = new Snapshot(); 129 | next.criteria = current.criteria.LeftCriteria; 130 | next.state = 0; 131 | stack.Push(next); 132 | 133 | continue; 134 | } 135 | else if (current.state == 1) 136 | { 137 | current.state = 2; 138 | stack.Push(current); 139 | 140 | next = new Snapshot(); 141 | next.criteria = current.criteria.RightCriteria; 142 | next.state = 0; 143 | stack.Push(next); 144 | 145 | continue; 146 | } 147 | else 148 | { 149 | if (current.criteria.CriteriaOperator == BusinessLayer.Uteis.BICriteria.Operator.AND) 150 | temp = (current.left.And(current.right)); 151 | else 152 | temp = (current.left.Or(current.right)); 153 | 154 | if (previous == null) 155 | { 156 | return temp; 157 | } 158 | else if (previous.state == 1) 159 | { 160 | previous.left = temp; 161 | } 162 | else if (previous.state == 2) 163 | { 164 | previous.right = temp; 165 | } 166 | 167 | continue; 168 | } 169 | } 170 | else 171 | { 172 | if (current.criteria.CriteriaOperator == BusinessLayer.Uteis.BICriteria.Operator.EMPTY_ONLY) 173 | { 174 | if (previous == null) 175 | return getEmptyBitmap(current.criteria.Key); 176 | else if (previous.state == 1) 177 | previous.left = getEmptyBitmap(current.criteria.Key); 178 | else if (previous.state == 2) 179 | previous.right = getEmptyBitmap(current.criteria.Key); 180 | 181 | continue; 182 | } 183 | else 184 | { 185 | EwahCompressedBitArray bitmap; 186 | 187 | if (!_bitmaps.ContainsKey(current.criteria.Key)) 188 | bitmap = getFilledBitmap(false); 189 | else 190 | bitmap = getCopyBitmap(_bitmaps[current.criteria.Key]); 191 | 192 | if (current.criteria.CriteriaOperator == BusinessLayer.Uteis.BICriteria.Operator.NOT_EQUALS || 193 | current.criteria.CriteriaOperator == BusinessLayer.Uteis.BICriteria.Operator.NOT_EQUALS_OR_EMPTY) 194 | bitmap.Not(); 195 | 196 | if (current.criteria.CriteriaOperator == BusinessLayer.Uteis.BICriteria.Operator.NOT_EQUALS_OR_EMPTY || 197 | current.criteria.CriteriaOperator == BusinessLayer.Uteis.BICriteria.Operator.EQUALS_OR_EMPTY) 198 | bitmap = bitmap.Or(getEmptyBitmap(current.criteria.Key)); 199 | 200 | if (previous == null) 201 | return bitmap; 202 | else if (previous.state == 1) 203 | previous.left = bitmap; 204 | else if (previous.state == 2) 205 | previous.right = bitmap; 206 | 207 | continue; 208 | } 209 | } 210 | } 211 | 212 | temp = new EwahCompressedBitArray(); 213 | temp.SetSizeInBits(_maxBitSize, false); 214 | return temp; 215 | } 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /CSharp.BitmapIndex/CSharp.BitmapIndex.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {5E7618C7-CF0D-4E49-BD63-975A6BA8501E} 9 | Library 10 | Properties 11 | BitmapIndex 12 | BitmapIndex 13 | v4.0 14 | 512 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 60 | -------------------------------------------------------------------------------- /CSharp.BitmapIndex/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("CSharp.BitmapIndex")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("CSharp.BitmapIndex")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2013")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("a8223c1f-54d5-4941-a3ac-596b11bf7d93")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /CSharp.BitmapIndex/libs/EWAH.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reinaldoarrosi/CSharp-BitmapIndex/HEAD/CSharp.BitmapIndex/libs/EWAH.dll -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #Bitmap Index (C#) 2 | 3 | This is a bitmap indexing library based on the amazing EWAH bitmap compression library available at https://github.com/lemire/csharpewah 4 | 5 | There is also a Java version: https://github.com/reinaldoarrosi/bitmapindex 6 | 7 | ##Installing 8 | 9 | - Clone this repository 10 | - Open solution in Visual Studio 2010 or later 11 | - Build solution 12 | - Add a reference to the BitmapIndex.dll and to the EWAH.dll available in the libs folder 13 | - Have fun! 14 | 15 | ##Usage 16 | 17 | ###Creating the index 18 | The index is a simple key-value pair where each key is an instance of BIKey and each value is a bitmap (compressed through the EWAH Bitmap lib). 19 | 20 | Suppose we have the following table: 21 | 22 | 23 | 26 | 29 | 32 | 35 | 38 | 39 | 40 | 43 | 46 | 49 | 52 | 55 | 56 | 57 | 60 | 63 | 66 | 69 | 72 | 73 | 74 | 77 | 80 | 83 | 86 | 89 | 90 | 91 | 94 | 97 | 100 | 103 | 106 | 107 | 108 | 111 | 114 | 117 | 120 | 123 | 124 |
24 | Printer 25 | 27 | Brand 28 | 30 | # of cartridges 31 | 33 | Pages/second 34 | 36 | DPI 37 |
41 | Model 1 42 | 44 | HP 45 | 47 | 2 48 | 50 | 20 51 | 53 | 300 54 |
58 | Model 2 59 | 61 | HP 62 | 64 | 3 65 | 67 | 30 68 | 70 | 700 71 |
75 | Model 3 76 | 78 | Cannon 79 | 81 | 1 82 | 84 | 40 85 | 87 | N/A 88 |
92 | Model 4 93 | 95 | Samsung 96 | 98 | 2 99 | 101 | 40 102 | 104 | N/A 105 |
109 | Model 5 110 | 112 | Cannon 113 | 115 | 2 116 | 118 | 20 119 | 121 | 400 122 |
125 | 126 | To create the index that represents this dataset we would do: 127 | 128 | // Attributes constants 129 | public static int BRAND = 1; 130 | public static int CARTRIDGES = 2; 131 | public static int PPS = 3; 132 | public static int DPI = 4; 133 | 134 | // Brands constants 135 | public static int HP = 1; 136 | public static int CANNON = 2; 137 | public static int SAMSUNG = 3; 138 | 139 | BitmapIndex index = new BitmapIndex(); 140 | index.Set(new BIKey(BRAND, HP), 0); 141 | index.Set(new BIKey(BRAND, HP), 1); 142 | index.Set(new BIKey(BRAND, CANNON), 2); 143 | index.Set(new BIKey(BRAND, SAMSUNG), 3); 144 | index.Set(new BIKey(BRAND, CANNON), 4); 145 | 146 | index.Set(new BIKey(CARTRIDGES, 2), 0); 147 | index.Set(new BIKey(CARTRIDGES, 3), 1); 148 | index.Set(new BIKey(CARTRIDGES, 1), 2); 149 | index.Set(new BIKey(CARTRIDGES, 2), 3); 150 | index.Set(new BIKey(CARTRIDGES, 2), 4); 151 | 152 | index.Set(new BIKey(PPS, 20), 0); 153 | index.Set(new BIKey(PPS, 30), 1); 154 | index.Set(new BIKey(PPS, 40), 2); 155 | index.Set(new BIKey(PPS, 40), 3); 156 | index.Set(new BIKey(PPS, 20), 4); 157 | 158 | index.Set(new BIKey(DPI, 300), 0); 159 | index.Set(new BIKey(DPI, 700), 1); 160 | index.Set(new BIKey(DPI, 400), 4); 161 | 162 | Each BIKey is composed of two parts: group and value. The group represents an attribute in our dataset, and the value represents the many values that an atribute might have. Each group of a BIKey can (optionally) be splitted into 2 fragments (group and subgroup - BIKey.BIGroup class), this allows for more flexibility but almost never necessary. 163 | 164 | Each bit in a bitmap represents a row in our table. Each BIKey is an represents the possible combinations of attributes and values, so for each of theses combination a bitmap will be created. 165 | 166 | With the index created we can query it though the BICriteria class. BICriteria contains some static methods that are used to create the criteria for our query. These criterias can also be joined with 'ands' and 'ors' to produce more complex criterias. 167 | 168 | An example is to find printers where the brand is HP and with a printing performance of 20 or 30 pages per second. 169 | 170 | BICriteria criteria = BICriteria.equals(new BIKey(BRAND, HP)) 171 | .and(BICriteria.equals(new BIKey(PPS, 20)) 172 | .or(BICriteria.equals(new BIKey(PPS, 30)))) 173 | 174 | EWAHCompressedBitmap result = index.query(criteria); 175 | 176 | The query returns an EWAHCompressedBitmap and we can use the **GetPositions()** method to retrieve the bits that are set, which in turn matches the rows that satisfies our criteria. 177 | 178 | Thanks to the amazing compression offered by the EWAH compression library this index scales pretty well and can be kept in-memory even with millions of rows in the dataset. The speed is amazing due to the fact that the criteria evaluation is simply a binary operation. --------------------------------------------------------------------------------