Index: src/test/org/apache/lucene/index/TestOmitTf.java
===================================================================
--- src/test/org/apache/lucene/index/TestOmitTf.java (revision 0)
+++ src/test/org/apache/lucene/index/TestOmitTf.java (revision 0)
@@ -0,0 +1,363 @@
+package org.apache.lucene.index;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Collection;
+
+import org.apache.lucene.util.LuceneTestCase;
+import org.apache.lucene.util._TestUtil;
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.HitCollector;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Searcher;
+import org.apache.lucene.search.Similarity;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.BooleanClause.Occur;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.MockRAMDirectory;
+
+
+public class TestOmitTf extends LuceneTestCase {
+
+ public static class SimpleSimilarity extends Similarity {
+ public float lengthNorm(String field, int numTerms) { return 1.0f; }
+ public float queryNorm(float sumOfSquaredWeights) { return 1.0f; }
+
+ public float tf(float freq) { return freq; }
+
+ public float sloppyFreq(int distance) { return 2.0f; }
+ public float idf(Collection terms, Searcher searcher) { return 1.0f; }
+ public float idf(int docFreq, int numDocs) { return 1.0f; }
+ public float coord(int overlap, int maxOverlap) { return 1.0f; }
+ }
+
+
+ // Tests whether the DocumentWriter correctly enable the
+ // omitTf bit in the FieldInfo
+ public void testOmitTf() throws Exception {
+ Directory ram = new MockRAMDirectory();
+ Analyzer analyzer = new StandardAnalyzer();
+ IndexWriter writer = new IndexWriter(ram, analyzer, true, IndexWriter.MaxFieldLength.LIMITED);
+ Document d = new Document();
+
+ // this field will have Tf
+ Field f1 = new Field("f1", "This field has term freqs", Field.Store.NO, Field.Index.TOKENIZED);
+ d.add(f1);
+
+ // this field will NOT have Tf
+ Field f2 = new Field("f2", "This field has NO Tf in all docs", Field.Store.NO, Field.Index.TOKENIZED);
+ f2.setOmitTf(true);
+ d.add(f2);
+
+ writer.addDocument(d);
+ writer.optimize();
+ // now we add another document which has term freq for field f2 and not for f1 and verify if the SegmentMerger
+ // keep things constant
+ d = new Document();
+
+ // Reverese
+ f1.setOmitTf(true);
+ d.add(f1);
+
+ f2.setOmitTf(false);
+ d.add(f2);
+
+ writer.addDocument(d);
+ // force merge
+ writer.optimize();
+ // flush
+ writer.close();
+ _TestUtil.checkIndex(ram);
+
+ // only one segment in the index, so we can cast to SegmentReader
+ SegmentReader reader = (SegmentReader) IndexReader.open(ram);
+ FieldInfos fi = reader.fieldInfos();
+ assertTrue("OmitTf field bit should be set.", fi.fieldInfo("f1").omitTf);
+ assertTrue("OmitTf field bit should be set.", fi.fieldInfo("f2").omitTf);
+
+ reader.close();
+ ram.close();
+ }
+
+ // Tests whether merging of docs that have different
+ // omitTf for the same field works
+ public void testMixedMerge() throws Exception {
+ Directory ram = new MockRAMDirectory();
+ Analyzer analyzer = new StandardAnalyzer();
+ IndexWriter writer = new IndexWriter(ram, analyzer, true, IndexWriter.MaxFieldLength.LIMITED);
+ writer.setMaxBufferedDocs(3);
+ writer.setMergeFactor(2);
+ Document d = new Document();
+
+ // this field will have Tf
+ Field f1 = new Field("f1", "This field has term freqs", Field.Store.NO, Field.Index.TOKENIZED);
+ d.add(f1);
+
+ // this field will NOT have Tf
+ Field f2 = new Field("f2", "This field has NO Tf in all docs", Field.Store.NO, Field.Index.TOKENIZED);
+ f2.setOmitTf(true);
+ d.add(f2);
+
+ for(int i=0;i<30;i++)
+ writer.addDocument(d);
+
+ // now we add another document which has term freq for field f2 and not for f1 and verify if the SegmentMerger
+ // keep things constant
+ d = new Document();
+
+ // Reverese
+ f1.setOmitTf(true);
+ d.add(f1);
+
+ f2.setOmitTf(false);
+ d.add(f2);
+
+ for(int i=0;i<30;i++)
+ writer.addDocument(d);
+
+ // force merge
+ writer.optimize();
+ // flush
+ writer.close();
+
+ _TestUtil.checkIndex(ram);
+
+ // only one segment in the index, so we can cast to SegmentReader
+ SegmentReader reader = (SegmentReader) IndexReader.open(ram);
+ FieldInfos fi = reader.fieldInfos();
+ assertTrue("OmitTf field bit should be set.", fi.fieldInfo("f1").omitTf);
+ assertTrue("OmitTf field bit should be set.", fi.fieldInfo("f2").omitTf);
+
+ reader.close();
+ ram.close();
+ }
+
+ // Make sure first adding docs that do not omitTf for
+ // field X, then adding docs that do omitTf for that same
+ // field,
+ public void testMixedRAM() throws Exception {
+ Directory ram = new MockRAMDirectory();
+ Analyzer analyzer = new StandardAnalyzer();
+ IndexWriter writer = new IndexWriter(ram, analyzer, true, IndexWriter.MaxFieldLength.LIMITED);
+ writer.setMaxBufferedDocs(10);
+ writer.setMergeFactor(2);
+ Document d = new Document();
+
+ // this field will have Tf
+ Field f1 = new Field("f1", "This field has term freqs", Field.Store.NO, Field.Index.TOKENIZED);
+ d.add(f1);
+
+ // this field will NOT have Tf
+ Field f2 = new Field("f2", "This field has NO Tf in all docs", Field.Store.NO, Field.Index.TOKENIZED);
+ d.add(f2);
+
+ for(int i=0;i<5;i++)
+ writer.addDocument(d);
+
+ f2.setOmitTf(true);
+
+ for(int i=0;i<20;i++)
+ writer.addDocument(d);
+
+ // force merge
+ writer.optimize();
+
+ // flush
+ writer.close();
+
+ _TestUtil.checkIndex(ram);
+
+ // only one segment in the index, so we can cast to SegmentReader
+ SegmentReader reader = (SegmentReader) IndexReader.open(ram);
+ FieldInfos fi = reader.fieldInfos();
+ assertTrue("OmitTf field bit should not be set.", !fi.fieldInfo("f1").omitTf);
+ assertTrue("OmitTf field bit should be set.", fi.fieldInfo("f2").omitTf);
+
+ reader.close();
+ ram.close();
+ }
+
+ private void assertNoPrx(Directory dir) throws Throwable {
+ final String[] files = dir.list();
+ for(int i=0;i>> 1;
- if ((code & 1) != 0)
- termFreq = 1;
- else
- termFreq = freq.readVInt();
+ if (field.omitTf)
+ docID += code;
+ else {
+ docID += code >>> 1;
+ if ((code & 1) != 0)
+ termFreq = 1;
+ else
+ termFreq = freq.readVInt();
+ }
+ assert docID != p.lastDocID;
+
return true;
}
}
Index: src/java/org/apache/lucene/index/TermsHash.java
===================================================================
--- src/java/org/apache/lucene/index/TermsHash.java (revision 678362)
+++ src/java/org/apache/lucene/index/TermsHash.java (working copy)
@@ -42,7 +42,6 @@
final TermsHash nextTermsHash;
final int bytesPerPosting;
final int postingsFreeChunk;
- final int streamCount;
final DocumentsWriter docWriter;
TermsHash primaryTermsHash;
@@ -55,7 +54,6 @@
public TermsHash(final DocumentsWriter docWriter, boolean trackAllocations, final TermsHashConsumer consumer, final TermsHash nextTermsHash) {
this.docWriter = docWriter;
this.consumer = consumer;
- this.streamCount = consumer.streamCount;
this.nextTermsHash = nextTermsHash;
this.trackAllocations = trackAllocations;
Index: src/java/org/apache/lucene/index/SegmentTermPositions.java
===================================================================
--- src/java/org/apache/lucene/index/SegmentTermPositions.java (revision 678362)
+++ src/java/org/apache/lucene/index/SegmentTermPositions.java (working copy)
@@ -60,6 +60,9 @@
}
public final int nextPosition() throws IOException {
+ if (currentFieldOmitTf)
+ // This field does not store term freq, positions, payloads
+ return 0;
// perform lazy skips if neccessary
lazySkip();
proxCount--;
@@ -116,6 +119,7 @@
}
private void skipPositions(int n) throws IOException {
+ assert !currentFieldOmitTf;
for (int f = n; f > 0; f--) { // skip unread positions
readDeltaPosition();
skipPayload();
Index: src/java/org/apache/lucene/index/SegmentMerger.java
===================================================================
--- src/java/org/apache/lucene/index/SegmentMerger.java (revision 678362)
+++ src/java/org/apache/lucene/index/SegmentMerger.java (working copy)
@@ -83,6 +83,10 @@
checkAbort = new CheckAbort(merge, directory);
termIndexInterval = writer.getTermIndexInterval();
}
+
+ boolean hasProx() {
+ return fieldInfos.hasProx();
+ }
/**
* Add an IndexReader to the collection of readers that are to be merged
@@ -164,6 +168,10 @@
// Basic files
for (int i = 0; i < IndexFileNames.COMPOUND_EXTENSIONS.length; i++) {
String ext = IndexFileNames.COMPOUND_EXTENSIONS[i];
+
+ if (ext.equals(IndexFileNames.PROX_EXTENSION) && !hasProx())
+ continue;
+
if (mergeDocStores || (!ext.equals(IndexFileNames.FIELDS_EXTENSION) &&
!ext.equals(IndexFileNames.FIELDS_INDEX_EXTENSION)))
files.add(segment + "." + ext);
@@ -198,11 +206,11 @@
}
private void addIndexed(IndexReader reader, FieldInfos fieldInfos, Collection names, boolean storeTermVectors, boolean storePositionWithTermVector,
- boolean storeOffsetWithTermVector, boolean storePayloads) throws IOException {
+ boolean storeOffsetWithTermVector, boolean storePayloads, boolean omitTf) throws IOException {
Iterator i = names.iterator();
while (i.hasNext()) {
String field = (String)i.next();
- fieldInfos.add(field, true, storeTermVectors, storePositionWithTermVector, storeOffsetWithTermVector, !reader.hasNorms(field), storePayloads);
+ fieldInfos.add(field, true, storeTermVectors, storePositionWithTermVector, storeOffsetWithTermVector, !reader.hasNorms(field), storePayloads, omitTf);
}
}
@@ -265,15 +273,16 @@
SegmentReader segmentReader = (SegmentReader) reader;
for (int j = 0; j < segmentReader.getFieldInfos().size(); j++) {
FieldInfo fi = segmentReader.getFieldInfos().fieldInfo(j);
- fieldInfos.add(fi.name, fi.isIndexed, fi.storeTermVector, fi.storePositionWithTermVector, fi.storeOffsetWithTermVector, !reader.hasNorms(fi.name), fi.storePayloads);
+ fieldInfos.add(fi.name, fi.isIndexed, fi.storeTermVector, fi.storePositionWithTermVector, fi.storeOffsetWithTermVector, !reader.hasNorms(fi.name), fi.storePayloads, fi.omitTf);
}
} else {
- addIndexed(reader, fieldInfos, reader.getFieldNames(IndexReader.FieldOption.TERMVECTOR_WITH_POSITION_OFFSET), true, true, true, false);
- addIndexed(reader, fieldInfos, reader.getFieldNames(IndexReader.FieldOption.TERMVECTOR_WITH_POSITION), true, true, false, false);
- addIndexed(reader, fieldInfos, reader.getFieldNames(IndexReader.FieldOption.TERMVECTOR_WITH_OFFSET), true, false, true, false);
- addIndexed(reader, fieldInfos, reader.getFieldNames(IndexReader.FieldOption.TERMVECTOR), true, false, false, false);
- addIndexed(reader, fieldInfos, reader.getFieldNames(IndexReader.FieldOption.STORES_PAYLOADS), false, false, false, true);
- addIndexed(reader, fieldInfos, reader.getFieldNames(IndexReader.FieldOption.INDEXED), false, false, false, false);
+ addIndexed(reader, fieldInfos, reader.getFieldNames(IndexReader.FieldOption.TERMVECTOR_WITH_POSITION_OFFSET), true, true, true, false, false);
+ addIndexed(reader, fieldInfos, reader.getFieldNames(IndexReader.FieldOption.TERMVECTOR_WITH_POSITION), true, true, false, false, false);
+ addIndexed(reader, fieldInfos, reader.getFieldNames(IndexReader.FieldOption.TERMVECTOR_WITH_OFFSET), true, false, true, false, false);
+ addIndexed(reader, fieldInfos, reader.getFieldNames(IndexReader.FieldOption.TERMVECTOR), true, false, false, false, false);
+ addIndexed(reader, fieldInfos, reader.getFieldNames(IndexReader.FieldOption.OMIT_TF), false, false, false, false, true);
+ addIndexed(reader, fieldInfos, reader.getFieldNames(IndexReader.FieldOption.STORES_PAYLOADS), false, false, false, true, false);
+ addIndexed(reader, fieldInfos, reader.getFieldNames(IndexReader.FieldOption.INDEXED), false, false, false, false, false);
fieldInfos.add(reader.getFieldNames(IndexReader.FieldOption.UNINDEXED), false);
}
}
@@ -477,7 +486,8 @@
private final void mergeTerms() throws CorruptIndexException, IOException {
try {
freqOutput = directory.createOutput(segment + ".frq");
- proxOutput = directory.createOutput(segment + ".prx");
+ if (hasProx())
+ proxOutput = directory.createOutput(segment + ".prx");
termInfosWriter =
new TermInfosWriter(directory, segment, fieldInfos,
termIndexInterval);
@@ -561,11 +571,20 @@
*/
private final int mergeTermInfo(SegmentMergeInfo[] smis, int n)
throws CorruptIndexException, IOException {
- long freqPointer = freqOutput.getFilePointer();
- long proxPointer = proxOutput.getFilePointer();
+ final long freqPointer = freqOutput.getFilePointer();
+ final long proxPointer;
+ if (proxOutput != null)
+ proxPointer = proxOutput.getFilePointer();
+ else
+ proxPointer = 0;
- int df = appendPostings(smis, n); // append posting data
-
+ int df;
+ if (fieldInfos.fieldInfo(smis[0].term.field).omitTf) { // append posting data
+ df = appendPostingsNoTf(smis, n);
+ } else{
+ df = appendPostings(smis, n);
+ }
+
long skipPointer = skipListWriter.writeSkip(freqOutput);
if (df > 0) {
@@ -672,6 +691,53 @@
return df;
}
+ /** Process postings from multiple segments without tf, all positioned on the
+ * same term. Writes out merged entries only into freqOutput, proxOut is not written.
+ *
+ * @param smis array of segments
+ * @param n number of cells in the array actually occupied
+ * @return number of documents across all segments where this term was found
+ * @throws CorruptIndexException if the index is corrupt
+ * @throws IOException if there is a low-level IO error
+ */
+ private final int appendPostingsNoTf(SegmentMergeInfo[] smis, int n)
+ throws CorruptIndexException, IOException {
+ int lastDoc = 0;
+ int df = 0; // number of docs w/ term
+ skipListWriter.resetSkip();
+ int lastPayloadLength = -1; // ensures that we write the first length
+ for (int i = 0; i < n; i++) {
+ SegmentMergeInfo smi = smis[i];
+ TermPositions postings = smi.getPositions();
+ assert postings != null;
+ int base = smi.base;
+ int[] docMap = smi.getDocMap();
+ postings.seek(smi.termEnum);
+ while (postings.next()) {
+ int doc = postings.doc();
+ if (docMap != null)
+ doc = docMap[doc]; // map around deletions
+ doc += base; // convert to merged space
+
+ if (doc < 0 || (df > 0 && doc <= lastDoc))
+ throw new CorruptIndexException("docs out of order (" + doc +
+ " <= " + lastDoc + " )");
+
+ df++;
+
+ if ((df % skipInterval) == 0) {
+ skipListWriter.setSkipData(lastDoc, false, lastPayloadLength);
+ skipListWriter.bufferSkip(df);
+ }
+
+ int docCode = (doc - lastDoc);
+ lastDoc = doc;
+ freqOutput.writeVInt(docCode); // write doc & freq=1
+ }
+ }
+ return df;
+ }
+
private void mergeNorms() throws IOException {
byte[] normBuffer = null;
IndexOutput output = null;
Index: src/java/org/apache/lucene/index/TermsHashPerField.java
===================================================================
--- src/java/org/apache/lucene/index/TermsHashPerField.java (revision 678362)
+++ src/java/org/apache/lucene/index/TermsHashPerField.java (working copy)
@@ -57,9 +57,9 @@
bytePool = perThread.bytePool;
docState = perThread.docState;
fieldState = docInverterPerField.fieldState;
- streamCount = perThread.termsHash.streamCount;
+ this.consumer = perThread.consumer.addField(this, fieldInfo);
+ streamCount = consumer.getStreamCount();
numPostingInt = 2*streamCount;
- this.consumer = perThread.consumer.addField(this, fieldInfo);
this.fieldInfo = fieldInfo;
if (nextPerThread != null)
nextPerField = (TermsHashPerField) nextPerThread.addField(docInverterPerField, fieldInfo);
@@ -488,6 +488,7 @@
}
void writeVInt(int stream, int i) {
+ assert stream < streamCount;
while ((i & ~0x7F) != 0) {
writeByte(stream, (byte)((i & 0x7f) | 0x80));
i >>>= 7;
Index: src/java/org/apache/lucene/index/SegmentInfo.java
===================================================================
--- src/java/org/apache/lucene/index/SegmentInfo.java (revision 678362)
+++ src/java/org/apache/lucene/index/SegmentInfo.java (working copy)
@@ -77,6 +77,8 @@
private int delCount; // How many deleted docs in this segment, or -1 if not yet known
// (if it's an older index)
+ private boolean hasProx; // True if this segment has any fields with omitTf==false
+
public SegmentInfo(String name, int docCount, Directory dir) {
this.name = name;
this.docCount = docCount;
@@ -89,14 +91,15 @@
docStoreSegment = name;
docStoreIsCompoundFile = false;
delCount = 0;
+ hasProx = true;
}
public SegmentInfo(String name, int docCount, Directory dir, boolean isCompoundFile, boolean hasSingleNormFile) {
- this(name, docCount, dir, isCompoundFile, hasSingleNormFile, -1, null, false);
+ this(name, docCount, dir, isCompoundFile, hasSingleNormFile, -1, null, false, true);
}
public SegmentInfo(String name, int docCount, Directory dir, boolean isCompoundFile, boolean hasSingleNormFile,
- int docStoreOffset, String docStoreSegment, boolean docStoreIsCompoundFile) {
+ int docStoreOffset, String docStoreSegment, boolean docStoreIsCompoundFile, boolean hasProx) {
this(name, docCount, dir);
this.isCompoundFile = (byte) (isCompoundFile ? YES : NO);
this.hasSingleNormFile = hasSingleNormFile;
@@ -104,6 +107,7 @@
this.docStoreOffset = docStoreOffset;
this.docStoreSegment = docStoreSegment;
this.docStoreIsCompoundFile = docStoreIsCompoundFile;
+ this.hasProx = hasProx;
delCount = 0;
assert docStoreOffset == -1 || docStoreSegment != null;
}
@@ -180,6 +184,10 @@
assert delCount <= docCount;
} else
delCount = -1;
+ if (format <= SegmentInfos.FORMAT_HAS_PROX)
+ hasProx = input.readByte() == 1;
+ else
+ hasProx = true;
} else {
delGen = CHECK_DIR;
normGen = null;
@@ -190,6 +198,7 @@
docStoreIsCompoundFile = false;
docStoreSegment = null;
delCount = -1;
+ hasProx = true;
}
}
@@ -507,8 +516,18 @@
}
output.writeByte(isCompoundFile);
output.writeInt(delCount);
+ output.writeByte((byte) (hasProx ? 1:0));
}
+ void setHasProx(boolean hasProx) {
+ this.hasProx = hasProx;
+ clearFiles();
+ }
+
+ boolean getHasProx() {
+ return hasProx;
+ }
+
private void addIfExists(List files, String fileName) throws IOException {
if (dir.fileExists(fileName))
files.add(fileName);
Index: src/java/org/apache/lucene/index/FreqProxTermsWriter.java
===================================================================
--- src/java/org/apache/lucene/index/FreqProxTermsWriter.java (revision 678362)
+++ src/java/org/apache/lucene/index/FreqProxTermsWriter.java (working copy)
@@ -31,10 +31,6 @@
final class FreqProxTermsWriter extends TermsHashConsumer {
- FreqProxTermsWriter() {
- streamCount = 2;
- }
-
public TermsHashConsumerPerThread addThread(TermsHashPerThread perThread) {
return new FreqProxTermsWriterPerThread(perThread);
}
@@ -102,8 +98,13 @@
state.docWriter.writer.getTermIndexInterval());
final IndexOutput freqOut = state.directory.createOutput(state.segmentFileName(IndexFileNames.FREQ_EXTENSION));
- final IndexOutput proxOut = state.directory.createOutput(state.segmentFileName(IndexFileNames.PROX_EXTENSION));
+ final IndexOutput proxOut;
+ if (fieldInfos.hasProx())
+ proxOut = state.directory.createOutput(state.segmentFileName(IndexFileNames.PROX_EXTENSION));
+ else
+ proxOut = null;
+
final DefaultSkipListWriter skipListWriter = new DefaultSkipListWriter(termsOut.skipInterval,
termsOut.maxSkipLevels,
state.numDocsInRAM, freqOut, proxOut);
@@ -135,6 +136,7 @@
int numPostings = perField.numPostings;
perField.reset();
perField.shrinkHash(numPostings);
+ fields[i].reset();
}
start = end;
@@ -148,13 +150,15 @@
}
freqOut.close();
- proxOut.close();
+ if (proxOut != null) {
+ state.flushedFiles.add(state.segmentFileName(IndexFileNames.PROX_EXTENSION));
+ proxOut.close();
+ }
termsOut.close();
// Record all files we have flushed
state.flushedFiles.add(state.segmentFileName(IndexFileNames.FIELD_INFOS_EXTENSION));
state.flushedFiles.add(state.segmentFileName(IndexFileNames.FREQ_EXTENSION));
- state.flushedFiles.add(state.segmentFileName(IndexFileNames.PROX_EXTENSION));
state.flushedFiles.add(state.segmentFileName(IndexFileNames.TERMS_EXTENSION));
state.flushedFiles.add(state.segmentFileName(IndexFileNames.TERMS_INDEX_EXTENSION));
}
@@ -205,8 +209,12 @@
}
final int skipInterval = termsOut.skipInterval;
- final boolean currentFieldStorePayloads = fields[0].fieldInfo.storePayloads;
+ final boolean currentFieldOmitTf = fields[0].fieldInfo.omitTf;
+ // If current field omits tf then it cannot store
+ // payloads. We silently drop the payloads in this case:
+ final boolean currentFieldStorePayloads = currentFieldOmitTf ? false : fields[0].fieldInfo.storePayloads;
+
FreqProxFieldMergeState[] termStates = new FreqProxFieldMergeState[numFields];
while(numFields > 0) {
@@ -235,8 +243,12 @@
final char[] text = termStates[0].text;
final int start = termStates[0].textOffset;
- long freqPointer = freqOut.getFilePointer();
- long proxPointer = proxOut.getFilePointer();
+ final long freqPointer = freqOut.getFilePointer();
+ final long proxPointer;
+ if (proxOut != null)
+ proxPointer = proxOut.getFilePointer();
+ else
+ proxPointer = 0;
skipListWriter.resetSkip();
@@ -261,45 +273,53 @@
assert doc < flushState.numDocsInRAM;
assert doc > lastDoc || df == 1;
- final int newDocCode = (doc-lastDoc)<<1;
-
- lastDoc = doc;
-
final ByteSliceReader prox = minState.prox;
// Carefully copy over the prox + payload info,
// changing the format to match Lucene's segment
// format.
- for(int j=0;j 0)
- copyBytes(prox, proxOut, payloadLength);
- } else {
- assert 0 == (code & 1);
- proxOut.writeVInt(code>>1);
+ if (!currentFieldOmitTf) {
+ // omitTf == false so we do write positions & payload
+ assert proxOut != null;
+ for(int j=0;j 0)
+ copyBytes(prox, proxOut, payloadLength);
+ } else {
+ assert 0 == (code & 1);
+ proxOut.writeVInt(code>>1);
+ }
+ } //End for
+
+ final int newDocCode = (doc-lastDoc)<<1;
+
+ if (1 == termDocFreq) {
+ freqOut.writeVInt(newDocCode|1);
+ } else {
+ freqOut.writeVInt(newDocCode);
+ freqOut.writeVInt(termDocFreq);
}
- }
-
- if (1 == termDocFreq) {
- freqOut.writeVInt(newDocCode|1);
} else {
- freqOut.writeVInt(newDocCode);
- freqOut.writeVInt(termDocFreq);
+ // omitTf==true: we store only the docs, without
+ // term freq, positions, payloads
+ freqOut.writeVInt(doc-lastDoc);
}
+ lastDoc = doc;
+
if (!minState.nextDoc()) {
// Remove from termStates
Index: src/java/org/apache/lucene/index/SegmentReader.java
===================================================================
--- src/java/org/apache/lucene/index/SegmentReader.java (revision 678362)
+++ src/java/org/apache/lucene/index/SegmentReader.java (working copy)
@@ -298,6 +298,12 @@
fieldInfos = new FieldInfos(cfsDir, segment + ".fnm");
+ boolean anyProx = false;
+ final int numFields = fieldInfos.size();
+ for(int i=0;!anyProx && i 0;
+ assert omitTf || p.docFreq > 0;
- if (docState.docID != p.lastDocID) {
- // Term not yet seen in the current doc but previously
- // seen in other doc(s) since the last flush
-
- // Now that we know doc freq for previous doc,
- // write it & lastDocCode
- if (1 == p.docFreq)
- termsHashPerField.writeVInt(0, p.lastDocCode|1);
- else {
+ if (omitTf) {
+ if (docState.docID != p.lastDocID) {
+ assert docState.docID > p.lastDocID;
termsHashPerField.writeVInt(0, p.lastDocCode);
- termsHashPerField.writeVInt(0, p.docFreq);
+ p.lastDocCode = docState.docID - p.lastDocID;
+ p.lastDocID = docState.docID;
}
- p.docFreq = 1;
- p.lastDocCode = (docState.docID - p.lastDocID) << 1;
- p.lastDocID = docState.docID;
- writeProx(t, p, fieldState.position);
} else {
- p.docFreq++;
- writeProx(t, p, fieldState.position-p.lastPosition);
+ if (docState.docID != p.lastDocID) {
+ assert docState.docID > p.lastDocID;
+ // Term not yet seen in the current doc but previously
+ // seen in other doc(s) since the last flush
+
+ // Now that we know doc freq for previous doc,
+ // write it & lastDocCode
+ if (1 == p.docFreq)
+ termsHashPerField.writeVInt(0, p.lastDocCode|1);
+ else {
+ termsHashPerField.writeVInt(0, p.lastDocCode);
+ termsHashPerField.writeVInt(0, p.docFreq);
+ }
+ p.docFreq = 1;
+ p.lastDocCode = (docState.docID - p.lastDocID) << 1;
+ p.lastDocID = docState.docID;
+ writeProx(t, p, fieldState.position);
+ } else {
+ p.docFreq++;
+ writeProx(t, p, fieldState.position-p.lastPosition);
+ }
}
}
Index: src/java/org/apache/lucene/index/FieldInfo.java
===================================================================
--- src/java/org/apache/lucene/index/FieldInfo.java (revision 678362)
+++ src/java/org/apache/lucene/index/FieldInfo.java (working copy)
@@ -27,13 +27,14 @@
boolean storeOffsetWithTermVector;
boolean storePositionWithTermVector;
- boolean omitNorms; // omit norms associated with indexed fields
+ boolean omitNorms; // omit norms associated with indexed fields
+ boolean omitTf; // omit tf
boolean storePayloads; // whether this field stores payloads together with term positions
FieldInfo(String na, boolean tk, int nu, boolean storeTermVector,
boolean storePositionWithTermVector, boolean storeOffsetWithTermVector,
- boolean omitNorms, boolean storePayloads) {
+ boolean omitNorms, boolean storePayloads, boolean omitTf) {
name = na;
isIndexed = tk;
number = nu;
@@ -42,15 +43,16 @@
this.storePositionWithTermVector = storePositionWithTermVector;
this.omitNorms = omitNorms;
this.storePayloads = storePayloads;
+ this.omitTf = omitTf;
}
public Object clone() {
return new FieldInfo(name, isIndexed, number, storeTermVector, storePositionWithTermVector,
- storeOffsetWithTermVector, omitNorms, storePayloads);
+ storeOffsetWithTermVector, omitNorms, storePayloads, omitTf);
}
void update(boolean isIndexed, boolean storeTermVector, boolean storePositionWithTermVector,
- boolean storeOffsetWithTermVector, boolean omitNorms, boolean storePayloads) {
+ boolean storeOffsetWithTermVector, boolean omitNorms, boolean storePayloads, boolean omitTf) {
if (this.isIndexed != isIndexed) {
this.isIndexed = true; // once indexed, always index
}
@@ -66,6 +68,9 @@
if (this.omitNorms != omitNorms) {
this.omitNorms = false; // once norms are stored, always store
}
+ if (this.omitTf != omitTf) {
+ this.omitTf = true; // if one require omitTf at least once, it remains off for life
+ }
if (this.storePayloads != storePayloads) {
this.storePayloads = true;
}
@@ -87,6 +92,9 @@
if (omitNorms != other.omitNorms) {
omitNorms = false; // once norms are stored, always store
}
+ if (this.omitTf != omitTf) {
+ this.omitTf = true; // if one require omitTf at least once, it remains off for life
+ }
if (storePayloads != other.storePayloads) {
storePayloads = true;
}
Index: src/java/org/apache/lucene/index/DocFieldProcessorPerThread.java
===================================================================
--- src/java/org/apache/lucene/index/DocFieldProcessorPerThread.java (revision 678362)
+++ src/java/org/apache/lucene/index/DocFieldProcessorPerThread.java (working copy)
@@ -183,7 +183,7 @@
// easily add it
FieldInfo fi = fieldInfos.add(fieldName, field.isIndexed(), field.isTermVectorStored(),
field.isStorePositionWithTermVector(), field.isStoreOffsetWithTermVector(),
- field.getOmitNorms(), false);
+ field.getOmitNorms(), false, field.getOmitTf());
fp = new DocFieldProcessorPerField(this, fi);
fp.next = fieldHash[hashPos];
@@ -195,7 +195,7 @@
} else
fp.fieldInfo.update(field.isIndexed(), field.isTermVectorStored(),
field.isStorePositionWithTermVector(), field.isStoreOffsetWithTermVector(),
- field.getOmitNorms(), false);
+ field.getOmitNorms(), false, field.getOmitTf());
if (thisFieldGen != fp.lastGen) {
Index: src/java/org/apache/lucene/index/TermsHashConsumer.java
===================================================================
--- src/java/org/apache/lucene/index/TermsHashConsumer.java (revision 678362)
+++ src/java/org/apache/lucene/index/TermsHashConsumer.java (working copy)
@@ -28,8 +28,6 @@
abstract void abort();
abstract void closeDocStore(DocumentsWriter.FlushState state) throws IOException;
- int streamCount;
-
FieldInfos fieldInfos;
void setFieldInfos(FieldInfos fieldInfos) {
Index: src/java/org/apache/lucene/index/TermVectorsTermsWriter.java
===================================================================
--- src/java/org/apache/lucene/index/TermVectorsTermsWriter.java (revision 678362)
+++ src/java/org/apache/lucene/index/TermVectorsTermsWriter.java (working copy)
@@ -39,7 +39,6 @@
public TermVectorsTermsWriter(DocumentsWriter docWriter) {
this.docWriter = docWriter;
- streamCount = 2;
}
public TermsHashConsumerPerThread addThread(TermsHashPerThread termsHashPerThread) {
Index: src/java/org/apache/lucene/index/TermsHashConsumerPerField.java
===================================================================
--- src/java/org/apache/lucene/index/TermsHashConsumerPerField.java (revision 678362)
+++ src/java/org/apache/lucene/index/TermsHashConsumerPerField.java (working copy)
@@ -32,4 +32,5 @@
abstract void skippingLongTerm(Token t) throws IOException;
abstract void newTerm(Token t, RawPostingList p) throws IOException;
abstract void addTerm(Token t, RawPostingList p) throws IOException;
+ abstract int getStreamCount();
}
Index: src/java/org/apache/lucene/index/IndexReader.java
===================================================================
--- src/java/org/apache/lucene/index/IndexReader.java (revision 678362)
+++ src/java/org/apache/lucene/index/IndexReader.java (working copy)
@@ -75,6 +75,8 @@
public static final FieldOption INDEXED = new FieldOption ("INDEXED");
/** All fields that store payloads */
public static final FieldOption STORES_PAYLOADS = new FieldOption ("STORES_PAYLOADS");
+ /** All fields that omit tf */
+ public static final FieldOption OMIT_TF = new FieldOption ("OMIT_TF");
/** All fields which are not indexed */
public static final FieldOption UNINDEXED = new FieldOption ("UNINDEXED");
/** All fields which are indexed with termvectors enabled */
Index: src/java/org/apache/lucene/index/DocumentsWriter.java
===================================================================
--- src/java/org/apache/lucene/index/DocumentsWriter.java (revision 678362)
+++ src/java/org/apache/lucene/index/DocumentsWriter.java (working copy)
@@ -132,6 +132,8 @@
boolean bufferIsFull; // True when it's time to write segment
private boolean aborting; // True if an abort is pending
+ private DocFieldProcessor docFieldProcessor;
+
PrintStream infoStream;
int maxFieldLength = IndexWriter.DEFAULT_MAX_FIELD_LENGTH;
Similarity similarity;
@@ -261,9 +263,15 @@
final DocInverter docInverter = new DocInverter(termsHash, normsWriter);
final StoredFieldsWriter fieldsWriter = new StoredFieldsWriter(this);
final DocFieldConsumers docFieldConsumers = new DocFieldConsumers(docInverter, fieldsWriter);
- consumer = new DocFieldProcessor(this, docFieldConsumers);
+ consumer = docFieldProcessor = new DocFieldProcessor(this, docFieldConsumers);
}
+ /** Returns true if any of the fields in the current
+ * buffered docs have omitTf==false */
+ boolean hasProx() {
+ return docFieldProcessor.fieldInfos.hasProx();
+ }
+
/** If non-null, various details of indexing are printed
* here. */
synchronized void setInfoStream(PrintStream infoStream) {
Index: src/java/org/apache/lucene/index/TermVectorsTermsWriterPerField.java
===================================================================
--- src/java/org/apache/lucene/index/TermVectorsTermsWriterPerField.java (revision 678362)
+++ src/java/org/apache/lucene/index/TermVectorsTermsWriterPerField.java (working copy)
@@ -47,6 +47,10 @@
fieldState = termsHashPerField.fieldState;
}
+ int getStreamCount() {
+ return 2;
+ }
+
boolean start(Fieldable[] fields, int count) {
doVectors = false;
doVectorPositions = false;
Index: src/java/org/apache/lucene/index/SegmentInfos.java
===================================================================
--- src/java/org/apache/lucene/index/SegmentInfos.java (revision 678362)
+++ src/java/org/apache/lucene/index/SegmentInfos.java (working copy)
@@ -65,8 +65,13 @@
* This way IndexWriter can efficiently report numDocs(). */
public static final int FORMAT_DEL_COUNT = -6;
+ /** This format adds the boolean hasProx to record if any
+ * fields in the segment store prox information (ie, have
+ * omitTf==false) */
+ public static final int FORMAT_HAS_PROX = -7;
+
/* This must always point to the most recent file format. */
- static final int CURRENT_FORMAT = FORMAT_DEL_COUNT;
+ static final int CURRENT_FORMAT = FORMAT_HAS_PROX;
public int counter = 0; // used to name new segments
/**
Index: src/java/org/apache/lucene/index/SegmentTermDocs.java
===================================================================
--- src/java/org/apache/lucene/index/SegmentTermDocs.java (revision 678362)
+++ src/java/org/apache/lucene/index/SegmentTermDocs.java (working copy)
@@ -41,7 +41,8 @@
private boolean haveSkipped;
protected boolean currentFieldStoresPayloads;
-
+ protected boolean currentFieldOmitTf;
+
protected SegmentTermDocs(SegmentReader parent) {
this.parent = parent;
this.freqStream = (IndexInput) parent.freqStream.clone();
@@ -75,6 +76,7 @@
void seek(TermInfo ti, Term term) throws IOException {
count = 0;
FieldInfo fi = parent.fieldInfos.fieldInfo(term.field);
+ currentFieldOmitTf = (fi != null) ? fi.omitTf : false;
currentFieldStoresPayloads = (fi != null) ? fi.storePayloads : false;
if (ti == null) {
df = 0;
@@ -105,14 +107,19 @@
while (true) {
if (count == df)
return false;
-
- int docCode = freqStream.readVInt();
- doc += docCode >>> 1; // shift off low bit
- if ((docCode & 1) != 0) // if low bit is set
- freq = 1; // freq is one
- else
- freq = freqStream.readVInt(); // else read freq
-
+ final int docCode = freqStream.readVInt();
+
+ if (currentFieldOmitTf) {
+ doc += docCode;
+ freq = 1;
+ } else {
+ doc += docCode >>> 1; // shift off low bit
+ if ((docCode & 1) != 0) // if low bit is set
+ freq = 1; // freq is one
+ else
+ freq = freqStream.readVInt(); // else read freq
+ }
+
count++;
if (deletedDocs == null || !deletedDocs.get(doc))
@@ -126,27 +133,49 @@
public int read(final int[] docs, final int[] freqs)
throws IOException {
final int length = docs.length;
+ if (currentFieldOmitTf) {
+ return readNoTf(docs, freqs, length);
+ } else {
+ int i = 0;
+ while (i < length && count < df) {
+ // manually inlined call to next() for speed
+ final int docCode = freqStream.readVInt();
+ doc += docCode >>> 1; // shift off low bit
+ if ((docCode & 1) != 0) // if low bit is set
+ freq = 1; // freq is one
+ else
+ freq = freqStream.readVInt(); // else read freq
+ count++;
+
+ if (deletedDocs == null || !deletedDocs.get(doc)) {
+ docs[i] = doc;
+ freqs[i] = freq;
+ ++i;
+ }
+ }
+ return i;
+ }
+ }
+
+ private final int readNoTf(final int[] docs, final int[] freqs, final int length) throws IOException {
int i = 0;
while (i < length && count < df) {
-
// manually inlined call to next() for speed
- final int docCode = freqStream.readVInt();
- doc += docCode >>> 1; // shift off low bit
- if ((docCode & 1) != 0) // if low bit is set
- freq = 1; // freq is one
- else
- freq = freqStream.readVInt(); // else read freq
+ doc += freqStream.readVInt();
count++;
if (deletedDocs == null || !deletedDocs.get(doc)) {
docs[i] = doc;
- freqs[i] = freq;
+ // Hardware freq to 1 when term freqs were not
+ // stored in the index
+ freqs[i] = 1;
++i;
}
}
return i;
}
-
+
+
/** Overridden by SegmentTermPositions to skip in prox stream. */
protected void skipProx(long proxPointer, int payloadLength) throws IOException {}
Index: src/java/org/apache/lucene/index/IndexWriter.java
===================================================================
--- src/java/org/apache/lucene/index/IndexWriter.java (revision 678362)
+++ src/java/org/apache/lucene/index/IndexWriter.java (working copy)
@@ -3054,7 +3054,7 @@
synchronized(this) {
segmentInfos.setSize(0); // pop old infos & add new
info = new SegmentInfo(mergedName, docCount, directory, false, true,
- -1, null, false);
+ -1, null, false, merger.hasProx());
segmentInfos.addElement(info);
}
@@ -3362,7 +3362,8 @@
flushedDocCount,
directory, false, true,
docStoreOffset, docStoreSegment,
- docStoreIsCompoundFile);
+ docStoreIsCompoundFile,
+ docWriter.hasProx());
}
docWriter.pushDeletes();
@@ -3600,6 +3601,8 @@
}
}
+ merge.info.setHasProx(merger.hasProx());
+
segmentInfos.subList(start, start + merge.segments.size()).clear();
segmentInfos.add(start, merge.info);
@@ -3890,7 +3893,8 @@
directory, false, true,
docStoreOffset,
docStoreSegment,
- docStoreIsCompoundFile);
+ docStoreIsCompoundFile,
+ false);
// Also enroll the merged segment into mergingSegments;
// this prevents it from getting selected for a merge
Index: src/java/org/apache/lucene/index/DefaultSkipListWriter.java
===================================================================
--- src/java/org/apache/lucene/index/DefaultSkipListWriter.java (revision 678362)
+++ src/java/org/apache/lucene/index/DefaultSkipListWriter.java (working copy)
@@ -62,7 +62,8 @@
this.curStorePayloads = storePayloads;
this.curPayloadLength = payloadLength;
this.curFreqPointer = freqOutput.getFilePointer();
- this.curProxPointer = proxOutput.getFilePointer();
+ if (proxOutput != null)
+ this.curProxPointer = proxOutput.getFilePointer();
}
protected void resetSkip() {
@@ -70,7 +71,8 @@
Arrays.fill(lastSkipDoc, 0);
Arrays.fill(lastSkipPayloadLength, -1); // we don't have to write the first length in the skip list
Arrays.fill(lastSkipFreqPointer, freqOutput.getFilePointer());
- Arrays.fill(lastSkipProxPointer, proxOutput.getFilePointer());
+ if (proxOutput != null)
+ Arrays.fill(lastSkipProxPointer, proxOutput.getFilePointer());
}
protected void writeSkipData(int level, IndexOutput skipBuffer) throws IOException {
Index: src/java/org/apache/lucene/index/CheckIndex.java
===================================================================
--- src/java/org/apache/lucene/index/CheckIndex.java (revision 678362)
+++ src/java/org/apache/lucene/index/CheckIndex.java (working copy)
@@ -114,13 +114,12 @@
else if (format == SegmentInfos.FORMAT_SHARED_DOC_STORE)
sFormat = "FORMAT_SHARED_DOC_STORE [Lucene 2.3]";
else {
- // LUCENE-1255: All versions before 2.3.2/2.4 were
- // able to create position=-1 when the very first
- // Token has positionIncrement 0
if (format == SegmentInfos.FORMAT_CHECKSUM)
sFormat = "FORMAT_CHECKSUM [Lucene 2.4]";
else if (format == SegmentInfos.FORMAT_DEL_COUNT)
- sFormat = "FORMAT_DEL_COUNT [Lucene 2.4]";
+ sFormat = "FORMAT_DEL_COUNT [Lucene 2.4]";
+ else if (format == SegmentInfos.FORMAT_HAS_PROX)
+ sFormat = "FORMAT_HAS_PROX [Lucene 2.4]";
else if (format < SegmentInfos.CURRENT_FORMAT) {
sFormat = "int=" + format + " [newer version of Lucene than this tool]";
skip = true;
@@ -161,6 +160,7 @@
try {
out.println(" compound=" + info.getUseCompoundFile());
+ out.println(" hasProx=" + info.getHasProx());
out.println(" numFiles=" + info.files().size());
out.println(" size (MB)=" + nf.format(info.sizeInBytes()/(1024.*1024.)));
final int docStoreOffset = info.getDocStoreOffset();
@@ -224,7 +224,7 @@
final int doc = termPositions.doc();
final int freq = termPositions.freq();
if (doc <= lastDoc)
- throw new RuntimeException("term " + term + ": doc " + doc + " < lastDoc " + lastDoc);
+ throw new RuntimeException("term " + term + ": doc " + doc + " <= lastDoc " + lastDoc);
lastDoc = doc;
if (freq <= 0)
throw new RuntimeException("term " + term + ": doc " + doc + ": freq " + freq + " is out of bounds");
Index: src/java/org/apache/lucene/document/AbstractField.java
===================================================================
--- src/java/org/apache/lucene/document/AbstractField.java (revision 678362)
+++ src/java/org/apache/lucene/document/AbstractField.java (working copy)
@@ -33,6 +33,7 @@
protected boolean isBinary = false;
protected boolean isCompressed = false;
protected boolean lazy = false;
+ protected boolean omitTf = false;
protected float boost = 1.0f;
// the one and only data object for all different kind of field values
protected Object fieldsData = null;
@@ -203,6 +204,9 @@
/** True if norms are omitted for this indexed field */
public boolean getOmitNorms() { return omitNorms; }
+ /** True if tf is omitted for this indexed field */
+ public boolean getOmitTf() { return omitTf; }
+
/** Expert:
*
* If set, omit normalization factors associated with this indexed field.
@@ -210,6 +214,12 @@
*/
public void setOmitNorms(boolean omitNorms) { this.omitNorms=omitNorms; }
+ /** Expert:
+ *
+ * If set, omit tf from postings of this indexed field.
+ */
+ public void setOmitTf(boolean omitTf) { this.omitTf=omitTf; }
+
public boolean isLazy() {
return lazy;
}
@@ -257,6 +267,9 @@
if (omitNorms) {
result.append(",omitNorms");
}
+ if (omitTf) {
+ result.append(",omitTf");
+ }
if (lazy){
result.append(",lazy");
}
Index: src/java/org/apache/lucene/document/Fieldable.java
===================================================================
--- src/java/org/apache/lucene/document/Fieldable.java (revision 678362)
+++ src/java/org/apache/lucene/document/Fieldable.java (working copy)
@@ -133,6 +133,15 @@
*/
void setOmitNorms(boolean omitNorms);
+ /** Expert:
+ *
+ * If set, omit term freq, positions and payloads from postings for this field.
+ */
+ void setOmitTf(boolean omitTf);
+
+ /** True if tf is omitted for this indexed field */
+ boolean getOmitTf();
+
/**
* Indicates whether a Field is Lazy or not. The semantics of Lazy loading are such that if a Field is lazily loaded, retrieving
* it's values via {@link #stringValue()} or {@link #binaryValue()} is only valid as long as the {@link org.apache.lucene.index.IndexReader} that
Index: src/site/src/documentation/content/xdocs/fileformats.xml
===================================================================
--- src/site/src/documentation/content/xdocs/fileformats.xml (revision 678362)
+++ src/site/src/documentation/content/xdocs/fileformats.xml (working copy)
@@ -246,14 +246,16 @@
Term Frequency
data. For each term in the dictionary, the numbers of all the
documents that contain that term, and the frequency of the term in
- that document.
+ that document if omitTf is false.
Term Proximity
data. For each term in the dictionary, the positions that the term
- occurs in each document.
+ occurs in each document. Note that this will
+ not exist if all fields in all documents set
+ omitTf to true.
@@ -826,11 +828,12 @@
2.4 and above:
Segments --> Format, Version, NameCounter, SegCount, <SegName, SegSize, DelGen, DocStoreOffset, [DocStoreSegment, DocStoreIsCompoundFile], HasSingleNormFile, NumField,
NormGenNumField,
- IsCompoundFile>SegCount, Checksum
+ IsCompoundFile, DeletionCount, HasProx>SegCount, Checksum
- Format, NameCounter, SegCount, SegSize, NumField, DocStoreOffset --> Int32
+ Format, NameCounter, SegCount, SegSize, NumField,
+ DocStoreOffset, DeletionCount --> Int32
@@ -842,7 +845,8 @@
- IsCompoundFile, HasSingleNormFile, DocStoreIsCompoundFile --> Int8
+ IsCompoundFile, HasSingleNormFile,
+ DocStoreIsCompoundFile, HasProx --> Int8
@@ -936,8 +940,17 @@
This is used to verify integrity of the file on
opening the index.
-
+
+ DeletionCount records the number of deleted
+ documents in this segment.
+
+
+
+ HasProx is 1 if any fields in this segment have
+ omitTf set to false; else, it's 0.
+
+
Lock File
@@ -1264,7 +1277,9 @@
determines the position of this term's TermPositions within the .prx
file. In particular, it is the difference between the position of
this term's data in that file and the position of the previous
- term's data (or zero, for the first term in the file.
+ term's data (or zero, for the first term in the file. For fields
+ with omitTf true, this will be 0 since
+ prox information is not stored.
SkipDelta determines the position of this
term's SkipData within the .frq file. In
@@ -1338,7 +1353,7 @@
The .frq file contains the lists of documents
which contain each term, along with the frequency of the term in that
- document.
+ document (if omitTf is false).
FreqFile (.frq) -->
<TermFreqs, SkipData>
@@ -1349,7 +1364,7 @@
DocFreq
TermFreq -->
- DocDelta, Freq?
+ DocDelta[, Freq?]
SkipData -->
<<SkipLevelLength, SkipLevel>
@@ -1375,21 +1390,31 @@
TermFreq
entries are ordered by increasing document number.
- DocDelta
- determines both the document number and the frequency. In
- particular, DocDelta/2 is the difference between this document number
- and the previous document number (or zero when this is the first
- document in a TermFreqs). When DocDelta is odd, the frequency is
- one. When DocDelta is even, the frequency is read as another VInt.
+
DocDelta: if omitTf is false, this determines both
+ the document number and the frequency. In
+ particular, DocDelta/2 is the difference between
+ this document number and the previous document
+ number (or zero when this is the first document in
+ a TermFreqs). When DocDelta is odd, the frequency
+ is one. When DocDelta is even, the frequency is
+ read as another VInt. If omitTf is true, DocDelta
+ contains the gap (not multiplied by 2) between
+ document numbers and no frequency information is
+ stored.
- For
- example, the TermFreqs for a term which occurs once in document seven
- and three times in document eleven would be the following sequence of
- VInts:
+
For example, the TermFreqs for a term which occurs
+ once in document seven and three times in document
+ eleven, with omitTf false, would be the following
+ sequence of VInts:
- 15,
- 8, 3
+
15, 8, 3
+ If omitTf were true it would be this sequence
+ of VInts instead:
+
+
+ 7,4
+
DocSkip records the document number before every
SkipInterval
th
@@ -1454,7 +1479,11 @@
The .prx file contains the lists of positions that
- each term occurs at within documents.
+ each term occurs at within documents. Note that
+ fields with omitTf true do not store
+ anything into this file, and if all fields in the
+ index have omitTf true then the .prx file will not
+ exist.
ProxFile (.prx) -->
<TermPositions>
Index: docs/fileformats.pdf
===================================================================
--- docs/fileformats.pdf (revision 678362)
+++ docs/fileformats.pdf (working copy)
@@ -5,10 +5,10 @@
/Producer (FOP 0.20.5) >>
endobj
5 0 obj
-<< /Length 1115 /Filter [ /ASCII85Decode /FlateDecode ]
+<< /Length 1117 /Filter [ /ASCII85Decode /FlateDecode ]
>>
stream
-Gb!$G9lo#B&;KZO$6@53W]k9ICdOP`P=a5[dnAEt!C8gORi4Y_IpYbOI4uP7>VL*sJQDKN]6[Q8S%SK06ig^-JUHXo\)4)`fne(e3=[b6f>EEC"UTpJnTI4b:+&Q\[CnNTGc/7;_)qPA_)lrGchW__JWg47o`BO[p&Um!+.u0W#O_5XQks>]'NNfml7k4h>AP)7<_:=9$tb55Sr>k,OS]7BE[U-Ab\Y@C53O7U[j+kjGtTb7cGJWt4]4q%1?L1!CQQ<5`TI,I2_)adekIJ>*t/^>pAl3uDLFdf5&^rP`F@@)9W(IcTW(NY#\]*sIM'Z\]8oJGjSbj1prR?4Z*aJdu7J43Z2RImnNO,g&5I3M5VH2':-I_Sk%/*h!,Ube%='Nl=)%igfBIK6kB('./d.ond,XEb"Gj0GB>!mi6:P'nJ.nk=omFh!NY##@\@,j[:b1"cq>'#cGHH=j_*[ELH%0iiFuF6Ypa8)d6R)6hg!:TBoHp'bhG-KhP`1"^1W>96'NidM=<:"39-:ZdRbNHV-aWUlu;WS;@ccG>Q&E%qrkRV5YNNK?0HTYmqU0t*irpd"?qn,:d"C#-YFE^n1Pdh+p.E)6ormsXZ\W*VA:%RP,"e:+j.Cs4o`&ee8aUZ1jYiR+jsG2oQ:j
+Gb!$G9lo#B&;KZO$6@53W]k9ICdOP`P=a5[dnAEt!C8gORi4Z:^TSn%I4u(M/f6Qu5V)`b?+hcW?/#04U4=qR5W\?WoeGhWYioMGj;W_>r>%*jBf#hS$N07??;IG:iWe2$GTd%P5A[5AGK.,clStMnIs*foQHm-?;6D7rjp(_fkuW9P8UVE3V0PI;7%6iam]H;hfIlOSITofT^+bJa!4,V)0b+f8okNaP[D!`crot;@qgDZ/Q,oMcirC.FFE03DgO%D/GNrrb][MfLhU*Qmad9XH*(>sh([0>P%hOHi!(FagE2O5c4Nk&\/+QG3O1@heA$Z`U8iek<0JVAPD"J$fgc$)54&K$fAj``m5pu3!*MF\&CN:;4(+,C4&R4h40sA])K64jDS(%7PP_nM'RnQXB(a.Jf#AaCNo`5O!^bp?PMcD>_SL2%%VC(D/5Z;4dMa/&4Fq'2FFK;?W]H=V`=&E;V$hEk.bF?b:[F__"Q'.[+r79T3j?H.7ZaVCIAlmVZp\E0+m>O$/No*es2]Sb?a:h.oZ>h"X8me"Ggq4?1Qh&P;RgklK_F/[Kh3%/q+F
endstream
endobj
6 0 obj
@@ -270,7 +270,7 @@
<< /Length 627 /Filter [ /ASCII85Decode /FlateDecode ]
>>
stream
-Gaua<9lJN8&;KZL'm%S?C2Cpt3DrHp:kad_\,_:4lePae8"7a)jjt/-95GED\Y[Sc7X=BH`oEKQ13lf;+;eN8%gdu#63'e'R=&ai$;Q\u%*B@"V%V/rr.+@u/>BIa&^UsV=A\:Vh8'ifG5q3Se>)9?C3\H`F.gdD%0G]@ZO9YD@Gkc81O#-.k..g@mSH^gqXLZ!g?@#JVua3B$Sbj5-6,lYbgqV<_-MOGp2XN$pVKT[k+LB1bu^Ta/eRg(Hke[TI-QKqC-((aKp7?.ld2=JIa_ZsVQBf];mDG-F`N&NDC3uW6c"b"oVhLM6gO&ZX1N@MHro?KJ^.VU[SWJkhjMteaA*iUIVW+CApDnb/ZVn$Pl\PUMlM6@+!]FVhZm,3qV*f=rP+@@C:pfEP`ehZ`Vc9HN!qc#'<`SdLDYF/=I#jY1@-,bL994*/O8Yk\uNVD?41;XtIn?$2+PUB1'DZ]UuFnSiMiNcMs%Ypf]ahWeDHn2-NmrTNs]D^#'S3Umm(=EpmZ,g.&knsoZT5E*@W+n-3E\_F_O6%Q+O]]%.""h$VZiMYNWT=_jb$G^i~>
+Gaua<9lJN8&;KZL'm%S?C2Cpt3DrHp:kad_\,_:4lePae8"7a)jjt/-95GED\Y[Sc7X=BH`oEKQ13lf;+;eN8%gdu#63'e'R=&ai$;Q\u%*B@"V%V/rr.+@u/>BIa&^UsV=A\:Vh8'ifG5q3Se>)9?C3\H`F.gdD%0G]@ZO9YD@Gkc81O#-.k..g@mSH^gqXLZ!g?@#JVua3B$Sbj5-6,lYbgqV<_-MOGp2XN$pVKT[k+LB1/QSQj/eRg(Hke[TI-QKqC-:4cKp7?.ld2=JIa_ZsVQBf];mDFbF`N&NDC3uW6c"b"oVhLM6gO&ZX1N@MHro?KJ^.VU[SWJkhjMteaA*iUIVW+CApDnb/ZVn$Pl\PUMlM6@+!]FVhZm,3qV*f=rP+@@C:pfEP`ehZ`Vc9HN!qc#'<`SdLDYF/=I#jY1@-,bL994*/O8Yk\uNVD?41;XtIn?$2+PUB1'DZ]UuFnSiMiNcMs%Ypf]ahWeDHn2-NmrTNs]D^#'S3Umm(=EpmZ,g.&knsoZT5E*@W+n-3E\_F_O6%Q+O]]%.""h$VZiMYNWT=_jp0Yhu~>
endstream
endobj
53 0 obj
@@ -394,10 +394,10 @@
>>
endobj
73 0 obj
-<< /Length 2188 /Filter [ /ASCII85Decode /FlateDecode ]
+<< /Length 2230 /Filter [ /ASCII85Decode /FlateDecode ]
>>
stream
-GauHMgQ(#H&:O:SkcGe3=4(;ohi]<*ZmaY81"qD[&%"aZ6mU/'.=7Vh06ONZPY'O4MI<^$UnPjK$gCiH:nXq;XQNQaK3@`(dnc=]Na3_$nNWagm49aPO%iFCie`(gXiEE/r83J_-Do"]M;9oJH2OH_/(Mgs/!W(C4=mYWPF4O'n`f-r7NA`*1VF8knJ">+C;r=@sNR#6K^:A"6MQ5j0ed'FCSej5%FBEkL<-uMrAK6!sVuUTWhueE?R+8.*JGM5+cK&O"\\Z5++1NAMH[HuE/1M!3gl0m.GG%t3(CM^)0E'Dn-=/n+4jM0(jB"UQ"p;G/$MfgS$ms[(FBdVq$#&[N'aW'=qU+ZB(V8;0L[/F+5C;m4QKHFq0U)qsgs;3N:JeGPU";dG[1,.?B%^Q22u4=`OrHE],24+T\-CFEZs&Y3(EgM`h@t\R@JnOlojW\af&)9*UoSF$;..s[OQ=D1oLV`N_Mb=Z3DT#P@BIPgio.Rl_&-8=LJ=UlC?bbU7HQ7"G"KY35mi!OGh5K%'sQJW%nGJ@3[]2Hs#R/'PH5dI2C/mJrL!r>lG.G4@7H'`pQtb[?sK2,#6k2_`Q4hj(+;^<^'7h)/ShD6qjDQ2iVW"PO)Jgj.KX2UBX6R27pOs2arhs09&W*/AAOqhKZME-d?WGK?:#?L7MsUhRKknKYr;M3b.-Re0F2!2eXbEBXq]KI1H&1WF5F^*5VCPg:(U8h.G_3@Zs],l.Mu_R1OG/Q*-8I;.ZcothU9fb@B]2ELJ>:'r^^'q,]-sRC>'9^35_J!22pTiMXLh8;OSZc(pSHI'aC-)#L?cHa`\:oinE=0QmncqldSr6#h(m2,>8i%X=s`SZQOO_YqhNf"^?D(_''F.&=Tm]LK_lpq'gBhOhA`_N]Es/&%#+f5!`r"KJ3^;;pB(UdV7)06UM<'!6b6$YYQ1]/_ABao59+qOD`ZB/O:9k-HR9\Rd<>oRm"VuX"W'E#F>XAVATAmc"]B6-WUHT>&&2`ilmX[L/+AI?ARF(NNkF_Ih=d-Z$c$Za:]Y/b7bb!F::,T060K*i*8?KlPN-D9KOE'/c?p]1bMYPsC'U8#aF6,R!shehmQ9P8QNG*"(9bP(#ARWllLh8"62N;oMOBRUZ-M7V*Gr=VhJF#,K5iJAZtBefGn($mrRI+_qY?ZYj.!@il:#nS^bt>Gm/Va)\nO97i3aFT!SEnCn;T=ZV>KLbnjg(;(Q3j^^=T,-Yn,82L0ljZZ+H5u.Z:+sIQu@YFFRc_Dfa@.A(Mjs<@dRO7(%a_:u;8oFmVtH,E>.:ol$F9;\tu1E5AbbkOsmQD%>8TJ_
+GauHMbDt=8']%):B\*PEUZcF6h'Gc8ZmaA01"o(F"YJ+[&P7(8ar]a390Fh48u-9AK#,Ze1*?71GjZaRG5^oZrUB3jGBWQO_o'oD4_M$%aM1U-4?r^?dpUh]4T,$Ep?q@P=0^cjo$r'`i3f=Bq;XQNQSq4kKtHguB3dRu5,+dE)%u_0o,P-$4^sZC9++SEfP[0$Nq<]qO%;.KU$?>L1n3Ts\HB"TmAIUmtGX?m,9FdpWoH/RAG2B&I`5;9D=]nrlV7BO0[Q0JK\SD/gC6ga(G;4ak$7LOs[=\h.uC]QB@EGPXrD`5@+M18#0,!g);(HX'9"#SYB(7WF!5L8>nOfK*XRbHbia5G2XZVki$4g>$0D,Ah%?PW%*u0V?TLL]Hlu>gak(!hr`%JlFaZJW%n7LpbNeeiQ_(9?_RjdI4[Ag_!@P%gP)PeE4[0*aW>@V?s2ar(s09%,*Ja#%qhKZLE&rgl[un3l]\)np8CMg?j%"hU'.jmNFjYmu"C_-o(?ZpY-YT6O.AJ_Be&C=PA/IaQA5SWgMFm/(8[mXTH1a-`@>RN$jKB$">:Sb!8]LGdCIAcRM%&;_4;#Q3)tZV'#_iahTb;E`Zbj:%flGAKNe+g(n@"'?<-(gXNd("ner1eU4mr_IjL\_?N6d)2BZhe`S[-!KSL9dmW#7F>>R1J`8bH0sDM]YPJrrbZnFNTq*0;`;B#t_j&g=rLP(sm_KQrm=`]p=ghFR$[QD)=[:"7"XqLoUdYqo(e$tP1tJS-@;Tsa]l'1m4Ho^6Jn).Lm,Qk[Vq)TrF2$7M`dn5'22IMg2A^3&q1M+G?pJIa_OP?MgJWNe2j*BBe$X"mjgbVT.Eo&k(QGG4>%pf22Q3,)KF1I%;7"fLnY%"m@aK+m4_[`/E\p\4d]YZp%GM3Q5\9'/DK>rOR0K6jV8iC5j!m.FVIoISPXN:r,)PAAl=GP9mR"T,&/e?[R[Vlu0_DS*L0XKceN(%gaAR,Us\cO>/!!_i_4bErEoM'rs]A[V3Jr%MrU$#iVdm55bTXXqpjja-KLi(gE\646lmNIOdMAp4'V[6_484E=V76+#Zh-F\t'O9aW_TReOdGI)dEV;@FB0I+4>"d;?Xt(mh&8j%p4t1hPJnREi0o?eOZ;/0*D>];*i''+)cGrAsO0p64Td,h*74OHBDn&LJ&SPTJP9V6P-9CNYe38qVnR?Gt-n[H[[7S?L5k3#J%E*L8aaYV:[CPt&X0H8-O"lVS^f/_cK@)r?0'182fF427g@e`rI*4nkcZ=tStpUdDRTnbG9I$^(n/Qi7^Y?HM?/QAc8Iru23\[MI)DT/SN@J=A&lRHggWXFQ(C8#FMCNIjgG[O#F3#T7+!>.JtOT~>
endstream
endobj
74 0 obj
@@ -409,10 +409,10 @@
>>
endobj
75 0 obj
-<< /Length 1983 /Filter [ /ASCII85Decode /FlateDecode ]
+<< /Length 1980 /Filter [ /ASCII85Decode /FlateDecode ]
>>
stream
-Gau0DgQ(#H&:O:S#^OPo2BuOM",[)J1`N7S6diR56anIWRC7glU-cuf\6n-eCb:EGBtI(u#i[^UOdpK)k0-Y?QEteYg#j4^[da=q/.5#d`,Q3X,-p)B1sQ@7N!`Ul:U<"'frLSjTF?9PDJ!=d.YN:.33S8XM*hk+pVH;OYKQJd=Kl\4Q^a^KN>o$"WN0l5D;A0lh08+t2JTj*#dG6Xr?:HQ[!TG`)Z:sYl%p[S7b7^aE)3WC2.%Va5M;5YD^Xp)%WGf$]VOHb8-5L<_[IhQ!4'4*g,R!m8W1:LW3sF+9,C1COO!ahK5ZV5\)TX4iF[(DUC%<[?64W9bk_N8d+];5&G)"CmDQEo'C/AAEZR:I`lk:b.>Dg'\-/.!=>,pP&HdOloe:?CQ:+.J5iWM?BPssA.>S!/i)'s"3CjE%=>aFJcNm,MRF%LppS6B(Sq6g&S5ulBKj7DmgQI^ae3@sj*CNoWZh-lWbfKAf>dd8Fb8a;PWW6Y].AkbaeN"VI[f4\g162@U@9hdR_#fYXOFoKto_Pk;EZelQN3+tJj"BIdb!j>L@U`15[3-\;FCSM_"^msW2e!41g/Jp\o75'"V^4e[tfBo3=8Ifg>]'P[HYNubT%420gb\5RiANc;h69=BBR315Y+RI:LE!?C=$QS&(QZNP_S7^hJ0EW:Dl)\'ERdr2-NXa5!1[.^UjTUBn<@3qrN*&ncGH;I>q>63>Z?Kl1.@4eF!Yg[i@urL[^>^"e29`>8[C87Jc.)I[==r*97t#rKBXJ-H68[3.?Ot#hR?DqTj2j@<"`"n\phdH7jOU84?erB+l5GP!edVi>nE53eR4TSISRfnJY'#'JTG4iih#R@:duEH@Ne0fLm*nY'V%EGk]'LRoZa@8e#57!UAQ't+C_'>ooEUA0Uc6=0+QsS`q`RuA@Vl0-__R!S1:tZG-SnN[fRO/q&acb]Qqf7?.[3tZ'Mlm^;i:8)\]>NmB(Z5!/KUA@*/iqe?YaM0RHSdfk8Kf3_*_"L%$Jrcp[c7J*,gk/kA4[$N)OqGj25/%p*cS$B?QF"[=k6WI,5,/7->(C\XQ]h+fWgrmIG^paW[MlNr<`Gt65+83_]ul9aN'L[+a//Ep40W_HfnYiY?BCn'6rgGq2TC-M""c(L,GIBc^rq/Y/::o6:U*J&-Qpm3W=8_)d2N9=hnete]UabB)<,fCI[eL6YY_"I)GefXk6NRsPX`WD/o>R;,:`I>me70q-n')1TUi8ME:`>4j$Qa+4FQ3m2j;1"/37!sJe.K#]@:\D>=`>W3%P]qf^aHK',mL%I:G)j@5@j2oZ*";,8kGKc%2WK])Y_1g[q1a.0G95K#:q"?<%JQDE&,mm?cjYBB)/o0(NW)sJO)n'!15[+k@+M+1bLjmZ9rBP5YWSNKPTt*oNKrm.qfZCVp"kte2JIiB(d<;YPQPc%8?cMH%/qQA!6g2m/'o>U=,c`8!#Uem,6,)HkWkVNVZ:e&S[)L,OT.X-uaP]7J>cdoQ\,LY-Jka.h&jt>[M29O5DAkqhMk^9TG*H8^f3;OQ9OB-1e1u>[`kJ890%^:Y423+)&%](d1kr'9\T;]>J@g:2#*k_u~>
+Gau0DgQ(#H&:O:S#^OPo2Bu+DTEpXTh&o,uUoiB8FGka:Bj%BPU$-XSYOBi$XJ&\M3lqR6GYOSMkF@r#1Z[lpieR3dj2**^'"aa1s8/&Gs+-ZXN[$@#ro5YMSOMNNf*MO$55d`r?dXC#cZc1(2N+1DYLe[K[uj&NK_96A3nXR8J3W=@YPK;6&"Rk-r;#+q2pR;OQ[+%L(LeAtk@It22pPdUqT$llH=#iQDh.#73".GeKF)(A"bB$DB7[TTUVr5)c!M4)\DId>Do^g+'Qo\3/JoP.HMl(/YH>l<;5s*%T&1b4C6&QN0@?^R7`Sd$a3d&:-Y%Aj8VsIll`*CBFrm2_o/>LnKJX8.$r?8*=`T5+gPRnSq*o0p3fhAO5PCfi7u,Y@)K5YQ/t;]f/a_QY+i5?.Lta0@C`;3A"/C&;:nU<=1&tbbq%dn78\p[RG;k8%Xfr!>Qftoc/dgIBR#/J]`=['>BdN#H[8DAX;(!^Wc;G9R&s&8b(FbplXbJ_)$3,H_m=5]XG/HE/"fRg7=YiRj/@Wa@Kn4lJ-IK;6&=,*HFU/>=rEY^e10)>3W#Qp6HlIcf*a#$Q[D@?Q`=dlh`c(cEo]K4`U^ui,!^"8(opI!l3A^pX@=ai$JBRE@)T-TacS'\n^OEbGOdh`pZp8('3/R!G2c\6pg,+M-"PRSrGg`e"F?$3[$D]2crWji=MQ'_RhLDNMnT=A3SBq]^:b?!R%R-MR6hWsA(:!LYXR4/P=&Lt1'`=]S5doj&?GKKk#nfKd63RU%G)An>a1,Ir/.'N-'T][f))_VVr\^7GQVc\]?=.kq%$rhHW9,8H$!9]/OlE1T16UdV4KH']c`%bS:#d5HdLk"#pp+ohK6Y#6=I7_%X!-bDnSkeVBR%c(%8He2b>,Tbn)P#[]8=j*h)iM4V^1(#fi1%didS[sSEQoaCmB2ZZ[><^@BLu3h%BH#`2X^7$?n$GWuoUjLZ/.P31dXJm-=VQAh`e10PltN+QoW=]s@75^gqclq'^aCu(.qn-r937`cm2PkiH&O!N%.3E.J(30A;`Yj[8Oqo-_q?Y)NJ#(#pkIo)GEoJFR_nT_?HQdiP5#qk;`J2TX=oa?d&DfDS8S`8-^uU'(E:he\T'0;l?6(Z*ejkOD\&ZCBV'%!`cO*QE+%Zl+J:;E,A&PnBGcq@5S*]$7qEpP^`9\rZ4d0t+qY^]7n\NGm,8Bi7!)?j@eu,O?*Q3hOVl2P<+io,Y&fDim^\%,cI7D0m[1rb0?#c\mF$L,u]*?ZEs+\f=6?$DT5Z,Q9Ql,=_7`g9f,NjWR;elCan9Qs'@SmL2--\`7b<5NhsJ\pM:>0g=!$Uk0^FZ'=_^*F&RoDGLR.Ot&;ar%f2Y)b22L(!&3_9eAh'aBN\]]M[/$@6u=#n+,Om07^.;mZ/Y##OM/4rip9X$?*tgb2("WS=Bs-om4`!8VteCe;LZM4l9%^>4*62^^UbXshjHhQ_Tk,NcSr39jGT)^+^sj'V,C3qdjS4h9)ZVWU<"6*GF?G2;)hGDjI[?Bt9F/JiC#+2sG@S,~>
endstream
endobj
76 0 obj
@@ -424,10 +424,10 @@
>>
endobj
77 0 obj
-<< /Length 2356 /Filter [ /ASCII85Decode /FlateDecode ]
+<< /Length 2306 /Filter [ /ASCII85Decode /FlateDecode ]
>>
stream
-Gatn*968iG'SZ;X'jN(A0giTEE7nd%9KHIdNLESrKd'C&Ae`C]jLG$["UW6M*s)qj3YU8D0;3_'mWV(VK^Vs"T3$qh$^0;G^E45&Q=`^[kNXi>mItgVb-]C`UoBM1Mr,?>JerCC;X+Q).U8puKFmhPNY^oS6$/F89RWjT7e&l:mj=f@fg`Q/BHaLYP2onOe=D_L-^RMX*2C\$)Xcg/JIofDmr=oHcML1[Mc&sd-WJQJ>NEZ*h5;DPlX6n0!1B\$5Fb-B_\Vt4\(C=bPN^AKrdMSk7+l^RDJ??+uIjkX_4;@7@.>f:'H*;%COC3-Jc@^hB9p%e^1'*JT^n>r%JQi%ftISlM5q%@3",[DVFl8msnGQ@^V"icnL`"u04EiU)URGJFRq+ZV&qisr:Ed_#/cUcYgml2J'qU^Kc0Q>LV,UUrofE/8U5ZBt83*n#$G6?pa)9iHSc`pDDFdTn:1k`^m_Bu*>1'oAtgj+?SE]Y-$g3aO4ff<)#fdW&EcGO*;F]Ll#kE!A-h-OX#*0E//tp2LIl]c0VEdLdj#QXn@H"sK+"cQnFjj)kn/V9Ghnh"+WZk;HFJ?TF=.hJh7rZFF=L`j#GZDco\+4cIF?ZJetp(/2"e)5$PYG4"eR[3J.1oS;Vs)HR%Cm+*(40XuSKgDs4oj+TgMh3toe*LB3@[slQ4)iLpA=F8,8*]%V"UNIb@1i23833:\/]t'\pPO:@6$ShlfOglruj0Xr*T-hjjhO8;P2e2&]k1r<1Uj`Y@WUXQ_SG>S2e1>AH'm!:)#G4YgFQ,];S`1bk_K?EiP=/7KLO+l%uo.s#\_r4EbF*m^L<:2V`7!N#b>2c1FU&m0tVVuXhCW&E8VP+#fPAt2&^(7r<1UmqQ8RR`&@`(g:RI>(s3g3_iqk$8`$&Y6=-K".O=Y"$Ldp\u12)Qd#jWFcn/)G67>TZ#obk8Im?h0@C`k!8O;OZ^LtYuh)Rs2R"OnR65fS]V$j9WW7.%&oNIenA8Z5.MKQSY&7DhBf<"#<8FMR^&(\,t[G';/D]ebJH'[S1IsDgnA01u$Cl[EIgWDO_3IZBmWmb[3XR4-mL]*pPLSsbCE,_BrWqQ,!4fih=rFTEecGOD[U]#XGD3!ANa.'*6PSm-JYFL^JX2mo$,gCaXrJ,lM8G"^'PcJklB.?oZAV)o]qK?!eKMBS*ZEt`RbG';2[5ksN=?!-.cDW@k1bErlGst>O%rkq5L9+(:+Stb[IG.Z.,O'9U5J,\><:=%ZS:+6`XZ,FCEOMS;p/KQ]pTh3urL^.PSTM<:DAO9T#'Ti-pOT]sDKWd>JeVe=7=!RCgt@N[kGE$t.pG:HP4FcC?BXiC,?mHe6:p8KD8iJI@A_,4j2"Zak6L1(%on%-IX#?um-DJSma"Z,N6bKeS`/:OqtX`MIUfbOlbRkY]3:9OnSgHOpPZPEENb)Q/nlMpr^3pu[HE43h>QSX^!S>E79UHe9cX+=:>PT'51\KRhqjctYp4VTfR-tsHcVZQ!L8DN5;%V'OY!?'kF#j9B6AtP$^:."lhg[>'i)Ru:GSi2(0i-YH"J6g>37#k>ZG^@It)kDdHp
+Gatn*:NP8K&B4,7'KeE42,+&R#p,R0PY%d.[T7`hHVc!Ak):lPPT2(.^*'[9_*7uB`&a)aUmKHr_u:^B:&'1FppaLT?*NO!s8KAROuS<(/CT*GZ?^jM72?\2(=d!gAb#ZW^%[+Xb1I3==iuP?rKGdf,&+5QoIguJ.j^7_,`Pi#dGJ%&?2Q>O2d6/8L_215:GI?IhAtKBf=ZO8X,jm;ITu4-XY\kd:X>(JXYWXN7N!!sM\ot#oek(g-%j't==*f:?SdRP-MhU8=qs(b(:&eJEP-5oo:us$NG]E'i/'j*JJ09tRrE)*H]lE3-f*@709`F*6o5hBZA^GUl4R-t?tk^]U0DsgQ'3+KBe$FM=B>+2lD$!sNg&H.-Gt.AI">4dY]A4d]l>KtZY`Is#Z_@[jgNt2G?_gC.9Br[1VUZ(:0>2-KFhfpnZ.i\5%pM;6WF6JN1`Vpk'T@VDNj0*D?E@t6qjgPR+>\V?G,NcS9L;")15!$.ZJD"AJZSs5d+eVXRP-\%6GCX7%cE3]]h26nWGHX.T?"Y6E3Z)]H0u72E-$sEGjrb\2_2$XDdYIs,2USYo-f'r;5bD"d9FFnR/m3g_QJj=P9dr@f!]Ip=KE.R\GcJFp4*A8,DldF:>FBB=?h"h?*X]UC$pY#_t;^DK98#+g,.+h%9W]t6hg,k=)#OAl25/:bFB/m\\'A_BV%3K)1+cI0TQFc#TQUNqoI0sDq:l(T6;`>!BZ7()j7jK2_He'5^/47F*BXC?!qBcj[iN*tl0V4n,3'[b*RnJYa%Ue6`\$l$SD2XN1o6(%U*M_!AL&n_qL^qdgDDJcR+oY`Ed3'Jbo.,lIk1W@L.qKkBTkso:&BSHVgSS4pdgoT*!$-L-b?^jBjX-!5/:d,:)q'T8EZjG+cI3EEH>jZKJ4s8_KU)i!ede)m30=tAD2f.Rm\)Mm1\9Dp16I&+*UP?CB:,MBmkX9XI\S+p>=S@4hLm3!(A$M0!18'Jb>4'K@$`k@jB>T>F7(:MM0MN^&[JsS38Xd$S6*LkZN8j$XABZ#1;Wm&IS7-!\]GF0;K(b^pW[J33,6\%'H/bf(Sr,:Cm;TlgP'_&Kct?Po3Zf\79kNKQo#?d13#^W9d0Y-3:^$V_hA(6I)sS_NlZg+'A_BpE$:lN+,R=%-X^=bUiY"_=N:gB!B)HN@NCb'3Hru%C9dLi,%iCfVl(,.&(RA#'^3*aJ#g#SF_7t0HEPH/U"\tHPHPKso75ibn8PHM+0F^_b22`KjkX4MWCm&]a5am\]e)2?D;!rDf3"t>7*YIjZ0&Yl$5H#&I<>IDIsd-tZ^e*nEI)qs;g2ChKsdU5b<06C65HFt//U=OkT5Vn*'ZQelbaTQCbACjOliQcjP!R[mrr@_=I-p[AENi>IG'iH9@DG'3ni?XZE"n3XF8JFXZ+;+[^Mn-qGQ`>p18%*oq/;H[Bd6;H180\49g!(?hY_oGJm7CJ=R7?)HiSR,-uIPp/nfKeL#RJjAE86_s;BW.cYXLcd1q%6RuE5a$lTia:eC;e916Do57c]n"!TZ_fmL%p!`ciCC7Z5kVVoZYZt)^8^(b,8iE*D^'CX-;Z:N]hg_uf.erY+XO`m(WJnF/OdVGROi^.j\pEYB&,YN3F`m`2_O!39EV0j/X?5E5P''8F;Q;maP\Z=upNO[0F`![PmU(.los&6RH[`TNG_%kghtpe%Q\VmG
endstream
endobj
78 0 obj
@@ -439,10 +439,10 @@
>>
endobj
79 0 obj
-<< /Length 1821 /Filter [ /ASCII85Decode /FlateDecode ]
+<< /Length 1900 /Filter [ /ASCII85Decode /FlateDecode ]
>>
stream
-Gb!;dD/\/e&H;*)Tl3SSQkf:s]``#t]$$C"=`*e(;ZsI$gHm46V<#;UfC'tXk0^%E#:iUZ5nY20*UfSHmWd`\l/:B>n9%!u-2bJ!`&=m&+:-o/kL\$ILD%XjgmS]O*kZd_l;o4fU(0jj(B_9pabCmPD-uoU'%id5c)jbhP=h^kneLV"33mhjQ&0.&S7_9N&)H]HM02b8u4`tKA$R)E_h+o2$A-1-/+j[/143'4M8DN$7PJ+2#LHYW*"+`MiBFV)d,`YTmkUe"#Y0R)P%3P1@%01oQ-#Cb"\=jM-5U5-*ZorQ?(>]NO:,qlc=H?Q*\&Iet;=bfK>/OF-jgn$X03)VB73L;D987TbFnkp!Iob1LjisFJ)>k@q$8N^>fa^gj6_1WPWW/N@`1$"@G!-=b%MU0U&$]r/#/7_pmJ(%nZ^Qp)&-!D`5aBXkjBiVu@U2=i(4kW)$j[sD?p=n;G#l'D#dc@CbZpQsg3$:tO#Jb_6WoXpqY\7e"Ncn6:d3NAHl@8paLrcNHjZ&`2XMdu7=INZqbf$CD_6i9=#"1s+Koec$Y6C/uD)QL,MCNs!jG;QNF&9TW`!#E)oPp/^sj3bg/2B5u6Wg.+ohQ,u`Q>+X"1T&.EMVEc`l`SU?$Qc:Ye_1):mWhkfA1$->!HL!n:Hr(!9g1GX9P9?dT#\$R^&.jOqn?7D9L'fqhI!I]KQ^N[bH/*!VFGEj\J`TaqSiBm9Nc)]?%(Q5XGrXP]dVbO*7c[6kT'mCa@,TmhD?[chVJke>_6R-R5E'mh25>H;\p;Vs,oDUVd-I4%]4-hMe.1JE4h`.;h-,H4%7lAG7u9UDdaeM(a,292UeEbmg6;L9Rr'bGVL4;!M:TtN>:Nf<76C0E?D?HY)M1jbQ[js?AgI#`)3rrnG5VsX~>
+Gb!;dgQ(#H&:O:SkcIuqc%qO]9.pYuRlK4^okn7u0A.J@A_InDM(U+CV-i,BCmdY[g,NbrTEmFk8SL/*k0/O,3?>c(%fRMGB*j'+#)PuX-O`B;5@Db-O>.A/8iX/nT7`J;qtBUnF/T5B>^)Fg`AIO+_E/9FL%$ZaZE'PiBn)HEEiQpF<44V8lTtdK3-tR>3Z?"a.*>N7`EZ3_*^LRhj&)\R=qBp6g,Ko1ZSnq0,\9h>]J/\OBRU$FpFt.I+_2jY[OOs*m#17c2O`,G9T2T>FXGMAGfVT;A1<7K0IU]F,2X%+!$Y>\h*??q1Z7]UD"\`C./dF/4?37.k#qQ5YF5WUOHR,k"(8i+1L^\!=L:)&:HM+VBMn8@F[Q7WSLo,N[mEQZKb@Bqa]:%DM?9fD?O:A1Y.I*!dTHfB`uHmp7\HLmrN@__?=o$M1#("'^8(9K+YOCF_cHT,S1>+:rW-"$cea^41AjGR#]X8YAs=T_?)GWQ8m@coV2eck;/]Y[V(>Z+69aAEO()qok^8G\u_ec-VikJ).Ed8%`'JkOd1>(nN9asAP%TQR]&.`?Ci7'#2THVBr(jG!iNV%(2.DERb5jXTnhH:XYeAJ?KIh^Aq_)I\D]f5ALU"mg/pJ=1W[Vt#aGuH/&@3[HeW\(=3r^&A9@eQMW<)$`XT$nsjRO:FeD]_XfbKf(%MJZIi27Yr96^E<-(a1\j"-6#7)i:p:FIL@iu)+/h`Paes:H8CZ;:84_[@;]ls1RORqd_E"9%[h\dX.;69M_e//k?f@X%d#f&L1`^g^t#KTP$\eT?:f8hCcY$.p%\8@No7eOiDh,'/U(Ll,"!j
endstream
endobj
80 0 obj
@@ -454,10 +454,10 @@
>>
endobj
81 0 obj
-<< /Length 2155 /Filter [ /ASCII85Decode /FlateDecode ]
+<< /Length 2035 /Filter [ /ASCII85Decode /FlateDecode ]
>>
stream
-Gatm=D/\/e&H;*)+nSEk+]e8RGm+DJ:>BGsSLsPi!V9^G&nPjbV,W]>359p,/;JE^C!4=h1_;7$I.$C4j71ToF$&W6n!Mg\s8Um=)nM_gT#^jlDXlM)D--J=N,%t0Dk0[:J,Wm?C8Su-9VRPEc8,/Z;qoW?/_r3&D6hal]!u7&FT%SEP&M8AkgcN\[E9dK^(<2_PJrE>dVN39GEW6k4O#:G/DbT_5Dd3^P5CU"hqI/S)@YBMSHFfohh:'";TupkVKaHGpGmjSjfoQBIB8f`ec6i9L]hcLGcEt[Q#l\F5ag!0J'2P/\g*!N<>N2>9,#n0lo%MBnG?2#&7_3`om0B:s)]a^!sbOE$UXnr>cJ'a.nBd.-mguWR\__U&bm;`QJc'MhM3!nh*Qj7'F.@_/)8[>!S&+^g'/e!#=J1WSI*7>SHdG$>a2MKSH>Z))#j+sf$TFd-8'k&Y0(rVZ:id&B5RZSQqS++D4e-MdB.*rgc)\mbCUKN0!!C=o"T`?W6MY*L5c_*XucRL%[.$,sZ'gYe<7u3KcN5plHnZtPJA@6.Q\5\\l:DR>kHjQc(-n(;,j!o9a"=fsCD@N?gU6]"n*5Akd`b%Ah%L0n!F]Jc-a[r!fIE/>fCUfNG]]6UJ`,Fl)1CQJop<(XLFO81D*XN==10@D8E.dEuGG1iU.%Hs5d#K!rJ\XR7b.pPIdfZ+:@8rnW'hQlaC4i%LB]u0ieM&;,`Eg%eKCssb#@Gp;hcc!*=AIJ*:d[.8cS>GV$#4Q*d?30"9JlWFk@t&J\k[ERC<48&Sj%]o?YBY&Z)/dTm;1FlM5D9=CfDOG?HQR2#4+%tnFDI>'Kh-k(r`u4cUjFbSO2!u29-pNGR&U(9pD,8H4/>C>nS.K&0fFq6%q^<-`sH0Z.s;1W3bZpDJGNQt$E4/`E3_TAR=Gn=i%%0fk-'B=R?>b0p%QsOUhHn!NpeTV1pctC'M5%a+P[[pfSP\XIe(+QF_!e$bAbBqf80o\:$F(?N+ld87og;d/bYEj)5id4`DSugq<)J]jT^k&_60]B*@lQO-)!.JZdaaMM+9L1FhDVBLQ0q(bhCu`O?=PeT*;,/B]rDn'"S/NuW-Xs^(2COL&0VbLLTL=7EX;MebC>I=7Rt.?,aD(fMD-R\#%.M4L/Zf2g;Uob-9pUTL4+\;a2GiafWZbOr"nS/e6C7h;\fkB?Ot]mq| qUEQ_O=D>B\P\qS0`%R;9&2X=a%6t!&oi=uE"l'#;=0BPWlhNXKQtL_5Zpo%q8^PkRkuL\]K[q`(/L7L:SIt&PVt;'K':$`@Y1>r9,S>Sb$PEZdL76V/^3k:83"MsJs-qMh*'F/p6`6atk1IPs7Bc^IbUI7O$Y($&`D!cQWp!h70\`T=8j>
+Gatm=D/\E'&H9tYYjT[\>(qRD>`,_Eq.I?oc25`pleS%0T'!;s(?*DR?",UL96H$g7MH]e!*9mHulDIX^\E541b2ZiJg-d0(GKM8H"%jC+8R-Rm2`q5L*O2>5Lr3rES$dAa8ttk96B,aHFE2'7ZAq.HO?k1sQf9&$n*MkL/Hd6amQKpK9FX^*Kb(er(;_QNtB^I";IGmA`91+?2=UH^\d$L::a0S9@C]%`!C<>69bA(g,#sf*'l)!ce1KnnCe:Qr==l2I#0eHrVrTO+W,M]r1%3\"h'L5PY)"58itdK[Lb-G"\Y+^:r16?AA9T*7P>!(P5S]861s#gn?d-?"bYm$5]W[ZssGd+E.l>1,'>U>!N`nN!`OHU1bH(Fc[9$%8Bg%:0`WrEL3cF@(B`#_"1$oOs<&S;:$2S<'rjDgPGkdp+(/,iQ1YE&l&AP3DG$ugN^c@L+5loaVl`,8lOZ,,pb:HkJJ3(2!0$0K,i;6=rR7>%T%qsMDnd^U!Pe>^aQs_EDFrHlkF!&p9!g5Cpg"1*[*59bLHWBQ?S?F3=?m)YB$M-Qr6.?B:$]T"aM3]h'uR29!IpT\L@+s'Y'g\M)#16Ct5;f%2G(Ld6<7+F.g_(7rYDF.nB-#FF59N[02Bp><'lmOV%.dXUj4Cm[QXF[)C[Q.#m%s0^m8(9*Ng&g8HoN%oZ,co^.@I%3C<-Nl=4l)_GUW)RoKg]GRmh$9P-p''7Sh#PF7rt4S3Eu"Qpt^aK(M3,#PlWosRFm]7`g*0FXXIeb$"Y'h<4o'c0pEpHc@n`VfkHVrp+";u3T(-PUD27Xh;;Z5^#>NLh:\bnC3c8E5\[++QM3G!c0XA%=3O(]eEBS;#J`K1]MQ>WaL$#K_/FA7,R%1&a8Nh)S5in^Su/67E"395"[gnu_Ft[N;?inb$NTe&nmkYsJbUKn>VOX<')DFV*-FPN&_M"*J<";Q7<4Xc$r-M\U'9ECWDqTGMBIGRL*8Q*9Lenu8$h`tH7^4FT^\bPe,jAlKe2rUJ9VERbXkN?h3Jj&HLmu'pN>03H<"jbt'9f2,WNm*Q.%W3(A$=XMlU\H=*Ip^t-_shco.6kol]&hupjFY8S3E(gGA*\!8K`%CbnR`eLYaPMPs-fjp/^JUU2a,W0oT&6ND4=aJm[*2c0=s'0LBZ(3]*JG\0u_3h$s/D1Qalto0NX3g8W[d]
endstream
endobj
82 0 obj
@@ -469,10 +469,10 @@
>>
endobj
83 0 obj
-<< /Length 1945 /Filter [ /ASCII85Decode /FlateDecode ]
+<< /Length 2006 /Filter [ /ASCII85Decode /FlateDecode ]
>>
stream
-Gatm<>Ar7S'Roe[&Fu%e%4b?+%2]V/C-$+Kq?lD)]lS55\$Gf%]H9;9V&&8=495@o\-6#AU:2)*D!Yc:lCu4O2Yg8e(l,(>FTQ?@d9#NleX:0\oh51U\_?!uY<(oN/+aPXoYZn]*L[*B5Dg:"!8.te=9QPdUaF9,WUh$JZRg:WXZUtpLRc=AkbZsM&VTuh,`C*EAFZ>be_fk;K)ihj#6i.Vqk5#@cQtW>,<\D\gX\LbD>tHk,$oL#I5a0P%Fr^<;/%X"$>Ta7766<"!D!>(%R5+a!ql#Ph7e]Hm9F%6tHPf3ZS"40BY9:'@ik_Mo],fF:?^_$f5"T[X_3mkKNp-#<8MgW;D(Du\Akb[iUtG'.9eA,9Xp9XbS]0bY1s#A8Z_EC)o2&o-3%rEF1''hf0e[iD[Zgso1nZX#SN$SO@eehN(G&R.NL@YR\O(bjL$a'[UKS:bSKZ^.[lft1$b(7Sebu%^*%"2JcQFQ=?:GEMG3X\*J@'Eb5BBQ!q.U<*uXDL4car5spB(.`o>,+t+4W9EjtT*acV,2C_KX@ZB@0K?73]o+[,A,bO_HtneF.!M$j/"JpkFB2gVeB:g'\&Z]rdUpAW<*)Y*3H9O0qld0dUD#-H0RFFVPu%#Tm]k2tf=9!Yq1!gcSF]i2?8/^#W'BA5((J^&"ha/R14FslVM(-Md'\3UYKc:%"`5Kmrlp0PW`UDbr#Hn8IdTC3tuE:f8Yn!Q?,lI*oCdWYG2(CCB"V,RtHSs+>u/DEfXg7<>HcYd?9.RH>qg!cLV3LI0NoDUQ1%O!JHm+%[=hFN08ND+qLLjDlc,<'Fci`Yg>c[+`tkUd\oe@*1$'_X.MRg>HMf>S;69,-rHS@5JX.d[\=i9nZp*,:R,.Y%`XQ#I`+r/%j-hWtM#OKn?S9hok=[k5^;1FDM1AKIYoJ6At[Hp\HS`*&%tj#!OMi:IDL?O4ZTWaUntlb^;ml?lidh1B0PYPk,r@FV*tl\E3(!bE)fM!n2Lfdm:$O90.7?%>aZ.[PcCN3fRs)l:V^NuAr*/keW;O1UE'HN?`TVH1FMe-\eRteKo"6AY$`IESIiq9/rkqElb,o:jhd+u@3BMk4AFXnd>+Dm5L%t)=ZoN%6mbB;0;7!>46NP_I?T@KC%a'GK"GC+Z<+[lZY+"tF?n$>"C*Uj.`pe^DF+%rrsFG(!rc7Oara,t>s?lU2dcjp\6h>".olA),8qjH3irDd(=0sn$[6pKn\Y0\"0=aB5"YlVN;!B3]L;Z~>
+Gatm<=c_;q&:XAW&GDq>@$_J))_DCBRr4Z=8CPLj$Zq;YQ7/5Y%S);frq@F)Q8OoK4b@LS=cq\uo?HgMkk/udbB!,q6*3$B^0O,bYq=l-iIBJFT!(;t-e+'U8m&.5+,ea3DP34,L6fTeodn8Dbq`SWr@T&g;/=hK1#grj[EPb&0'fC9`!bn"o`nd"1)'=;gi!=EgMA-]=c7DTMWP.#Q'?:Cc(V,%=Nc:ij*-4A]U7=1lB09ZmmJJN"'2?4lUj&?UH)'FPR*.e.gkbW_`h3Kia-D#06B`ECA:8/U60#,;mnZ+.M8"I@^9gtjt#dd=SS[R&-JV_GA3$)UIFirq^Q]^dU""piA7j3K"Ui!-+Fm?"g^)H(JY^2c=sgqL_p[timDZE1-K-NP79)Qa*6Jl1it!Kaqk27!;6:h:(5"r+/T$a-jMoWVBmNH&0FmZSe9a@l$&_^#(8%IYopOsmBS8uoK=&oZ:4&p_#d2P%qMmY-deUm]MIeMdC]cfG_uei;[33!9Pkl;d$SBc/tSO%hM]F'W4XD%`k#P!*pkFL)21\415;b%1$0KL3/h,$_XXT)V&b9Fej=15:hNTXap.D1nltIS`=:bm!P)`T>%b1npCAO+Q[2G=8,Q9f>tF&!UitnNGpT@6W>\rJ%hVYgN0b\8m_ZD?+#,:lldS%Z$S5$E?eWV'd.4&.7>C";ZnX_H_!jiH)o;7`jq1.m8qG8mI#Ej"p4*MkjpL@uj`K(^d"D$M-i+BJ&g-p.Qbc&!"R$_KgYCBTDXRD*Fkl(..2uND,Kg+rt?24M;VV=4-br0YkC"I.mE$2uVH>$&S`;]A!i=H@0f6GB4L>eBkA`rpQVpHiZ@V"!CE5q( 0U,Kc^,JJUddPU(n%"YL>r62`>i5M8$g7sZa3P]\l'-e!-]k;`)]K>GIqsPl1JE0k6I(mPH"gj,Zg%AX0&o99mnW.Crs!g&fKJ.83eU98>akF-?@A.<;5U;R79#"PXWo!Ncc[?9=q*`rcT(^n.Wds$-'GpMrD$Q~>
endstream
endobj
84 0 obj
@@ -484,10 +484,10 @@
>>
endobj
85 0 obj
-<< /Length 1375 /Filter [ /ASCII85Decode /FlateDecode ]
+<< /Length 1602 /Filter [ /ASCII85Decode /FlateDecode ]
>>
stream
-Gat%#>Ar7S'Roe[i7j]oAk?8ZC$5cFm8B_sMJdG2ddBD`.@Z\UH5+mhrUlp<2@jNEFV#hG+aL6gc:;ocRf0L[rAUKbUOV1G14fg9//J)#'R/I+3(Pc\6R3OqR/JmHNX>oe=\;$1rJrAorl69W&X"(i4o+h61qJJfj+9a\LKCqkU7n/^Pr$iY7e@3[K5)+[N!*SNQ-ic%5^c?H?E@P4&\)C6X2CO'd2eJ9\eD4A2!_b=+tV%Ff[g&`(-=n73-EEVb708DM5Qs)Llfn.;[p:=ULbfG22S%B\Z6sD/Qbj0`QK:DQd:1np(I-Dr!*)]L].SQ=LRR0;;h-3<%t'aLVA;&<%jWFc0U<:a'?M$ud@bpLZbli82rf-#ePU`jK7rWf,JHT^[/=<.4[MeFW;I0oeHc`9mnScY+^JU@9B\tni@WA6H7T0D#=09,g9$-di2*1.s?p6Usebh0lnEQ>9aYtD)h/J=-im[I>Y,3K3f)t#"D/:4+R8ATLEh151kFt"Wj1fOod<_0&J'Z@]3VVOM[uWuRR].n*Hpa&Dr-]["%[Y,dl5r9M6Go+)i@3NlW;Hk[#k>h"j)g#elUG:@KQIE'=9R0eqHFG1Kmh]ek.H^!B3gHa7<$`K.?/7PSHOkW`UBC3*^G.0UmbQ&X+9/[^g6AV%7.UKJ^0)\3^TkT]8q>g=C=cr$-5a\*P)[:FmlZpJ7%D6C7n2ijNN3pb/9g!q4Q8cGXF&J42fQAF1XF^lQ@pTkNd@4mABYa3<$rO6n*_JA`5@&0;/'c*Y?;EWf*W;Klj0ZNoT0]4?Y"/bs52/UB)\i8(((B%$?iOlT.?;Vh,=!]-!HK<=&*)EGL5,f*Wh#S8\>)OamYl'OSmgl=4(#)(dnb'Kn-Dqs26-/IN=5#;OqipM(q*hT@[)fleR1`8[[Qu?eRP_+iC)*2(ga+GXp_8D_]qIRSonq6=u?"/GSUE<~>
+Gatmu']&X:ZtlOp),V%>.#J)NTH9mG"DQmk(JP^Q7+jnAXZedcn>ntlpBBaP*Y,HfNMeZHO0P42nGcm\1U1?+uEhN_b/q=5!IL:9tAs.k8Zu("0R]HFg-@Sf+6X;ih.iXJ6a6bapuu!uhP`QTHE3PJQ`TjGgu`8'.dBi#i7Qc&ZPjfR_F=E>#mtds_N=\)5+u@`K'bBE%#]T:>qrDMWlV^6g&0#6o]'#7!DB%5URB&FmZpbQo?RJViJuO!?fulBA0+2CaO$&b2%US!?tN32b&T,.[H,28"0:oJ.L__6B*X+6oj%Ih\HIVS=*ldc6P-lN1ONlL"dVAqHQd5WQTs0fpo$.Zipk',qHh/!g0/f,aEi10Uidq[fn@q9CF>,;E]55_O&0YK\MmX>&Fq5<=.0e3E+i[Uok$\;mAlbQ:g`aL$(Rn$Y]jN.O`A=!b?XI)7:=+HsLrJ:EEuU,sPjN>`,ub4p&F-8pa]W#c=@qP'5ncLP:.*mpNTlts5AKGC'[8BRGYG=5$%0Sp2N2F4.!'u]uK:T&9+Y7&H6SrJrnhHo&6BT8V].Ed$.K5W?BA@gb7a#?Alo<2d4i`&GA]*d5HMq">WAi0L\+qt71&g9-%8V58_%8eVbTL-@HLo'/]26CW>g@lZBD0k>^n$#;CQVgO3KUAH"(26]F0c^t[f4?_3&!5[#95.>B(($)WLi$hTO_)_!1j$`+Om5V,caio-UoZ>LQH&,VVl,s5:_%fGCY+P`VYqg+<#TK:B7j9N7RQ!k(``bphGe[0U!5et]1Qk5L8`/+TX543!1jG-f6Cj01-UUWB+4G*7IF59ZR##+[l&@ucWaE./4>UfN;9lau#&d-7^L=PZ6\F'&'FjSf7$gNpU~>
endstream
endobj
86 0 obj
@@ -499,10 +499,10 @@
>>
endobj
87 0 obj
-<< /Length 1291 /Filter [ /ASCII85Decode /FlateDecode ]
+<< /Length 1282 /Filter [ /ASCII85Decode /FlateDecode ]
>>
stream
-Gatm;gMZ%0&:O:Sn1arQL)3^R@V_Xne-d(,Rl9[uZu,o`VJT`Va\1$l/Gel_A]l'nFLIYjK#F5mkO_;-m/=4V8F6"'\qFR]uLD@m^a:_1X/6$aL4Lkt4a!Uqd?2XA5+lNGkhn&7jBA\@S7.bV2&=bg:bS_'@L=5,DJ`OOaMdL`9@:BWnX@K@SM]1I'/')foGI@P%Gu:tqGHb)MJ?kNPcGNlncp<_nhA#8TV>=ic+94_jAj>9eXEEo,HS*;t#-']+U6Xq8Csn1N0^+&L[b6ZAKjKHp@3;//_Os%pAF/n9UL@Hh3S?b<>">eE:B2Saf>SRVse@*L>Bl?o?1r_XMgoQGDU[YAW3@##GK'kYCTIR?>@0n?8A>u@V%9[DDgDhckO)Ru2V/3_DI6!uK\-[^H5B*Cm\GY5Sfh9,`:]A77MJ?//OlgdnGUQ3@4H_[bYW-N3d&.(h@[=p+_$4_)mKmeiI4pk&+;b#_^TD^F#/4fZPYXcE;Ea(enDA[C[_Nnm`[KsiZQJcd)f[GOAD-U`[#DmYKbK(&nSfN/';b>jTu1"ELF"Cr2L`%8l/?e?A86/DNnB@:Y2mUlOAO)Xc+4iZ>T_-mI!Kb:;KbAg)t&C&Rh''![X]e;jQhFrbe2Yp>$oaE0eENJ[`juCZnp'$p@BfrQ\9@qcl):S1uV-D/GM>8KYOOH%Qd==0K2A:&D;O8XQ31N(VOZ_"oBbqtj4pc:uEp6^hH&P"QN0hkgI*XRN@&H=BR\[h7E]r)("RArGSQ+hEP\T
+Gatm;D/\/e&H;*)_2f';1F+8=e?B+DS%8$MXY9D=@Ij[O(@;B-,Yt.uVWa'o.9Yf\URH!>K#Bj9GPCUp\`784*=gUL_=,q3PuF8dIJ@W0qRL4aKAF+StQI+Xc6Cl]ZJ[gbcXVdQWEn\W`gLP_"pB8(\oG(LAjTaT2/_s'Sj@pW'B48h1&Gl96C^a\#[:3n%m^7f^"88(BeVC\=?QF[1lMX#1ZeX:Bg7pPmD$($E_hXFd_4<5>E350-X.2?Wh'JWNiF$$JPT\iR+XM*dS+bD%)o]<+_7i(_hp1OFXTC"%g;VW=o?8bpjl;XYS1E(>ZWU`rrGg^\X0]iQ0)Z$GAFW\CV];c;RqHP&E!Q@5e(^?.$j?^>1oL3!@U%A$/a/@pPl3dp^Re6GCZL=j&/!+VQZT<8rX?Ds8`km#C7ND:/2Kd/QPR&?$_VQ/f:?^'J>s]U\Jj1M(k-f5]"&LC.5ki957N:-2,\/.t5MA3N@QbpOlq5cEP6iQ_,#;)`s.7,Y9k5BK3&j3#=l7Ps>kNuiA?-3Of,lQF68J_n))2.4=%^,AArX3?0=-6OW@%`6kM+<$Al#')H^aXQ2U_m"fq<"=Qi5k*1,QDQKLW??+XE'QS'QQe(ne$nV#)'-L.-9)8@fI/p)s6!BC$CLGT$gs1ERgM>n:A9I/1,/Z&&n;"7UFU20Y&2JVEG'7?``?^^nWrbc=doV9mcO@f\so%Sr2<1:l\DhIl\c;L%P7L=;3$8Mfe;S[UN%k-AC6pW1l2*K$;Ei\O-f/E&!YL\)G\*GG%(Zce_fpJG,!?%LJs[D-Sd?kF>7:HPUE+s8/PrjUKEj/AP$P0a'H:E3"s=lM'IbjXDqL63)U.(=m7qS(TRQ^:C5q9jb0t'K4Rjd#aAbO,+=FhkjW0+,0HdUoP0bZ)eps5$#-Rjm3&j"S0&DC49m]"L@GAW4Hd?9l:C*c>?A>MYIFTRA*.kdo^H;&+Y1=O@sUOd"i#&6S8L":GMADL)ILN]Q^KD,P^a%GR~>
endstream
endobj
88 0 obj
@@ -514,10 +514,10 @@
>>
endobj
89 0 obj
-<< /Length 1808 /Filter [ /ASCII85Decode /FlateDecode ]
+<< /Length 1696 /Filter [ /ASCII85Decode /FlateDecode ]
>>
stream
-Gb"/(95iiK&AJ$C#ekB_XL3@I^(ff!ejYJ'8.k;sRN?!rZAD2L6W(,E?XHEkbb7]k:)iPn-l,sQP_Sef2]mgMO3>Y+bK85O[FX@+Vod`!*@m!knUD+Y^Ls74fR_#'[@7"Oq=s7,5:f.Eou*&*0l]6'8,RE[f1B/nd'FrEYa1RIqn%W\..I5URX*^emq/opjkt\G9\)/R+4g#GnKP\_#K%b[%#IF@&6\VLHR\r^Ada?b^e?ifN(T[n\U-g?j10q0n[=q9lZNrr)g!S7J%[.5.h^-;gDNDF)dH%(!gcHe-p=h7Y6=?9\!hSd5hd?N;:#FUFfTE[l9.)aRF'Gh'QqNYsDndJs@nP6qe-7MNj-OIgGdF'EK!A3\1h0Ml5C@>1JU(Y>?'?E5((_p2nCn$_em_hmQ5jbRbXX#Df4((C%eBi"%;A2uL_;&_<%GK90MIjANmeVk@DE,,*i#"W>rS#7T]d*h4_*3q.X1sW"e(#0<V-'RtX+ZHU(62"e%T(PAgB,h1d$6DoCPb=uVjC_f_@3a>_9]$f-<7GVK&1!+n)$Q!]HAu3CqZSQ59_B8>7'U9k7E`9WNo6M(emV72KVRXH&;AqpehEWtG8\[h:6kECAT],+(HI9I8n;lnLa8P`0`2L\'A"bE5AM[H,V[XBe?j99`4ZP?F3\dl@a&G*NREC>,M=LW9p][7tZO(2;'pXT!s7/20`Il5BXCp1GD1<)Tn0>cI#sjg(^CWDng+HHma5F('/REqEms&8$7'*FEj=:/o"$CL&P_f*rtq#7jh1gEWUq=@''R^e=)u9a0$QXG@/4G;QtC,71NU`0FN:#]*D5>'`i[r]R1@O=q[km\r]5XP@ra]\'R.UgMc>uJrIGh3mc+NX2kb_W$&fgb+<3unDia`'k2T)qCm($im@cfqJ<0qd--]>QF3Za4(Bko102l<$oIP/581QEH^N3B72)/B3iC0'+1fn.>)1k,o"A2^nU+hDG=k2"KKj.$=E=TA`6,Vg?'*\8i'%/5oQ:*X>!h,Ge?ll^SfrDqiS1-O\b@-Er9=drDD/a9^D$Q_6Nl1\o/n_"LF?^(cpBAisb0V/?U($CapopI1Z\ZhMHnKX6oP?.6D^$g\'^L'n=l5feMW`cC`.>#Q&tJWL5M&L%mL2kj^,M\gHOs;>3ANrNsr9GFdBH_u=G)30qGT>=:2nMf?'^cN?7cH^!pI[AqIDJ]Fp74E_]+n_t[Eh_W-rSk#K>"N#T]\CN%=4YXP*FL=B(FGLM6KcGAu'?O+DdDl7n>rR5*"lJt^c/[#75Ul.mg'2"t.0lF3)N7NF!7`qmLWKE'Wd?m.~>
+Gb"/'>Ar7S'Roe[&G"6RLfI;r"%.XISVIX!\qpp.sg:4(+q5KH/dg`-c.4*5jc;-Ml6hYfl$f+l?m0e"`WWS91U4.X*P`#%t"F"aX[Xi53g%1:PY%NPL3'Z8_:=FH+o?+/QD%Od(YS93dVta!!me>g%2[l@7]M`FM&T!X)ru;KKB_h?W'4ZY&bt\"_=.@3!PbfE5ZCJc/1L@jVMsP/d`[7M1Ku0Aab0\\P\$4J4um%/QXk[A,c*#WCt9k+M?;RRYMAqb0h7pD]a,`/>ph0p752oK.F%A\V-XhL#-s+bjVu/u!_JQVOqIjU,o-3`,CE38a>\BU,su&!p,/,rGgC7*Q+eVC^:=0"=\WS+g7pR]ni5K"F2Q:nZ4bk`h.Xg.@Xbh(l@O.$_9FmW'jr04[R"i`:0?K5gtcL1s#YLgm5r>:uVaTp\G?3.\L'L_"/^7SCG+%]B`WSO1(]6FX?0*WUM;AfuH2Kn6p:),3'"b$Z:KT^j@?Gh/W(%6`G-(-T\BnS&39#H#'Cb6q8Lo0s!;VHeHIrKELPm\#0bngl'?$P";UDqKc]RP3?Vn&GKg+M/&G/ddrDqjJiC76R)&gG69A^f!L1j,]]6FmW#8V.lFA[6[#&@G[H"2b5%^0laqa]"FSq2EOpD@BY#d8`G;ED&rJ-?G[co-GNE$V.g!9>fWVs'%3&K/>\$V-j@if8WOB>NWc_3?'aLsu'*es,Fer0d!>3%;(anRV8/MbOrX@t#,gSn`;l*l=M>7WkPHb),0NeI*?u@dG'Za;jNBQ&7#kt6-Hr62.Kt\AF>#Ki[7Y/[&pe>T8e7N]boLu]2lu7HR8%9K]fXgh5pCB[eD1DQ<.,V8BWnPoMGCs"pSGuH(\UG[Mg4'Fj!"*eg^9)i/K]t)K+dijT8b`A@Jo1%CaaH6K'G)&NIg6ZdU4?l$iXKYRp&9h%i"Zt12LFJkM?cn"'6O!\am>]P\)d$Q$Z7X;KF"'4]:o#L,dELHH3bD@lr*+f.U.7(qm,3Tg!.gL:06C8qe"mPudBSJ'p`:CX9G>/`_&?Lqj:o/sE#+?9[\N;C*@GR7"X"S"o"'FPtpa;,Q9)?JI>[jn@VCHS:3-0?83J?6m[,ObgIgSC,/XATL15!^^N$&%!hO'WZ.r_$YY0li>ukmQ[946=bn$)P6/abPDM,j/E0O$5Koc)QJWq65COlBKFFej.+No_R3k-5Oi!34<(i;c5o2gP-gE-MX4I[\o?MG>ad-ACD:>khNq9RcmIu8Z.tAtRpgVu*%/%eTV&uW-Vi#^ht(:QNjLRfHom@7O`-GKH5Z:(`lRDkkLd$Yq#R#D#D##G"&%\ZjJ%[d8%L]7Z#Xlip!YY2b1ul>bPj^iV/V7ruE1#Wg!2elOahes4"1B^`))NGAPP=g!G>rW.n'q4%~>
endstream
endobj
90 0 obj
@@ -529,10 +529,10 @@
>>
endobj
91 0 obj
-<< /Length 1637 /Filter [ /ASCII85Decode /FlateDecode ]
+<< /Length 1680 /Filter [ /ASCII85Decode /FlateDecode ]
>>
stream
-GatU4gMZ%0&:O:SkcG0V0V[t:Jh2)/HBCX"UlDu>FUQP/jUft]d3VQe^8,;-6\Vnr(-uc#,%o10cWmD%bLo\7g%,VV)ufk[(>Hp=Jfs!DShGP"po]T=hmI36X_5Do^7=!:KKaFlo#l`*@>@'MAi%'VAb/-&@65*+I0TqaB.XMWO0cGRV6q[c^mr0CnJhi`Zh@^FS'S41G3rQJ\RV>`:d6(gfr%(Qol&jZ7]jfLF.7lg\o%rU6KY-q8QWfmXI@>ChO%N9\)_ij$/D@U*J>h=4OOTlB`aZ8.6:##qEU'3R81Q]*9$ttT)o>dWTaek\l5Piqoq9_*H>P6SCYtPi^7@15GcTX+hAmu,jE]YUA%Vr^W[DD"En+l&E_c-D7?$j!Ga?(Vo?t<98B+$P_[Eqm/(46Y/G3#GF`r+R@13V;+%n=\;310ja^"f1&UWfrcX8\Z`r\Do[uOeJl^0n@,UPclfr/KVG_;`ZDFNLAGp&>1c8lLHL/.[KR6MYqobrOUJh4W9JBDq[=gs7H.;#E]:4"k_4f3gbCbMW`kJLo'sF4*=jZ^A?)p]X>K$rS2HCqnA*L&kmH8^JB,;*^o6/65*cmj]]=J[$[]j&rQ\fWlQJCESF)mEVT5aiFY"\%L6"f!e*s$$T0k_U(Iu)6>eB8A%kGHm$\R(8bF1u_[m[b[R'$cZ"=M2;4<42Gn&N&lM6Hb'@/V`a+`$$?5-as!YIuHh[6U9RZKnaPKG;RtGkZ6T[)INsc6e^'PX"^'>YmnB`XX9K%a*#Y+dU=oaBMu5FR\+a\H"G0f2^]bbf.U3n(c>4d6kkU7d[HhhX)A_FuXC`EN[jc?C:i[pH(OIESsFfBlTREC+dGW7*c#cnpRkV=IH0MV+Q6D#)Pdn+020Y"W$f@S$RdUJ;*j#:PjZ0f:)29OL",C5O\qHC7e:f[Ch\7Ip@q(W8IF2)QR!;7\GhEQe;>0[@?UoNA]s=nhi@/U#(?NuP@Lkod*q]WgW;<_'m)J`qrclD*6I1F*VgKT*JT!ui/3*NJ^8\PZ2=I78X<'k0Gr\'S,KI4p3SIQ[@0!slNutF(h
+GatU4>Ar7S'Roe[&Gi[:8/U/9^sJcljs!.sCl?o3\du/93Q*2jTr9sHpEM!-3g<2`h%1hi.IgY,Icm"mX2V9C`T+gV[ds19,'/n4`,R@.L6;=](&8/nUVPj,fe!,-I!YHNOC]gEY?rq-a7JDV]e=(gd'R%@curU/mfdFi[NWVs,M;X:6`0=B@.4qG"QcG*!E'k]Z6hHhi$iQZiNBR;gi<$U$`I&HAG(ZJh-'\7pHQ_q3;S^-S@#D$W-A:Dbs7]8HR\MUnLH#^'th^Ya2&NATfNI`;IG7YM*QSp>13iM2gBkk>lNilgf*`N3JWNE$Ha9neZ==6$;uLL+l&$<)^0DnLm+A!imORu[OK;h%B0IgK,pch8rm?n?JdXelOQ]Ff#i'F^::cN!1833Q1.h#FZEBtKR@B;,N]MS)aX64Y/(&85BI.=:%fn$'PkJDB6E3o4HZWI@KsFP.[arc&d#ok%A1p]Nr:O=$@K0"+#$W;p5H481^eAgkn5k(Ib_.]NM]p5T`,0nEB"!%!Gdqlo>m?qD>0Rt@,luEFVmg(1^UF#rd)VRX]^\Qc`Ut/V]ZVCRPrMC/S]I14VP)HSl)52C?K+Y5n[%oJMn9DVb%%Xd**!2fgMAOk(;`d9OZid-m0eCH!/M",b-\Of\6tB-cBW`s1q,>0!82+GRt6'"&&UXNA1DGA:X]`)%$9#jGC21265!$1Isd,R"NZkIE?JH[o$#dL?7?4.i=&<)ktqVeNaT#<2>3fZ;ABo$`K4p&WVPKm+;EnoO'.H"cY$1D2Xr,a"SK,=c#1@!,KgZF&lf.)-\/Fj4eijkQ#=X,V;CoO/'/`\4jmt0Y,/Xlh2=B5D=oEX(4EWQZ9WpaD*X*Cf')17b;?S_I_*jC&IgT1-m/g!B2O%rG3Z?F$G[AIC:eli<:X-WAu^o?:!R\FIP>`iKph9*=D1KZ_67h'U@SP>2)=IV-`6cNM#/?*pUb:)j;NF5O?4)2ea4,f:\QYd2rKU?rKlsXak'2C8S&kC_M>:aCXU9qAGg_%2X'tHPP"-+9G3R9YqK=a/glXmFeu4#oDNZA]SL9s:JY0(Wdf[2I`fbiM%5[5,!StV>)n1!c-;8Z$Bleu=btMe@.bUdX6]@Di4%kZOY1^=b^:$##@%t:/<65WPR&7jrlfO=>ZQcSY"@>'acF)Kjh#CmXU[p3=9/!iofXhE*cnQlPY
endstream
endobj
92 0 obj
@@ -544,10 +544,10 @@
>>
endobj
93 0 obj
-<< /Length 2091 /Filter [ /ASCII85Decode /FlateDecode ]
+<< /Length 1873 /Filter [ /ASCII85Decode /FlateDecode ]
>>
stream
-Gb!#]?#SIU'Rf_Zd+]0a;+,i55R+;3/lJKt[i4#=]E,B-gVdXMV;sVhY9,&nk+tK":=Br3O]\EubBj`f4hR"c:IjlNUX(/q/]HWE;<$5g'o&FWmg&OYFl<(=*-`5HepR,Ukk40@NYhb6^DR7lElB]\`Q2a_3T>[mG%BObU#TA+[Ir_%Pjn@5PL#TH[G0?F+@X6u.:ibH6oGn.#Uc&,Qp8].>,7\HOqp^DQa(YE(,f`"Z!GZ^[kFkuXQbM3CEBe[cF(,4I7s,<"'_Q6ma;/_2eUZ5[]1'&4Z.ajA;7>s_9%uWl'!^rmL"6Q_7ZN,2TP_fG'4qa\6?T&U0'+N5/n,'"8H4,,1iLoc/#qYOPql2?V^.2HF'mc4t`2`WVgG$"n*/fYAZek%Gt]+n%+7^Fr-EeRng))),HnPRlu)7+i,@&Tgc>#dB^"HeqEj3s,qSSuQW3E/U[>"4h@Co=4Dfe+fihM&OEjX[IB?77Z8"^l=ZE:%@p,*8uP-9qGr2_^Oq+oOmX3iO!<,$#eE&57'T[e4/4']BQ^LNAuTrJ,(8#I+Aomg]o>_,!)/R;'"NBSkn4h!L=;<[ao!p]hZ&PiOt>;00ItY>F4Vi-Wb`Yi'?R]6stAO(4To6b+"dD[d#Lbhki7g^h_DOqdpLOnp*MNrk`]?]/@acMf8LQFAPEuS+Bgl0%Jn:u/8**`ZIDX[4:.A%BX;=FDg?^3<'D?5cXm>j34j4hiR-*H8SGMD!Lo9$i[%\'VLR#/[U][:G?[W`\7[-1$,fd<(!/$[pWY4F'Sf^ZIU4V[#]/jGn@F!JP^W"`HX_6.j^.ol+$-9sP:+lg,L(j4r"gCG4f;NW$^jm@.at3s[!`7L*0HcV(g9CYl=H,.WP.]6&MEnS3ZD,4C0Im>7i"$#[*eFE4\i;/39*S%G6f4#9a\W'H]I*SO7`.IsMNWG!"=&0j<%5lX77BmskF=);U%3FP(TJ4Q9VdGidPW3*j<)U=iIOopJ.E!N;@'&fOSTT5<-Um:SdVF=qT-qjKq[@q)%%F`;nbsS9Va"b%p5_WAB?"c`QAJ8nDlqe\q4?r'%?8lK_qM*"C2W&U1ap\IdEXnoDm_pEddiPAY[[b.CY.&[F2fQYu1!`h6Li+2(6,RKH/IYjhc901IZ^qfF!q_iH\dl[UStTA6q2lH!Mi[X1hPT+ngrPh>[)a-FZ\t>*BAIHOdkp".3P0)l-@n,lY/UqB1`%&7&2UJ/Tb*lWmd4?rId&Ce(-RSohKSDB-0/ZruPfTGDk*Q9VSF'ob*YI,M^O%,/=!otdg-O(45-0DA0K9:?Fm0'H\m`DgThpS4p[iRn'T5$fX52C+..k;@H8c;M4Z`$ctf@+MX2Sq>mo/PLTYEhF]W,7;:dDug;f=3:F^9$E;\J*XnY_VZ!DG]A"FL[IakJXjiB^bKp0@e20W&l+k:a/UsG[ZS`^eVb^ML>LI[C4qrbnI"ugkZR"!h*Rj+O_G=1bmAW,(+ZfV7*eT4tYq@o9^I\6]gf$u8kHD)?=#TM8$UF-$eug4.P5ZI/~>
+Gau`U>Ar7S'Roe[d+]2W;08.1Zn'^N));=^L)Sga]E,<+fu.FLV5UoWY9,2rk+P2sDS*"V@Yb`?F2!^u7dA6-o#"r-@H'@anc.W[m^\pQ,`2;U@ekBbLRoGF$otB109\>e4T+n*G5OV<=d0T'S`P\mhs"amJX^nHZe.=R?bQIIn(qV<]68(DG-.g7S*s>:j\%Vl!Bm.A!Kf7s9\$c8)_h9SAp`mIDu;Dd?QQ"%>LE8%ZhS7-B^!&?<4&37dhJt8GJ9jJ*CCodQgOEl_@_.;W]uhOK9a/NO8e]rH#;'NpY9.A>I1_N,6Z15e&UgcU05l`pNe7FtlM01LLalHUO1Oe/ub+"182=,[c'GmhR!;T2g6bSX4eapQ'`TfQ6#l<+Ate1\$##2*((!\N=G$-R-#&EP7*6p-UKpL>n&Q]Mo6g\lmR>>g:d:_FV,\JO+Z/i7[.qmdUOkd:WLG[a#@V40'86KeJ2(sK1&nnSiHr6?#/$l6F;b.UM>9M$J-4o6qnr8?*)Zmed.4fO56#D6Frp6Z!HX_RJc$e\-]8Ua"2c[itLn9[^^^OCJ)OI;Q.$B4s(#jRnLm=8Z^q!t=$.Gb0,"mK"Sen[H2PsZ-,=Y[K^TjhXV4to0k,2TrYU2mm8!e/mW:0[Z;k`(^,OQgTnH3MrMdh"X?Hfo-5o6J/ROR5=q+RL!V89TQ0JX3u2/r"pE/'Zb)L70*U-.PVS2JAqs/IHEKP-\)2L_3J,dP&qb,XU4WAk[PeJ?:/R9$GMA$]XNrJ*0De2.sco^jJlP-SrE0dUF`C/.2K2Fc-9:K9BbK-#_1Ag4E$RkY`m>m[D2qXr(?hr#K-:n$PVdnCR4,(,Qt>$@salnARK-f-%'lX$Nac=q9s)L0:D_dkGXd:%(Ke#%^tKIk?5[&W=r99+/(k:jXP6.27f(FF+[$l$[0%$[02kKl1G!T&$M,+n98bkog)_=mC,iG7"j*\9.0RZ"[c7N[382P!=W0tptDl4kU4\L;!i\asWt=s;i<@"tm-"rnGFmnh$#8a,Aj7b8-`=BRQ;_-L,=gIepVf@d0U!Dde';,R1L<_fB(OL4Z01ZVUO"?"VNoPAe^W,9T5K/p/`=db\6Qo>9"oh$^jED^ElcYGR!Br>^>bP`UFK0f;?uH2b>QGF(B2:X"0jQG2tcN;^(Q1k9:/KYcZlf#)g4CgFCR7\jFu-&dZpJP%F<8d'!oIPD7XAMjh-ffUs$7/6hg61GJG7R$#`R?HOtU66LM$c0Jh&%D7u-Ft;]*RP$V_cIFis_o$BHY`IiVIt]aL?u)p'`M)Af@YNIESM\G1N>jddH,lH[j(E3:7N*"fmM7VghD!e&REqJ;rgg.R#]*OXd2jB%R`0>,e/j26WgEGCBmB:#q(m,At,Sk&3"4fJ:GX`\&-Fr_1lEk)$\j3E65MSZ205E=QF&j*Ej_"YIKhU:49_s:%//a5qA\-uhR[0"ZI<9mq\>m!pT[boPsmgmgXla`c".GDBH(JLkZeS&OGTIoGAp8%+P"EXSCeH_St~>
endstream
endobj
94 0 obj
@@ -559,10 +559,10 @@
>>
endobj
95 0 obj
-<< /Length 1690 /Filter [ /ASCII85Decode /FlateDecode ]
+<< /Length 1913 /Filter [ /ASCII85Decode /FlateDecode ]
>>
stream
-Gatm<>Ar7S'Roe[d+a`"AjfeOV&3Aec!7%mL28U<;YPa..%>`<3g:=+q=UL.b@V"_?mhjt'#PNNV.an@])ri:3icENl?9k1RgmWEf+OSW8kX-uaTI^2^kobh)40R<\*V(MG=kL/l67E0crDcC!C;Mism%J.g;tGdZ\QYYIVbDcfl%kgK:cbeG3u4iPM2e\77,Br:.(BXM2P%Qflra'nMm>`!UTCB>!7rQh2j.O.aU,4AoSG_;!8M8bHFAs,Cq@7E9WE3>XON"J2j'#so=HfQ;49-Je2Nf.,bN-QdVGi?.IfoV]"TIC7YBHSF))gS&?09M>R?/28)pJ5SH(3p[f^a"(ZV7p28AO)FO;$P\*!jL(&oY1$Bn2];0\Nj>5V`QB:.k0,[,3[*[(*"IFF\j772RG-*LNUPK91+!%?8o9-;7"AIt#kPu-]]U:3[=67XYNlE/pjD8HSQB`Qj=h6=ru"758YpQf.?J3OJ?IF*;b+EH-K->/H?T[jF2KJrC8\Ei7D`aB;b$@&oUeLlPg[k&+%Asr1dp9t1#@h!9kpm=gF"L`"10LYRB,FUeXncg+cL=QSkk(h4@uumAk%W3NO:W]9=fC;Be.jC#HO1t/V^CUm=`>F;&m,FVtp$@DSCrH7uefqNrAJ902=ITnC/tYf?Z9QVs%kOOK2OJW$lP=)S1b[5o=s>M*j[]&-!>a6Z`5nofdFd'BP&`MQRCi4?#[\%sq.TqfG7?"NOFT'&8NbfYg/P"/mbdeZ?PEM*gjMYgc/r>3XFi,ms\=8aFcmcHDLk!5IZuodgT$\ji,0-D]\C7ASNVA`)<8r8UkJ:Am.dr%9/4BBX@m>:L8J1:,4IBjP!M[4GSG'j'jRd*Sd2$DS>f&5@L%kWtXCBs[W(CX]W,-<9A<@n"7`J8iiDJ\>+BH?\$)>M%#R@"$@%p\^l^o@;'+,32,,qlY^eLcD(88aOD:hqtocD68h,LuL,XS;V<._?t^,U9/;P#\uO#?uFV1U:AXg[@(cQHE0jOaZ`U&b=A!dc2']Ea'o]@6:tc9p/)ODI2-)Qr,;Z.`blUW.U@=n:V\e%'8#4o30CBqYdaOCZ$hpc[;LC.7]l>HJqoWS]"tW)O'fL&Y[4rU(Kn0#^FXIg1Jnr;4V[6G=e6.^Q?NYdXCUmaV'&M4$T`BKh>~>
+Gatm=>Ar7S'Roe[d+]Nk;++"*AQW08Vq/bDSSCPT8F67\I\+J?[G#8"0MgXTbZ)9OQL=L?:Q%g=c'lo)?$jn6^B)ti_WXdAY*fqTI/C954gXuB,HA5*Ed@Up%dJRE/WGV3#JY*;PcSb*aMGdi*c'@A$u1kKpnZ$n2SQ?!9J+1L#P!ko!_)omt!:[>+]rUt;5_kQ!CKEYX8J=&?m;M?fM<")jA,l,o:JTg*L2lKJLB][W28n[EZ%E+elYq"=UXYQNm*UmM&5_SF272cF)ORAP2'+E>T3`"!>W!b\aa/1e_/-O^Z;B>Q+n3$jqj&hji8-SMgNV6ODB4:l1VJHYi7HGKTK(#DEW4H_=gWpYhd';"24R@2+8H#i0S&5u4DSUad9G$qP&!`<'!dpl<-(J1*5+jp8uC\?(-oEsIRIq9:$IYk;^3_KKrtOGbI%j"dQ-PA"6`7jCKd;=T1!IPZ3i"ekTM@Of><.*Q%NO$$$`):,M5o3=C'H,J=qV<2jP79lF_-YI)Mo_H$\*"Q6_I*k-mkV"F+0a"u@K>S1N*c,7Y+V(WL+TM^NFL(KKU_;AF:%hPkXEXt>=Mk9(g'%:uefaqCf;)`0ot)A>HUb_,\jfeA7n_2Ai/]BEep\Nhon>uMekmEc70DdYgpF6n7c=b>AM]3M+@6;,4l_7_;[OA]VL2$bj4H#q<-As4VZJ87aVbqsDa6$XQL9cJW%IK=3KEDdC'LRP9'a.'+_pjdCMKu%]KF#Xh=XXHQoSP5%D%^PSHKs*,J[G(Vg(JSLr?r!<_0*tPbkcL%bK2nY]B8ocb;mN3?c(K0OUS),Srs*PfVZ)hWMI1Pm:WV]>+hBUh!S&m(ssaHe$,e"IFWl1%RQl:.o9p?rW3il<2HJ"8hA]4lqh,a8T$)0!F#:RnT=*>.>-;\U;uAbho6.;OG-l4&8MBA^!m4R=NI5Im$GBTX=&\t@Q_be;ECDLbG"_XC%sDS#iKSea3g~>
endstream
endobj
96 0 obj
@@ -574,10 +574,10 @@
>>
endobj
97 0 obj
-<< /Length 1852 /Filter [ /ASCII85Decode /FlateDecode ]
+<< /Length 1937 /Filter [ /ASCII85Decode /FlateDecode ]
>>
stream
-Gatm<>Ar7S'Roe[cs'ZrAjfPHAISj>>MQ&WP:Z7P!R!1<2J!8X79>^pl)u0T9B)Whg)a')WHBKWn2n+?L\s+P>u!oI7bCkD^JCWG7BY\J^A?_seao0U&:'3q"a=RR5=Q_*:7qVb5C3+XKK6Pg2,-PX4j-k*Yd9h@#kD9IRBE*qh[tP!4(D0hGo,WO+O%b;s%1D_'ef?="9\:k9_2i8[>aZcXed:shrZ+9j"sgnJ>t0L68"/'<"&`d9L&95;iJ@)q*gTT=!RCVa*QR^p\N-Zr3I1(dD,3r_2He6>(@^(lUf7*L&@C*X%)OX!:1oX!pHb(XEFO4[H'TekKEbp4!2nm_?d],c5fB4k*,+pduuldpZ:K.JJU'Vq4LbQ5[g_$)`O_#Ji]jIo6$W5!aEXZISW2RPX]qujXc^oQ:.I>T3(9)V8X/4.p!j-'"*)qF?K4J;?PiVW2NY)Tf]*Bb!joZRnZi*,,^9\RY3-F=]VMj&l`]Y2d/gV2Tui7X`UAFm(e)FFdn`0&cOXcckMHb=:R8c\%h^,-5il&W6d(poYgE&rRRN`.D_$SJM@GEbkHo*7cnb*AiKG#`%5rE7bj/R,LNn0:l)KCJ=\\WMN^]O2Mi)*=2cQ*h\DR]!UCW&9VW@31DMh8]nbHX8Z?_gpKR^8:7V^mRk2>Nr?^!8MqU2%JA90FD"<]d%>@T]"Gl`WE(bQQt:j8scT`.#a.<9iA\BG!Ou#IemeE9r]PD$bQEslrDNPLoKB[?_4Je:%6C6d!%'>\.AVsQrrH7s9:D9rspiVcY&2*(]Nc3)UjSCoB__J%&-E>gPO4?f+S6#'=n>iqWesgIl3U@N@5SWHE6:j57G*cd5Rp":U00HJdi8:XQjaUY;MD:"_I3HY*"T9l:6&@$4A-U't](N]p^_KqM(\d:W]B+-`Dn\C='D;3<)'VJckD?@aYCeAhTMDLXKK7)2`1OA0&dKHq6;\l!UJPiiEi/^jsJX6!DhWEFkWrFN7djD"T\taEG\BqOf0(BZ/4V:+9$#X29oD0[mHrlR\/.i3NZgunu/hlS"0bH3n*;ml]bUS^OjaZK`17I?*Xnugsm2fBQA1gj^S)T_r]_Qe]ftV'(,/B3R9u2$1_nmVG(WIhgPsq58@khK1OmsPU3$'F>5;>_f[j\:8iuN?aG;-=%o?c$/MOHW:d.*7tFI/Xkg%_+a*%r]pU_UWI@_%$5j7Wh0.B8A%,(8L4!8p=@Knp9>,Q]F6'#KBHZ3P962g-!/n+oiuPPnOMGAaMA&q1N0.&_H]`e1fHK!3WBaH]aQ=bm(q01T@h2\-b>"drm[M4/#tb!gu\f4R)!2H1!mBSj`h~>
+Gatm<>Ar7S'Roe[cs)[LAjoSHV(Dm.>MNfR\umpELSbTh:"]Y[d1rK_qWgYnP',uM[TH/H9fT*P9#7UaVm.a)6>Iq5$ccGpEl1X4rI7p-;M)'m%',!E$H@Qb.]6E:*B0]c]2ah"S)/ukWG,R^hn.2VYH,;chQJ.iXh#d@c`NYism;Abl1;4K!W!(YR\`P:#Z%=u`Me7>*P:35hk.F7+.-rtjc97?mWaik*H:QaOenbKVl!!IMZ97j^N:i)`pjk\H[)`a>uPk=$'TF(kkTljuNio7k9n*d=ZTEua\L0&2*Ht>plKjYW#J3=1U1-ZRArR>[B]Q`q[j2D@GJ.ekSQAmF29uD(/_"2'K(WhV3i*W41I^^"!%>N'"o)m*G"rBTh3`UYNLdG-C'M(&Ki=7E:AlabCM7#-W(#'^*g:?Sg#H*iq-,18%=8D>^>au+5_CVC-uuo_L8fuO`+3s(Xq$SA63YBM#@Sk*:+f.&Ht(?0?XgJ`=LOU3_W?&6bFJV?nGTgl"Ln6pL$lc]BDG6BkC'"aA'9!Q$KUBj(%j?bgsfh$:r2-?:@"_=GQQL!]q:+(6eC"OEXX4s)3L!PYBS'oYJf1Bm*W6Ijf)etu=h(8Bc"en&U$g2scaWFkUVc]d\@WYk-^.nm_*J?F*Z*XoR,bh*2*n3r&IH>Y7mXRocK\UGr^?0%cGBR1Mps'^?CC=kZS+FaUfX$gjdlp7!IA7TXg9662BO=`VAGfrr$sorle$c-:SACh*:AaBtqqcn[]/o$OQ/1IUX&9W+_kBcnI9:9S"%27Jrh;(@DB2(BQk^r_Oga)U1V(\/u9ZlWE^*!!fs(6%U@"h!N*PBP,CJQD?9AU+=.7[o1"rWQelp4'rr+`1I1Y6H=WhRET)X[:)KMP[Z?0_YB]AI)mS<64hV^iK(=C-@>a%eRtG]mT@QYE:A.D=;7FG8i'U`;]FP5PI:^M5ehMaF5tP:XVmY*K,H&Uk*3/I5VK"ehCJf@1JCB<_qor\]`n+nG!/Cc\![=ee$5Pbs59^V[]Bq^b[h#oUQ__9'ZFTi&PfA>JB[MlQG7eY$HAImY"hrQpMnNF_"Y^a/qtNen+i!R1CRo..egcn5lfKmT#XFYEC(9%FUq:6hQ5T>r.]&/!qj[s$olgI[@YIf-lg0jL5u-27%fn)eH*lAi6XspgquG(J0P-OT\HMi_DkLL_#L$eDVqp8.272));$79E7P9C4VO)H+83#\.08?F]q5Q5to\AeAKH_>%,i0X7',p0GOh&:fHutP*cT^OF`$m=T'Vu&YOZFgBd7Y\s\E3*o4gmH.7Q1<;RXjGRrn7?VA_)X",Yn4U_3N+Na$=/$mqgsX,`"epmbBO6lq"fX)^X^,nseDuPra3!+V6Tckjg@!GSgUu*t=uJ#?[kAR-k?rpm;J[QB93"ta`s`k"kpmt["RaScM2eAT6~>
endstream
endobj
98 0 obj
@@ -589,10 +589,10 @@
>>
endobj
99 0 obj
-<< /Length 1313 /Filter [ /ASCII85Decode /FlateDecode ]
+<< /Length 1492 /Filter [ /ASCII85Decode /FlateDecode ]
>>
stream
-Gb!#[gMYb*&:O:SkV3*QQD?o?#)X,>VI!eqD6f#L0?mt"g6=2)Q<]QpjmSPI:`RW@';I4=^k%7^cC>ctS09P\ak(4sF$cD)qYWOF@>#ZYpXObSf>C7--lKgdLNQ5VOe+#iQqc1?]G<>smo>8AQZE\+N4oYiF@JD%f_A=,n)KPOrRlPXFt3UG5HS0idID1$4;;4o4.=C:l8OpfC:p1oC4B3_q4IR%?gFcWInqX$%IWaiZL406ZH\fROoWs>E=eO$*$"o%7c\XW>oTjCP[*3ADU(;Q6a;uX`i8e3gYkB$jW[2jhQcY/M4ER3Y[0@9Xjrm*7F^Pf;i&(e;JW0K8C<&`p%BAfj*\TP"$6VB^\G'Or+];X*e=i%8?n1KnL<^(5O/&%:RSQ5'+^kW_h?J0!*VkWj34@7rG+`"2Wgf#upc^gJ]34(LHs!H(C_tHV,l.#.C*[-/*#/QRV"$O^9]6Fj"V$+b_PR6Fu#-+0f$0Y!>(`NAU>D3\5)N+Zh2n\'3$ptoKbgbO^=A;&7GE6)&f&Urg\%-hU\o1AN(NQ3lP]JpDhUijbeM@^2dN6#DBq.)7Hhm%N4n'(+07nW^r6fDa*!lFJO:KSYQart6PCifcH+$DWYY#I/b4ep'<0J.MmLLpt`b##Y304>sPC.&\Z#H*#WR60\E++*]2Dp]WH+Bi0R&WY/2"DVI5a@Mi;ZQ594StS=/6^R5oCj:d6d"eB?s0Xijd+bYlpu^s,,WIr+1F$5%b*3jF7r'q`DZ5QDTsiSZV[F[5)Y,h^m9)V!F_'*`im.HAW:STRaFg@uMh:?H.hN)3[7#VD=kg4#7D$6&YRl?JGHM#i[2@)28u^2"2?0?o*OL5''%dAUlVGI`qJh7Cq@*,oM@nK2>$r6o"Cpe;hpG!84F7LHL^FE<0,&H'tck1O%T^>9hY3"d$:Q`=lT%PJ$nqSmh0s~>
+Gb!#\?#SIU'Rf_Zi*ui,N(B*-(lA@];AC(\2G7;M^cW#t9\BVdd?S5iq=gXJBO8hjloc%"!llX1aa8:$\VHtE9L^*OUE:_4(@(L*'RSJ"5nL!pN7YhbSApq:*u+i?NrC#H3&r+W3!.[_#tKZK#Erub21n$a7o2:/#<;2iRV^>X(Y(:C0%$%Edp-E6Z(BuKoJ`6:hAbNsbk.R?6B!??^R0Q_@[e-I,tq)eM[c2$/P=Jc$Xid0#W6X?3b5sR"[ci%Cuo7ZG<%?0`F:(_WZ4K&(oA4Z64=F@3RUF.(I)[mZ]""CaFX"hr7EH^fqi2/:.O*;ZH$2Pa8?_"R!4F*6HaK$@n8,q9=6(eOdMNLa++X.M]^V#VkJ^!@2"$g%.Q6Q_515jO:7Y)M"C)`='HfU5Q)NM[d($e"&QeYclk/E!DFgJ]aC)cEBoC[=fDJW^p1>s3U(+LEV';uNlSnd>+C&6MP=(OI]"R'PNAgAq,L!4L/VbKh%]\qN\\n:r%.nqs/-K&,>aha\2_9!)mhu=W'as+V6l8YA!V>mi'sfKe;gPP5NIIE*c:N`ru!C7%f(PmZF4f5*g:#^SnAm[4Hg0PB:1CWk9FC5J?Y$W.e8%'71J-D:aW&U.F+TJ03oN9I#QaF_2dRDEY\jWbo.`(5=dY!t$@7co&78LP+od-gCD;3gr<GR\I+CLN+.O:YX)dmeWVBP!Xoa=WPhDjFa8KFL1XFHGgf4)-i2QR@_7W9e(VPT/.0WcrbD$*20Bg9\?HLBWZZoq!/mr'V0_6EUd1`G6tBT#b&HSGc/#6"e@`G/3~>
endstream
endobj
100 0 obj
@@ -604,10 +604,10 @@
>>
endobj
101 0 obj
-<< /Length 1805 /Filter [ /ASCII85Decode /FlateDecode ]
+<< /Length 1696 /Filter [ /ASCII85Decode /FlateDecode ]
>>
stream
-Gau0D>Ar7S'Roe[&G!+0M]%?aFX`%H903q-MDe\Om@ics,#bp(=`ee+ls`2.Ua2GmaHW0f(kUBe7@s+A.mNPg%M/6X*^@06@O/_#8k'A:`Y#TN.C%C$>p7!"kcmBf9IPYK"6fjMW3jIFF[et1t`t$X#7Yu&1epM=_])7qm'sFYgCJ%f6Qdb274o"9f];!$j@l8WskN."jnh4(qB5@M4:q5g&mi_O\W-S'Y][$$Q4fj"+PY!0]dqQ?/4o'NWi$:+Al^)fleIe$*n`Q=iD9_YGjcUB'Fecg/'JB+tS8&-W0@@i0[t.U'=+3__Up%f7Roe:O&T$">@j9BCQU>-h2f0p(nqWkV?GC,>DmZb1a]:&&H*dcYJVH]LW1J6.K!d'OqDmc"!^F)(64g^)oTWn])hH;dN)@,=.u_DEVG[VimpA,%0RoBp<8Q30,TM<`:.%V`tfMP8!83$j.'2AgN,6f"Re_#5?,@T8+V%$C]_RlV]S>j'/!=Kre#@r'&]sP[,KpN*0O3n&dN"4_UVpS9LB9o,a;f^bc+,ij@\[s"c9]fRYJGq5G?IpU-3?d`L9Y'f;$"ecf5XjL,irm8)7HKh12<$:@+ikO]b8R&1s-7\VnES)DU>b1UXp-863DiccNmih@cVc,`-NXHka3"kPrc6'DA85k@#Jk!;]2rDK7(KEpT]_8j-?3%D"UiW_`&3'I=7U8`ud\:dHM--_@F/RhN9M4:L_M^$e)"Vb7-[C)o)L8),-ZPJAQO#"t:-hcj11cWYL0'&ZI0@)l>4AB$`bY[uD4EQ_X;hu0YqB1_+C5_1K?:F@*tsFuP.XqfhNtg=[]?_8jNSRH0>>T-Rq;gm@=s-gm`&qUINu8`n($E6UM1qD=r^9sET]%Eh3@(-A5Fr1^V+@Aa,_dP5.S^Z]XB/m&'=Th/!3*KTfObnl4+S)+F7+e1detOo=mt0Q$Z=T/p10oeShI"$_-0XXG<[\Mimqd?H%EV*SZgZnDX.u#.^%K1cN*;o#VF)+;8;?KXW97n7RCd>0"TaG]T3@TMRtMT&C5PK).\4u2XQOJIU@"q96)tfN>qg(d^faI)D*jYbcKTm@4%@GV8&CpSHlk#H1+*,=4)2#62Oo3,<#ES>HV-g#@Z?r.6)=0phls\[RGsn,$TJ3rjgcG>\goJs'ed&m@$.&X(SEf<_>~>
+Gau0DgMYb*&:O:S#^L+kfSiAWM]tU=ej512P"c(o1rVei.9h.bQ$9ko6KJ#*c`:E.&aD@r&M=af)mpNOUnm-bT-d!r[*ROAp_\]5M3cKh]-bEE_Y9o1ZS@X\4t,T`f.9VcJp1H@^TZj'd\,c"WLPe(,T33iE;VP`Nn2ePuqlJTHsZOBT\/%SusQAT]@W7SgmO58I=Ia(i#qR!b_R`R;`U"N:?/#(+VZD5YGA/T/Fkp$&,m1LkY5rK]Q("*l,Z6/!K,#F9oaB.>48QSBrg%:*;DBlm"99R`c+(SYKpA5J7e-B!Y.8#T*(9/P7YlrGA*Z,9H9"TGMfl>g`tlBm.e4q'D-A"glEF,tKEQOEh85UKS,0S%O>2=E)[O?F3!p51!t;$T,VFpu>lZfAaukj3?C3J_!GupoRlM*;H'I]@j5OlT*$.cjn95YV'+`.Nsg(EbNCf7b6+`U2!hs,m*PV^.-9BAj]*r<$"uJ\,64IG49aIfr+=(79+Q#mPMIP"*Wa_A_J>M08s.(Ebc8TUS/0X&+S7pVK6)[f/s3!go'Q'=,;2U&"%V1:[FUJBo*\)Cnqc4Pmm\37%%-'cQ%6u^_O'O:?:F0srFT@AIQ(]l=a\6t^o-b"#dYZgA9kA:9iL9--]iDLFJgX1CC@8F_H9uJ!DYoHbo6jes^'Qu`N',bQ>1!#QBmc$qiqc\#H%I`(?f;,?:)[ciq_?;i&ZCIM#)NGKEsD@Z0u29T$Z`XHo$1+lG;!To6b4>0YJtV(4Sa\PBi0r1k+M<7cQ6'o'];c5k!`knV6MX4lVbsEUWcEb#\qH1j:2[05d1&?[S.lP66>ANgjg(t^U,m"DjXl_C6u023lp)6kXU\[a3XnGQ\!*A>r4k6CU\ShT;KM89iTLL05)BaHU;WMn*J.$amn1!4b1G4bPQS&:;J#Cjr61XWZGlfrE>B30b&`1lr>+5hPc7(quu?80ng,E008@@2K/I+W^^3V/S2Dr!mcb*##0:9?K?m_WOD!&V7hEV&6%GR2K))c8*^8c=#>G[+_g3"7"s-(:.>&'Q*\d>cKS"8V76DLgLb$8=8O_>Hr"bC.QR*KoJ-Q/WPOd_%pAOB*@1;UMu@]m8N=8m;Ubf6_??.C3l.E`t.4]UXO("AV4n";<-ePanG?k@JW0+>JhO]"ZV#pJ`62Z:j=#J,\:cFoIj\/\I^)6,@2L4jTIH$]O3)/8L6f)8uk.jI#f0d952R5(X!/n,8ANd4%`3UKZD3X(R^i^(Ck2uF;rPWl7,2$eeW:^"R8E+$^,,XU^
endstream
endobj
102 0 obj
@@ -619,10 +619,10 @@
>>
endobj
103 0 obj
-<< /Length 1120 /Filter [ /ASCII85Decode /FlateDecode ]
+<< /Length 1618 /Filter [ /ASCII85Decode /FlateDecode ]
>>
stream
-Gat%b99Z,/&:j6K'fsW>figri*kB7ZG\U-U<$"deR2gkl2H>90&GA)u52tO$Ma2Ga;]`"$^t?rj_d2U$-;V0:S>:Jq>+!s*`b-GEc"L:a8iCq.6o4hs)9n*)Uc#51_BpiiBNR*82,VYcBOkSjff^`E[,1fd#+]9'*[$Qd&O1qHGibUj:Qg2kS('[A'TtR&0_,UIMe1AT=!>'M$21=!k6K6HBO['9:0Zmk83\V73@p7[*`K`(/?XqX&S(?7H+2X>R\qdVM&:E:aFsTKjjp?'KIT5ooR@W=3Sk!JQ=@ij<4-EYka-rT>Y.ZDDC'Yn\@_e0)&"YME/Z!&k3DfuPQk)@l@r:L5QnDZXLd:[]D9Kh:,=,d`X5%!E/7f@qd,@#s[Q`Y(b/$e\W^T?ukC<"3lVQ^dPRs9\1XM#34?u@oe&0uqPGM!l%`ML[A^d^3I'e`SDuTe..U(9k\0:WWp`Z2^'n'S7K`/uVcI8["BLuJ1e%LFDifHIRD)BH*-VnTKchCTN5;d(cUVF5h#c8OH?6Kt#,ZYF!6;")$i~>
+GatU4=`<=Y&:XAWcsq[]$q]8D;4uds6&MC<]^8)8#MPngTou@>-p-9m?V7WAThN""'L?1=O1FGC@@$64&*qoH)0'ibpMgsYKUj4ke6gPj^+WaK6]k;gB/BF%[f#.F%kHN\<:-d9)=DEOog>8.VGC'>4_J%[J),tPhHA3sbM>e?"d:V6pWh[AqT$u0QQYa;BfJ(ZSg8g254eS*P931s9$M+Upf8%MZVnBab*?@&03f6YAqIoZSL?aIjB:J";a6-O^+fNbO]@TM]?U/tUAW5N0p2N;RqYG[La"6]6I6fM'DK1*7fl5O?o)V%fMI&;)gs.;f)JXi9U%(u5QCgTb9YgtA[#M+h1lEJ/5!Wd1-5If%kMYp9g2j!kF,pmU'\AcqV(SNR&mUj/TLRO2K'8#+PTI@-9<)2hV:q.mX[*(>ASPdBp%]LS!.hF.ntYIhju/=,#=JeT'%K7oQ']MG?n?76ne:A&\Cn+X:t'6qYlgU7MVAs@5VGuD?q$=8cr1UW!7l+th.nJPgU?#bn*npm>:qFUmWghO.RVE\.$L,m./0#hE'XI?fd'egG!X61_Z:E=\TC"M%Z>&ZB#3b^3%-Qep(EsWCWLU:ag3lhS`bmmB`S4q81.tWYQ4g.&hR=%LZII*p>?N/25_Zp=!@.N"nH99"/S_d6k/=[.j7doViW0HkPRb_+5rT^)(a,j@Q-)Rm'MOjNeW$!2MZ_j/;*u?-XCIhOmq8Cf |