WIP: index support for regexp search

Started by Alexander Korotkovabout 14 years ago74 messages
#1Alexander Korotkov
aekorotkov@gmail.com
1 attachment(s)

Hackers,

WIP patch with index support for regexp search for pg_trgm contrib is
attached.
In spite of techniques which extracts continuous text parts from regexp,
this patch presents technique of automatum transformation. That allows more
comprehensive trigrams extraction.

A little example of possible perfomance benefit.

test=# explain analyze select * from words where s ~ 'a[bc]+[de]';
QUERY PLAN

----------------------------------------------------------------------------------------------------
---
Seq Scan on words (cost=0.00..1703.11 rows=10 width=9) (actual
time=3.092..242.303 rows=662 loops=1)
Filter: (s ~ 'a[bc]+[de]'::text)
Rows Removed by Filter: 97907
Total runtime: 243.213 ms
(4 rows)

test=# explain analyze select * from words where s ~ 'a[bc]+[de]';
QUERY PLAN

----------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on words (cost=260.08..295.83 rows=10 width=9) (actual
time=4.166..7.506 rows=662 loops=1)
Recheck Cond: (s ~ 'a[bc]+[de]'::text)
Rows Removed by Index Recheck: 18
-> Bitmap Index Scan on words_trgm_idx (cost=0.00..260.07 rows=10
width=0) (actual time=4.076..4.076 rows=680 loops=1)
Index Cond: (s ~ 'a[bc]+[de]'::text)
Total runtime: 8.424 ms
(6 rows)

Current version of patch have some limitations:
1) Algorithm of logical expression extraction on trigrams have high
computational complexity. So, it can become really slow on regexp with many
branches. Probably, improvements of this algorithm is possible.
2) Surely, no perfomance benefit if no trigrams can be extracted from
regexp. It's inevitably.
3) Currently, only GIN index is supported. There are no serious problems,
GiST code for it just not written yet.
4) It appear to be some kind of problem to extract multibyte encoded
character from pg_wchar. I've posted question about it here:
http://archives.postgresql.org/pgsql-hackers/2011-11/msg01222.php
While I've hardcoded some dirty solution. So
PG_EUC_JP, PG_EUC_CN, PG_EUC_KR, PG_EUC_TW, PG_EUC_JIS_2004 are not
supported yet.

------
With best regards,
Alexander Korotkov.

Attachments:

trgm-regexp-0.1.patch.gzapplication/x-gzip; name=trgm-regexp-0.1.patch.gzDownload
#2Robert Haas
robertmhaas@gmail.com
In reply to: Alexander Korotkov (#1)
Re: WIP: index support for regexp search

On Tue, Nov 22, 2011 at 2:38 PM, Alexander Korotkov
<aekorotkov@gmail.com> wrote:

WIP patch with index support for regexp search for pg_trgm contrib is
attached.
In spite of techniques which extracts continuous text parts from regexp,
this patch presents technique of automatum transformation. That allows more
comprehensive trigrams extraction.

Please add this patch here so it does not get lost in the shuffle:

https://commitfest.postgresql.org/action/commitfest_view/open

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#3Alexander Korotkov
aekorotkov@gmail.com
In reply to: Robert Haas (#2)
Re: WIP: index support for regexp search

On Thu, Dec 1, 2011 at 12:29 AM, Robert Haas <robertmhaas@gmail.com> wrote:

Please add this patch here so it does not get lost in the shuffle:

https://commitfest.postgresql.org/action/commitfest_view/open

Done.

------
With best regards,
Alexander Korotkov.

#4Heikki Linnakangas
heikki.linnakangas@enterprisedb.com
In reply to: Alexander Korotkov (#1)
Re: WIP: index support for regexp search

On 22.11.2011 21:38, Alexander Korotkov wrote:

WIP patch with index support for regexp search for pg_trgm contrib is
attached.
In spite of techniques which extracts continuous text parts from regexp,
this patch presents technique of automatum transformation. That allows more
comprehensive trigrams extraction.

Nice!

Current version of patch have some limitations:
1) Algorithm of logical expression extraction on trigrams have high
computational complexity. So, it can become really slow on regexp with many
branches. Probably, improvements of this algorithm is possible.
2) Surely, no perfomance benefit if no trigrams can be extracted from
regexp. It's inevitably.
3) Currently, only GIN index is supported. There are no serious problems,
GiST code for it just not written yet.
4) It appear to be some kind of problem to extract multibyte encoded
character from pg_wchar. I've posted question about it here:
http://archives.postgresql.org/pgsql-hackers/2011-11/msg01222.php
While I've hardcoded some dirty solution. So
PG_EUC_JP, PG_EUC_CN, PG_EUC_KR, PG_EUC_TW, PG_EUC_JIS_2004 are not
supported yet.

This is pretty far from being in committable state, so I'm going to mark
this as "returned with feedback" in the commitfest app. The feedback:

The code badly needs comments. There is no explanation of how the
trigram extraction code in trgm_regexp.c works. Guessing from the
variable names, it seems to be some sort of a coloring algorithm that
works on a graph, but that all needs to be explained. Can this algorithm
be found somewhere in literature, perhaps? A link to a paper would be nice.

Apart from that, the multibyte issue seems like the big one. Any way
around that?

--
Heikki Linnakangas
EnterpriseDB http://www.enterprisedb.com

#5Alexander Korotkov
aekorotkov@gmail.com
In reply to: Heikki Linnakangas (#4)
Re: WIP: index support for regexp search

On Fri, Jan 20, 2012 at 12:30 AM, Heikki Linnakangas <
heikki.linnakangas@enterprisedb.com> wrote:

The code badly needs comments. There is no explanation of how the trigram

extraction code in trgm_regexp.c works.

Sure. I hoped to find a time for comments before commitfest starts.

Unfortunately I didn't, sorry.

Guessing from the variable names, it seems to be some sort of a coloring
algorithm that works on a graph, but that all needs to be explained. Can
this algorithm be found somewhere in literature, perhaps? A link to a paper
would be nice.

I hope it's truly novel. At least application to regular expressions. I'm
going to write a paper about it.

Apart from that, the multibyte issue seems like the big one. Any way
around that?

Conversion of pg_wchar to multibyte character is the only way I found to
avoid serious hacking of existing regexp code. Do you think additional
function in pg_wchar_tbl which converts pg_wchar back to multibyte
character is possible solution?

------
With best regards,
Alexander Korotkov.

#6Alexander Korotkov
aekorotkov@gmail.com
In reply to: Alexander Korotkov (#5)
Re: WIP: index support for regexp search

I also have a question about pg_wchar.

/*
*-------------------------------------------------------------------
* encoding info table
* XXX must be sorted by the same order as enum pg_enc (in mb/pg_wchar.h)
*-------------------------------------------------------------------
*/
pg_wchar_tbl pg_wchar_table[] = {
{pg_ascii2wchar_with_len, pg_ascii_mblen, pg_ascii_dsplen,
pg_ascii_verifier, 1}, /* PG_SQL_ASCII */
{pg_eucjp2wchar_with_len, pg_eucjp_mblen, pg_eucjp_dsplen,
pg_eucjp_verifier, 3}, /* PG_EUC_JP */
{pg_euccn2wchar_with_len, pg_euccn_mblen, pg_euccn_dsplen,
pg_euccn_verifier, 2}, /* PG_EUC_CN */
{pg_euckr2wchar_with_len, pg_euckr_mblen, pg_euckr_dsplen,
pg_euckr_verifier, 3}, /* PG_EUC_KR */
{pg_euctw2wchar_with_len, pg_euctw_mblen, pg_euctw_dsplen,
pg_euctw_verifier, 4}, /* PG_EUC_TW */
{pg_eucjp2wchar_with_len, pg_eucjp_mblen, pg_eucjp_dsplen,
pg_eucjp_verifier, 3}, /* PG_EUC_JIS_2004 */
{pg_utf2wchar_with_len, pg_utf_mblen, pg_utf_dsplen, pg_utf8_verifier, 4}, /*
PG_UTF8 */
{pg_mule2wchar_with_len, pg_mule_mblen, pg_mule_dsplen, pg_mule_verifier,
4}, /* PG_MULE_INTERNAL */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen,
pg_latin1_verifier, 1}, /* PG_LATIN1 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen,
pg_latin1_verifier, 1}, /* PG_LATIN2 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen,
pg_latin1_verifier, 1}, /* PG_LATIN3 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen,
pg_latin1_verifier, 1}, /* PG_LATIN4 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen,
pg_latin1_verifier, 1}, /* PG_LATIN5 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen,
pg_latin1_verifier, 1}, /* PG_LATIN6 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen,
pg_latin1_verifier, 1}, /* PG_LATIN7 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen,
pg_latin1_verifier, 1}, /* PG_LATIN8 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen,
pg_latin1_verifier, 1}, /* PG_LATIN9 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen,
pg_latin1_verifier, 1}, /* PG_LATIN10 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen,
pg_latin1_verifier, 1}, /* PG_WIN1256 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen,
pg_latin1_verifier, 1}, /* PG_WIN1258 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen,
pg_latin1_verifier, 1}, /* PG_WIN866 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen,
pg_latin1_verifier, 1}, /* PG_WIN874 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen,
pg_latin1_verifier, 1}, /* PG_KOI8R */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen,
pg_latin1_verifier, 1}, /* PG_WIN1251 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen,
pg_latin1_verifier, 1}, /* PG_WIN1252 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen,
pg_latin1_verifier, 1}, /* ISO-8859-5 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen,
pg_latin1_verifier, 1}, /* ISO-8859-6 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen,
pg_latin1_verifier, 1}, /* ISO-8859-7 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen,
pg_latin1_verifier, 1}, /* ISO-8859-8 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen,
pg_latin1_verifier, 1}, /* PG_WIN1250 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen,
pg_latin1_verifier, 1}, /* PG_WIN1253 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen,
pg_latin1_verifier, 1}, /* PG_WIN1254 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen,
pg_latin1_verifier, 1}, /* PG_WIN1255 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen,
pg_latin1_verifier, 1}, /* PG_WIN1257 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen,
pg_latin1_verifier, 1}, /* PG_KOI8U */
{0, pg_sjis_mblen, pg_sjis_dsplen, pg_sjis_verifier, 2}, /* PG_SJIS */
{0, pg_big5_mblen, pg_big5_dsplen, pg_big5_verifier, 2}, /* PG_BIG5 */
{0, pg_gbk_mblen, pg_gbk_dsplen, pg_gbk_verifier, 2}, /* PG_GBK */
{0, pg_uhc_mblen, pg_uhc_dsplen, pg_uhc_verifier, 2}, /* PG_UHC */
{0, pg_gb18030_mblen, pg_gb18030_dsplen, pg_gb18030_verifier, 4}, /*
PG_GB18030 */
{0, pg_johab_mblen, pg_johab_dsplen, pg_johab_verifier, 3}, /* PG_JOHAB */
{0, pg_sjis_mblen, pg_sjis_dsplen, pg_sjis_verifier, 2} /*
PG_SHIFT_JIS_2004 */
};

What does last 7 zeros in the first column means? No conversion to pg_wchar
is possible from these encodings?

------
With best regards,
Alexander Korotkov.

#7Alexander Korotkov
aekorotkov@gmail.com
In reply to: Alexander Korotkov (#6)
Re: WIP: index support for regexp search

On Fri, Jan 20, 2012 at 1:07 AM, Alexander Korotkov <aekorotkov@gmail.com>wrote:

What does last 7 zeros in the first column means? No conversion to
pg_wchar is possible from these encodings?

Uh, I see. These encodings is not supported as server encodings.

------
With best regards,
Alexander Korotkov.

#8Erik Rijkers
er@xs4all.nl
In reply to: Heikki Linnakangas (#4)
Re: WIP: index support for regexp search

On Thu, January 19, 2012 21:30, Heikki Linnakangas wrote:

On 22.11.2011 21:38, Alexander Korotkov wrote:

WIP patch with index support for regexp search for pg_trgm contrib is
attached.
In spite of techniques which extracts continuous text parts from regexp,
this patch presents technique of automatum transformation. That allows more
comprehensive trigrams extraction.

Nice!

Yes, wonderful stuff; I tested quite a bit with this patch; FWIW, here's what I found.

The patch yields spectacular speedups with small, simple-enough regexen. But it does not do a
good enough job when guessing where to use the index and where fall back to Seq Scan. This can
lead to (also spectacular) slow-downs, compared to Seq Scan.

I used the following to generate 3 test tables with lines of 80 random chars (just in case it's
handy for others to use):

$ cat create_data.sh
#!/bin/sh

for power in 4 5 6
do
table=azjunk${power}
index=${table}_trgmrgx_txt_01_idx
echo "-- generating table $table with index $index";
time perl -E'
sub ss{ join"",@_[ map{rand @_} 1 .. shift ] };
say(ss(80,"a".."g"," ","h".."m"," ","n".."s"," ","t".."z"))
for 1 .. 1e'"${power};" \
| psql -aqXc "drop table if exists $table;
create table $table(txt text); copy $table from stdin;
-- set session maintenance_work_mem='20GB';
create index $index on $table using gin(txt gin_trgm_ops);
analyze $table;";
done

\dt+ public.azjunk*
List of relations
Schema | Name | Type | Owner | Size | Description
--------+---------+-------+-----------+---------+-------------
public | azjunk4 | table | breinbaas | 1152 kB |
public | azjunk5 | table | breinbaas | 11 MB |
public | azjunk6 | table | breinbaas | 112 MB |
(3 rows)

I guessed that MAX_COLOR_CHARS limits the character class size (to 4, in your patch), is that
true? I can understand you want that value to be low to limit the above risk, but now it reduces
the usability of the feature a bit: one has to split up larger char-classes into several smaller
ones to make a statement use the index: i.e.:
txt ~ 'f[aeio]n' OR txt ~ 'f[uy]n'
instead of
txt ~ 'f[aeiouy]n'

I made compiled instances with larger values for MAX_COLOR_CHARS (6 and 9), and sure enough they
used the index for larger classes such as the above, but of course also got into problems easier
when quantifiers are added (*, +, {n,m}).

A better calculation to decide index-use seems necessary, and ideally one that allows for a larger
MAX_COLOR_CHARS than 4. Especially quantifiers could perhaps be inspected wrt that decision.
IMHO, the functionality would still be very useful when only very simple regexen were considered.

Btw, it seems impossible to Ctrl-C out of a search once it is submitted; I suppose this is
normally necessary for perfomance reasons, but it would be useful te be able to compile a test
version that allows it. I don't know how hard that would be.

There is also a minor bug, I think, when running with 'set enable_seqscan=off' in combination
with a too-large regex:

$ cat fail.sql:

set enable_bitmapscan=on;
set enable_seqscan=on;
explain analyze select txt from azjunk4 where txt ~ 'f[aeio]n'; -- OK
explain analyze select txt from azjunk4 where txt ~ 'f[aeiou]n'; -- OK

set enable_bitmapscan=on;
set enable_seqscan=off;
explain analyze select txt from azjunk4 where txt ~ 'f[aeio]n'; -- OK
explain analyze select txt from azjunk4 where txt ~ 'f[aeiou]n'; -- crashes

$ psql -f fail.sql
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on azjunk4 (cost=52.01..56.02 rows=1 width=81) (actual time=1.011..5.291
rows=131 loops=1)
Recheck Cond: (txt ~ 'f[aeio]n'::text)
-> Bitmap Index Scan on azjunk4_trgmrgx_txt_01_idx (cost=0.00..52.01 rows=1 width=0) (actual
time=0.880..0.880 rows=131 loops=1)
Index Cond: (txt ~ 'f[aeio]n'::text)
Total runtime: 5.700 ms
(5 rows)

QUERY PLAN
-------------------------------------------------------------------------------------------------------
Seq Scan on azjunk4 (cost=0.00..268.00 rows=1 width=81) (actual time=1.491..36.049 rows=164
loops=1)
Filter: (txt ~ 'f[aeiou]n'::text)
Rows Removed by Filter: 9836
Total runtime: 36.112 ms
(4 rows)

QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on azjunk4 (cost=52.01..56.02 rows=1 width=81) (actual time=0.346..0.927
rows=131 loops=1)
Recheck Cond: (txt ~ 'f[aeio]n'::text)
-> Bitmap Index Scan on azjunk4_trgmrgx_txt_01_idx (cost=0.00..52.01 rows=1 width=0) (actual
time=0.316..0.316 rows=131 loops=1)
Index Cond: (txt ~ 'f[aeio]n'::text)
Total runtime: 0.996 ms
(5 rows)

psql:fail.sql:24: connection to server was lost

Sorry: I found the code, esp. the regex engine hard to understand sofar, so all the above are
somewhat inconclusive remarks; I hope nonetheless they are useful.

Thanks,

Erik Rijkers

#9Marti Raudsepp
marti@juffo.org
In reply to: Erik Rijkers (#8)
Re: WIP: index support for regexp search

On Fri, Jan 20, 2012 at 01:33, Erik Rijkers <er@xs4all.nl> wrote:

Btw, it seems impossible to Ctrl-C out of a search once it is submitted; I suppose this is
normally necessary for perfomance reasons, but it would be useful te be able to compile a test
version that allows it.

I believe being interruptible is a requirement for the patch to be accepted.

CHECK_FOR_INTERRUPTS(); should be added to the indeterminate loops.

Regards,
Marti

#10Alexander Korotkov
aekorotkov@gmail.com
In reply to: Erik Rijkers (#8)
Re: WIP: index support for regexp search

Hi!

Thank you for your feedback!

On Fri, Jan 20, 2012 at 3:33 AM, Erik Rijkers <er@xs4all.nl> wrote:

The patch yields spectacular speedups with small, simple-enough regexen.
But it does not do a
good enough job when guessing where to use the index and where fall back
to Seq Scan. This can
lead to (also spectacular) slow-downs, compared to Seq Scan.

Could you give some examples of regexes where index scan becomes slower
than seq scan?

I guessed that MAX_COLOR_CHARS limits the character class size (to 4, in
your patch), is that
true? I can understand you want that value to be low to limit the above
risk, but now it reduces
the usability of the feature a bit: one has to split up larger
char-classes into several smaller
ones to make a statement use the index: i.e.:

Yes, MAX_COLOR_CHARS is number of maximum character in automata color when
that color is divided to a separated characters. And it's likely there
could be better solution than just have this hard limit.

Btw, it seems impossible to Ctrl-C out of a search once it is submitted; I
suppose this is
normally necessary for perfomance reasons, but it would be useful te be
able to compile a test
version that allows it. I don't know how hard that would be.

I seems that Ctrl-C was impossible because procedure of trigrams
exctraction becomes so long while it is not breakable. It's not difficult
to make this procedure breakable, but actually it just shouldn't take so
long.

There is also a minor bug, I think, when running with 'set
enable_seqscan=off' in combination
with a too-large regex:

Thanks for pointing. Will be fixed.

------
With best regards,
Alexander Korotkov.

#11Alexander Korotkov
aekorotkov@gmail.com
In reply to: Marti Raudsepp (#9)
Re: WIP: index support for regexp search

On Fri, Jan 20, 2012 at 8:45 PM, Marti Raudsepp <marti@juffo.org> wrote:

On Fri, Jan 20, 2012 at 01:33, Erik Rijkers <er@xs4all.nl> wrote:

Btw, it seems impossible to Ctrl-C out of a search once it is submitted;

I suppose this is

normally necessary for perfomance reasons, but it would be useful te be

able to compile a test

version that allows it.

I believe being interruptible is a requirement for the patch to be
accepted.

CHECK_FOR_INTERRUPTS(); should be added to the indeterminate loops.

Sure. It's easy to fix. But it seems that in this case gin extract_query
method becomes slow (because index scan itself is breakable). So, it just
shouldn't work so long.

------
With best regards,
Alexander Korotkov.

#12Alexander Korotkov
aekorotkov@gmail.com
In reply to: Alexander Korotkov (#5)
Re: WIP: index support for regexp search

On Fri, Jan 20, 2012 at 12:54 AM, Alexander Korotkov
<aekorotkov@gmail.com>wrote:

On Fri, Jan 20, 2012 at 12:30 AM, Heikki Linnakangas <
heikki.linnakangas@enterprisedb.com> wrote:

Apart from that, the multibyte issue seems like the big one. Any way

around that?

Conversion of pg_wchar to multibyte character is the only way I found to

avoid serious hacking of existing regexp code. Do you think additional
function in pg_wchar_tbl which converts pg_wchar back to multibyte
character is possible solution?

Do you have any notes on it? I could make the patch which adds such
function into core.

------
With best regards,
Alexander Korotkov.

#13Erik Rijkers
er@xs4all.nl
In reply to: Alexander Korotkov (#10)
Re: WIP: index support for regexp search

On Sat, January 21, 2012 06:26, Alexander Korotkov wrote:

Hi!

Thank you for your feedback!

On Fri, Jan 20, 2012 at 3:33 AM, Erik Rijkers <er@xs4all.nl> wrote:

The patch yields spectacular speedups with small, simple-enough regexen.
But it does not do a
good enough job when guessing where to use the index and where fall back
to Seq Scan. This can
lead to (also spectacular) slow-downs, compared to Seq Scan.

Could you give some examples of regexes where index scan becomes slower
than seq scan?

x[aeio]+q takes many minutes, uninterruptible. It's now running for almost 30 minutes, I'm sure
it will come back eventually, but I think I'll kill it later on; I suppose you get the point ;-)

Even with {n,m} quantifiers it's easy to hit slowdowns:

(table azjunk6 is 112 MB, the index 693 MB.)
(MAX_COLOR_CHARS=4 <= your original patch)

instance table regex plan time

HEAD azjunk6 x[aeio]{1,3}q Seq Scan 3566.088 ms
HEAD azjunk6 x[aeio]{1,3}q Seq Scan 3540.606 ms
HEAD azjunk6 x[aeio]{1,3}q Seq Scan 3495.034 ms
HEAD azjunk6 x[aeio]{1,3}q Seq Scan 3510.403 ms
trgm_regex azjunk6 x[aeio]{1,3}q Bitmap Heap Scan 3724.131 ms
trgm_regex azjunk6 x[aeio]{1,3}q Bitmap Heap Scan 3844.999 ms
trgm_regex azjunk6 x[aeio]{1,3}q Bitmap Heap Scan 3835.190 ms
trgm_regex azjunk6 x[aeio]{1,3}q Bitmap Heap Scan 3724.016 ms

HEAD azjunk6 x[aeio]{1,4}q Seq Scan 3617.997 ms
HEAD azjunk6 x[aeio]{1,4}q Seq Scan 3644.215 ms
HEAD azjunk6 x[aeio]{1,4}q Seq Scan 3636.976 ms
HEAD azjunk6 x[aeio]{1,4}q Seq Scan 3625.493 ms
trgm_regex azjunk6 x[aeio]{1,4}q Bitmap Heap Scan 7885.247 ms
trgm_regex azjunk6 x[aeio]{1,4}q Bitmap Heap Scan 8799.082 ms
trgm_regex azjunk6 x[aeio]{1,4}q Bitmap Heap Scan 7754.152 ms
trgm_regex azjunk6 x[aeio]{1,4}q Bitmap Heap Scan 7721.332 ms

This is with your patch as is; in instances compiled with higher MAX_COLOR_CHARS (I did 6 and 9),
it is of course even easier to dream up a slow regex...

Erik Rijkers

#14Alexander Korotkov
aekorotkov@gmail.com
In reply to: Erik Rijkers (#13)
1 attachment(s)
Re: WIP: index support for regexp search

Hi!

New version of patch is attached. Changes are following:
1) Right way to convert from pg_wchar to multibyte.
2) Optimization of producing CFNA-like graph on trigrams (produce smaller,
but equivalent, graphs in less time).
3) Comments and refactoring.

------
With best regards,
Alexander Korotkov.

Attachments:

trgm-regexp-0.2.patch.gzapplication/x-gzip; name=trgm-regexp-0.2.patch.gzDownload
#15Erik Rijkers
er@xs4all.nl
In reply to: Alexander Korotkov (#14)
Re: WIP: index support for regexp search

On Mon, November 19, 2012 22:58, Alexander Korotkov wrote:

New version of patch is attached.

Hi Alexander,

I get some compile-errors:

(Centos 6.3, Linux 2.6.32-279.14.1.el6.x86_64 GNU/Linux, gcc (GCC) 4.7.2)

make contrib
trgm_regexp.c:73:2: error: unknown type name ‘TrgmStateKey’
make[1]: *** [trgm_regexp.o] Error 1
make: *** [all-pg_trgm-recurse] Error 2
trgm_regexp.c:73:2: error: unknown type name ‘TrgmStateKey’
make[1]: *** [trgm_regexp.o] Error 1
make: *** [install-pg_trgm-recurse] Error 2

Did I forget something?

Thanks,

Erik Rijkers

#16Tomas Vondra
tv@fuzzy.cz
In reply to: Alexander Korotkov (#14)
Re: WIP: index support for regexp search

On 19.11.2012 22:58, Alexander Korotkov wrote:

Hi!

New version of patch is attached. Changes are following:
1) Right way to convert from pg_wchar to multibyte.
2) Optimization of producing CFNA-like graph on trigrams (produce
smaller, but equivalent, graphs in less time).
3) Comments and refactoring.

Hi,

thanks for the updated message-id. I've done the initial review:

1) Patch applies fine to the master.

2) It's common to use upper-case names for macros, but trgm.h defines
macro "iswordchr" - I see it's moved from trgm_op.c but maybe we
could make it a bit more correct?

3) I see there are two '#ifdef KEEPONLYALNUM" blocks right next to each
other in trgm.h - maybe it'd be a good idea to join them?

4) The two new method prototypes at the end of trgm.h use different
indendation than the rest (spaces only instead of tabs).

5) There are no regression tests / updated docs (yet).

6) It does not compile - I do get a bunch of errors like this

trgm_regexp.c:73:2: error: expected specifier-qualifier-list before
‘TrgmStateKey’
trgm_regexp.c: In function ‘addKeys’:
trgm_regexp.c:291:24: error: ‘TrgmState’ has no member named ‘keys’
trgm_regexp.c:304:10: error: ‘TrgmState’ has no member named ‘keys’
...

It seems this is cause by the order of typedefs in trgm_regexp.c, namely
TrgmState referencing TrgmStateKey before it's defined. Moving the
TrgmStateKey before TrgmState fixed the issue (I'm using gcc-4.5.4 but
I think it's not compiler-dependent.)

7) Once fixed, it seems to work

CREATE EXTENSION pg_trgm ;
CREATE TABLE TEST (val TEXT);
INSERT INTO test
SELECT md5(i::text) FROM generate_series(1,1000000) s(i);
CREATE INDEX trgm_idx ON test USING gin (val gin_trgm_ops);
ANALYZE test;

EXPLAIN SELECT * FROM test WHERE val ~ '.*qqq.*';

QUERY PLAN
---------------------------------------------------------------------
Bitmap Heap Scan on test (cost=16.77..385.16 rows=100 width=33)
Recheck Cond: (val ~ '.*qqq.*'::text)
-> Bitmap Index Scan on trgm_idx (cost=0.00..16.75 rows=100
width=0)
Index Cond: (val ~ '.*qqq.*'::text)
(4 rows)

but I do get a bunch of NOTICE messages with debugging info (no matter
if the GIN index is used or not, so it's somewhere in the common regexp
code). But I guess that's due to WIP status.

regards
Tomas

#17Alexander Korotkov
aekorotkov@gmail.com
In reply to: Tomas Vondra (#16)
1 attachment(s)
Re: WIP: index support for regexp search

Some quick comments.

On Tue, Nov 20, 2012 at 3:02 AM, Tomas Vondra <tv@fuzzy.cz> wrote:

6) It does not compile - I do get a bunch of errors like this

Fixed.

7) Once fixed, it seems to work

CREATE EXTENSION pg_trgm ;
CREATE TABLE TEST (val TEXT);
INSERT INTO test
SELECT md5(i::text) FROM generate_series(1,1000000) s(i);
CREATE INDEX trgm_idx ON test USING gin (val gin_trgm_ops);
ANALYZE test;

EXPLAIN SELECT * FROM test WHERE val ~ '.*qqq.*';

QUERY PLAN
---------------------------------------------------------------------
Bitmap Heap Scan on test (cost=16.77..385.16 rows=100 width=33)
Recheck Cond: (val ~ '.*qqq.*'::text)
-> Bitmap Index Scan on trgm_idx (cost=0.00..16.75 rows=100
width=0)
Index Cond: (val ~ '.*qqq.*'::text)
(4 rows)

but I do get a bunch of NOTICE messages with debugging info (no matter
if the GIN index is used or not, so it's somewhere in the common regexp
code). But I guess that's due to WIP status.

It's due to TRGM_REGEXP_DEBUG macro. I disabled it by default. But I think
pieces of code hidden by that macro could be useful for debug even after
WIP status.

------
With best regards,
Alexander Korotkov.

Attachments:

trgm-regexp-0.3.patch.gzapplication/x-gzip; name=trgm-regexp-0.3.patch.gzDownload
#18Heikki Linnakangas
hlinnakangas@vmware.com
In reply to: Alexander Korotkov (#17)
Re: WIP: index support for regexp search

Glad to see this patch hasn't been totally forgotten. Being able to use
indexes for regular expressions would be really cool!

Back in January, I asked for some high-level description of how the
algorithm works
(http://archives.postgresql.org/message-id/4F187D5C.30701@enterprisedb.com).
That's still sorely needed. Googling around, I found the slides for your
presentation on this from PGConf.EU - it would be great to have the
information from that presentation included in the patch.

- Heikki

#19Pavel Stehule
pavel.stehule@gmail.com
In reply to: Heikki Linnakangas (#18)
Re: WIP: index support for regexp search

Hello

I tested it now and it working very well!

tested utf8, case sensitive, case insensitive

Regards

Pavel Stehule

2012/11/20 Heikki Linnakangas <hlinnakangas@vmware.com>:

Show quoted text

Glad to see this patch hasn't been totally forgotten. Being able to use
indexes for regular expressions would be really cool!

Back in January, I asked for some high-level description of how the
algorithm works
(http://archives.postgresql.org/message-id/4F187D5C.30701@enterprisedb.com).
That's still sorely needed. Googling around, I found the slides for your
presentation on this from PGConf.EU - it would be great to have the
information from that presentation included in the patch.

- Heikki

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#20Alexander Korotkov
aekorotkov@gmail.com
In reply to: Tomas Vondra (#16)
1 attachment(s)
Re: WIP: index support for regexp search

On Tue, Nov 20, 2012 at 3:02 AM, Tomas Vondra <tv@fuzzy.cz> wrote:

2) It's common to use upper-case names for macros, but trgm.h defines
macro "iswordchr" - I see it's moved from trgm_op.c but maybe we
could make it a bit more correct?

3) I see there are two '#ifdef KEEPONLYALNUM" blocks right next to each
other in trgm.h - maybe it'd be a good idea to join them?

4) The two new method prototypes at the end of trgm.h use different
indendation than the rest (spaces only instead of tabs).

These issues are fixed in attached patch.
Additionally 3 new macros are
introduced: MAX_RESULT_STATES, MAX_RESULT_ARCS, MAX_RESULT_PATHS. They are
limiting resources usage during regex processing.

------
With best regards,
Alexander Korotkov.

Attachments:

trgm-regexp-0.4.patch.gzapplication/x-gzip; name=trgm-regexp-0.4.patch.gzDownload
#21Pavel Stehule
pavel.stehule@gmail.com
In reply to: Alexander Korotkov (#20)
Re: WIP: index support for regexp search

hello

do you plan to support GiST?

Regards

Pavel

2012/11/20 Alexander Korotkov <aekorotkov@gmail.com>:

Show quoted text

On Tue, Nov 20, 2012 at 3:02 AM, Tomas Vondra <tv@fuzzy.cz> wrote:

2) It's common to use upper-case names for macros, but trgm.h defines
macro "iswordchr" - I see it's moved from trgm_op.c but maybe we
could make it a bit more correct?

3) I see there are two '#ifdef KEEPONLYALNUM" blocks right next to each
other in trgm.h - maybe it'd be a good idea to join them?

4) The two new method prototypes at the end of trgm.h use different
indendation than the rest (spaces only instead of tabs).

These issues are fixed in attached patch.
Additionally 3 new macros are introduced: MAX_RESULT_STATES,
MAX_RESULT_ARCS, MAX_RESULT_PATHS. They are limiting resources usage during
regex processing.

------
With best regards,
Alexander Korotkov.

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#22Alexander Korotkov
aekorotkov@gmail.com
In reply to: Heikki Linnakangas (#18)
1 attachment(s)
Re: WIP: index support for regexp search

On Tue, Nov 20, 2012 at 1:43 PM, Heikki Linnakangas <hlinnakangas@vmware.com

wrote:

Glad to see this patch hasn't been totally forgotten. Being able to use
indexes for regular expressions would be really cool!

Back in January, I asked for some high-level description of how the
algorithm works (http://archives.postgresql.**
org/message-id/4F187D5C.30701@**enterprisedb.com<http://archives.postgresql.org/message-id/4F187D5C.30701@enterprisedb.com&gt;).
That's still sorely needed. Googling around, I found the slides for your
presentation on this from PGConf.EU - it would be great to have the
information from that presentation included in the patch.

New version of patch is attached. The changes are following:
1) A big comment with high-level description of what is going on.
2) Regression tests.
3) Documetation update.
4) Some more refactoring.

------
With best regards,
Alexander Korotkov.

Attachments:

trgm-regexp-0.5.patch.gzapplication/x-gzip; name=trgm-regexp-0.5.patch.gzDownload
#23Alexander Korotkov
aekorotkov@gmail.com
In reply to: Pavel Stehule (#21)
Re: WIP: index support for regexp search

Hi!

On Wed, Nov 21, 2012 at 12:51 AM, Pavel Stehule <pavel.stehule@gmail.com>wrote:

do you plan to support GiST?

At first, I would note that pg_trgm GiST opclass is quite ridiculous for
support regex search (and, actually for LIKE/ILIKE search which is already
implemented too). Because in GiST opclass we store set of trigrams in leaf
pages. In was designed for trigram similarity search and have sense for it
because of elimination of trigram set computation. But for regex or
LIKE/ILIKE search this representation is both lossy and bigger than just
original string. Probably we could think about another opclass for GiST
focusing on regex and LIKE/ILIKE search?

However, amyway I can create additional patch for current GiST opclass.

------
With best regards,
Alexander Korotkov.

#24Heikki Linnakangas
hlinnakangas@vmware.com
In reply to: Alexander Korotkov (#22)
1 attachment(s)
Re: WIP: index support for regexp search

On 25.11.2012 22:55, Alexander Korotkov wrote:

On Tue, Nov 20, 2012 at 1:43 PM, Heikki Linnakangas<hlinnakangas@vmware.com

wrote:

Glad to see this patch hasn't been totally forgotten. Being able to use
indexes for regular expressions would be really cool!

Back in January, I asked for some high-level description of how the
algorithm works (http://archives.postgresql.**
org/message-id/4F187D5C.30701@**enterprisedb.com<http://archives.postgresql.org/message-id/4F187D5C.30701@enterprisedb.com&gt;).
That's still sorely needed. Googling around, I found the slides for your
presentation on this from PGConf.EU - it would be great to have the
information from that presentation included in the patch.

New version of patch is attached. The changes are following:
1) A big comment with high-level description of what is going on.
2) Regression tests.
3) Documetation update.
4) Some more refactoring.

Great, that top-level comment helped tremendously! I feel enlightened.

I fixed some spelling, formatting etc. trivial stuff while reading
through the patch, see attached. Below is some feedback on the details:

* I don't like the PG_TRY/CATCH trick. It's not generally safe to catch
an error, without propagating it further or rolling back the whole
(sub)transation. It might work in this case, as you're only suppressing
errors with the special sqlcode that are used in the same file, but it
nevertheless feels naughty. I believe none of the limits that are being
checked are strict; it's OK to exceed the limits somewhat, as long as
you terminate the processing in a reasonable time, in case of
pathological input. I'd suggest putting an explicit check for the limits
somewhere, and not rely on ereport(). Something like this, in the code
that recurses:

if (trgmCNFA->arcsCount > MAX_RESULT_ARCS ||
hash_get_num_entries(trgmCNFA->states) > MAX_RESULT_STATES)
{
trgmCNFA->overflowed = true;
return;
}

And then check for the overflowed flag at the top level.

* This part of the high-level comment was not clear to me:

* States of the graph produced in the first stage are marked with "keys". Key is a pair
* of a "prefix" and a state of the original automaton. "Prefix" is a last
* characters. So, knowing the prefix is enough to know what is a trigram when we read some new
* character. However, we can know single character of prefix or don't know any
* characters of it. Each state of resulting graph have an "enter key" (with that
* key we've entered this state) and a set of keys which are reachable without
* reading any predictable trigram. The algorithm of processing each state
* of resulting graph are so:
* 1) Add all keys which achievable without reading of any predictable trigram.
* 2) Add outgoing arcs labeled with trigrams.
* Step 2 leads to creation of new states and recursively processing them. So,
* we use depth-first algorithm.

I didn't understand that. Can you elaborate? It might help to work
through an example, with some ascii art depicting the graph.

* It would be nice to add some comments to TrgmCNFA struct, explaining
which fields are valid at which stages. For example, it seems that
'trgms' array is calculated only after building the CNFA, by
getTrgmVector() function, while arcsCount is updated on the fly, while
recursing in the getState() function.

* What is the representation used for the path matrix? Needs a comment.

* What do the getColorinfo() and scanColorMap() functions do? What
exactly does a color represent? What's the tradeoff in choosing
MAX_COLOR_CHARS?

- Heikki

Attachments:

trgm-regexp-0.5-heikki1.patchtext/x-diff; name=trgm-regexp-0.5-heikki1.patchDownload
diff --git a/contrib/pg_trgm/Makefile b/contrib/pg_trgm/Makefile
index 64fd69f..8033733 100644
--- a/contrib/pg_trgm/Makefile
+++ b/contrib/pg_trgm/Makefile
@@ -1,7 +1,7 @@
 # contrib/pg_trgm/Makefile
 
 MODULE_big = pg_trgm
-OBJS = trgm_op.o trgm_gist.o trgm_gin.o
+OBJS = trgm_op.o trgm_gist.o trgm_gin.o trgm_regexp.o
 
 EXTENSION = pg_trgm
 DATA = pg_trgm--1.0.sql pg_trgm--unpackaged--1.0.sql
diff --git a/contrib/pg_trgm/expected/pg_trgm.out b/contrib/pg_trgm/expected/pg_trgm.out
index 81d0ca8..ee0131f 100644
--- a/contrib/pg_trgm/expected/pg_trgm.out
+++ b/contrib/pg_trgm/expected/pg_trgm.out
@@ -54,7 +54,7 @@ select similarity('wow',' WOW ');
 (1 row)
 
 CREATE TABLE test_trgm(t text);
-\copy test_trgm from 'data/trgm.data
+\copy test_trgm from 'data/trgm.data'
 select t,similarity(t,'qwertyu0988') as sml from test_trgm where t % 'qwertyu0988' order by sml desc, t;
       t      |   sml    
 -------------+----------
@@ -3515,6 +3515,47 @@ select * from test2 where t ilike 'qua%';
  quark
 (1 row)
 
+select * from test2 where t ~ '[abc]{3}';
+   t    
+--------
+ abcdef
+(1 row)
+
+select * from test2 where t ~ 'a[bc]+d';
+   t    
+--------
+ abcdef
+(1 row)
+
+select * from test2 where t ~* 'DEF';
+   t    
+--------
+ abcdef
+(1 row)
+
+select * from test2 where t ~ 'dEf';
+ t 
+---
+(0 rows)
+
+select * from test2 where t ~* '^q';
+   t   
+-------
+ quark
+(1 row)
+
+select * from test2 where t ~* '[abc]{3}[def]{3}';
+   t    
+--------
+ abcdef
+(1 row)
+
+select * from test2 where t ~ 'q.*rk$';
+   t   
+-------
+ quark
+(1 row)
+
 drop index test2_idx_gin;
 create index test2_idx_gist on test2 using gist (t gist_trgm_ops);
 set enable_seqscan=off;
diff --git a/contrib/pg_trgm/pg_trgm--1.0.sql b/contrib/pg_trgm/pg_trgm--1.0.sql
index 8067bd6..ca9bcaa 100644
--- a/contrib/pg_trgm/pg_trgm--1.0.sql
+++ b/contrib/pg_trgm/pg_trgm--1.0.sql
@@ -163,4 +163,6 @@ AS
 
 ALTER OPERATOR FAMILY gin_trgm_ops USING gin ADD
         OPERATOR        3       pg_catalog.~~ (text, text),
-        OPERATOR        4       pg_catalog.~~* (text, text);
+        OPERATOR        4       pg_catalog.~~* (text, text),
+        OPERATOR        5       pg_catalog.~ (text, text),
+        OPERATOR        6       pg_catalog.~* (text, text);
diff --git a/contrib/pg_trgm/sql/pg_trgm.sql b/contrib/pg_trgm/sql/pg_trgm.sql
index 81ab1e7..7d8a151 100644
--- a/contrib/pg_trgm/sql/pg_trgm.sql
+++ b/contrib/pg_trgm/sql/pg_trgm.sql
@@ -13,7 +13,7 @@ select similarity('wow',' WOW ');
 
 CREATE TABLE test_trgm(t text);
 
-\copy test_trgm from 'data/trgm.data
+\copy test_trgm from 'data/trgm.data'
 
 select t,similarity(t,'qwertyu0988') as sml from test_trgm where t % 'qwertyu0988' order by sml desc, t;
 select t,similarity(t,'gwertyu0988') as sml from test_trgm where t % 'gwertyu0988' order by sml desc, t;
@@ -52,6 +52,14 @@ select * from test2 where t like '%bcd%';
 select * from test2 where t like E'%\\bcd%';
 select * from test2 where t ilike '%BCD%';
 select * from test2 where t ilike 'qua%';
+
+select * from test2 where t ~ '[abc]{3}';
+select * from test2 where t ~ 'a[bc]+d';
+select * from test2 where t ~* 'DEF';
+select * from test2 where t ~ 'dEf';
+select * from test2 where t ~* '^q';
+select * from test2 where t ~* '[abc]{3}[def]{3}';
+select * from test2 where t ~ 'q.*rk$';
 drop index test2_idx_gin;
 create index test2_idx_gist on test2 using gist (t gist_trgm_ops);
 set enable_seqscan=off;
diff --git a/contrib/pg_trgm/trgm.h b/contrib/pg_trgm/trgm.h
index 067f29d..6ec9345 100644
--- a/contrib/pg_trgm/trgm.h
+++ b/contrib/pg_trgm/trgm.h
@@ -7,7 +7,6 @@
 #include "access/gist.h"
 #include "access/itup.h"
 #include "storage/bufpage.h"
-#include "utils/builtins.h"
 
 /* options */
 #define LPADDING		2
@@ -28,6 +27,8 @@
 #define DistanceStrategyNumber		2
 #define LikeStrategyNumber			3
 #define ILikeStrategyNumber			4
+#define RegExpStrategyNumber		5
+#define RegExpStrategyNumberICase	6
 
 
 typedef char trgm[3];
@@ -46,8 +47,10 @@ uint32		trgm2int(trgm *ptr);
 
 #ifdef KEEPONLYALNUM
 #define ISPRINTABLECHAR(a)	( isascii( *(unsigned char*)(a) ) && (isalnum( *(unsigned char*)(a) ) || *(unsigned char*)(a)==' ') )
+#define ISWORDCHR(c)	(t_isalpha(c) || t_isdigit(c))
 #else
 #define ISPRINTABLECHAR(a)	( isascii( *(unsigned char*)(a) ) && isprint( *(unsigned char*)(a) ) )
+#define ISWORDCHR(c)	(!t_isspace(c))
 #endif
 #define ISPRINTABLETRGM(t)	( ISPRINTABLECHAR( ((char*)(t)) ) && ISPRINTABLECHAR( ((char*)(t))+1 ) && ISPRINTABLECHAR( ((char*)(t))+2 ) )
 
@@ -99,11 +102,21 @@ typedef char *BITVECP;
 #define GETARR(x)		( (trgm*)( (char*)x+TRGMHDRSIZE ) )
 #define ARRNELEM(x) ( ( VARSIZE(x) - TRGMHDRSIZE )/sizeof(trgm) )
 
+typedef struct
+{
+	int count;
+	char data[0];
+} PackedTrgmPaths;
+
 extern float4 trgm_limit;
 
+#define ERRCODE_TRGM_REGEX_TOO_COMPLEX MAKE_SQLSTATE('T','M','0','0','0')
+
 TRGM	   *generate_trgm(char *str, int slen);
 TRGM	   *generate_wildcard_trgm(const char *str, int slen);
 float4		cnt_sml(TRGM *trg1, TRGM *trg2);
 bool		trgm_contained_by(TRGM *trg1, TRGM *trg2);
+void		cnt_trigram(trgm *trgmptr, char *str, int bytelen);
+TRGM	   *createTrgmCNFA(text *text_re, MemoryContext context, PackedTrgmPaths **paths);
 
 #endif   /* __TRGM_H__ */
diff --git a/contrib/pg_trgm/trgm_gin.c b/contrib/pg_trgm/trgm_gin.c
index 114fb78..9f53644 100644
--- a/contrib/pg_trgm/trgm_gin.c
+++ b/contrib/pg_trgm/trgm_gin.c
@@ -75,19 +75,20 @@ gin_extract_value_trgm(PG_FUNCTION_ARGS)
 Datum
 gin_extract_query_trgm(PG_FUNCTION_ARGS)
 {
-	text	   *val = (text *) PG_GETARG_TEXT_P(0);
-	int32	   *nentries = (int32 *) PG_GETARG_POINTER(1);
-	StrategyNumber strategy = PG_GETARG_UINT16(2);
+	text			*val = (text *) PG_GETARG_TEXT_P(0);
+	int32			*nentries = (int32 *) PG_GETARG_POINTER(1);
+	StrategyNumber	 strategy = PG_GETARG_UINT16(2);
 
-	/* bool   **pmatch = (bool **) PG_GETARG_POINTER(3); */
-	/* Pointer	  *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
-	/* bool   **nullFlags = (bool **) PG_GETARG_POINTER(5); */
-	int32	   *searchMode = (int32 *) PG_GETARG_POINTER(6);
-	Datum	   *entries = NULL;
-	TRGM	   *trg;
-	int32		trglen;
-	trgm	   *ptr;
-	int32		i;
+	/* bool        **pmatch = (bool **) PG_GETARG_POINTER(3); */
+	Pointer		   **extra_data = (Pointer **) PG_GETARG_POINTER(4);
+	/* bool        **nullFlags = (bool **) PG_GETARG_POINTER(5); */
+	int32			*searchMode = (int32 *) PG_GETARG_POINTER(6);
+	Datum			*entries = NULL;
+	TRGM			*trg;
+	int32			 trglen;
+	trgm			*ptr;
+	int32			 i;
+	PackedTrgmPaths	*paths;
 
 	switch (strategy)
 	{
@@ -107,6 +108,32 @@ gin_extract_query_trgm(PG_FUNCTION_ARGS)
 			 */
 			trg = generate_wildcard_trgm(VARDATA(val), VARSIZE(val) - VARHDRSZ);
 			break;
+		case RegExpStrategyNumberICase:
+#ifndef IGNORECASE
+			elog(ERROR, "cannot handle ~* with case-sensitive trigrams");
+#endif
+			/* FALL THRU */
+		case RegExpStrategyNumber:
+			trg = createTrgmCNFA(val, fcinfo->flinfo->fn_mcxt, &paths);
+			if (trg && ARRNELEM(trg) > 0)
+			{
+				/*
+				 * Successful of regex processing: store path matrix as an
+				 * extra_data.
+				 */
+				*extra_data = (Pointer *)palloc0(sizeof(Pointer) *
+																ARRNELEM(trg));
+				for (i = 0; i < ARRNELEM(trg); i++)
+					(*extra_data)[i] = (Pointer)paths;
+			}
+			else
+			{
+				/* No result: have to do full index scan. */
+				*nentries = 0;
+				*searchMode = GIN_SEARCH_MODE_ALL;
+				PG_RETURN_POINTER(entries);
+			}
+			break;
 		default:
 			elog(ERROR, "unrecognized strategy number: %d", strategy);
 			trg = NULL;			/* keep compiler quiet */
@@ -147,11 +174,15 @@ gin_trgm_consistent(PG_FUNCTION_ARGS)
 	/* text    *query = PG_GETARG_TEXT_P(2); */
 	int32		nkeys = PG_GETARG_INT32(3);
 
-	/* Pointer	  *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
+	Pointer	   *extra_data = (Pointer *) PG_GETARG_POINTER(4);
 	bool	   *recheck = (bool *) PG_GETARG_POINTER(5);
-	bool		res;
-	int32		i,
+	bool		res, f;
+	int32		i, j,
 				ntrue;
+	PackedTrgmPaths *paths;
+	char	   *path;
+	int			pathCount, bitmaskLength = (nkeys + 7) / 8;
+
 
 	/* All cases served by this function are inexact */
 	*recheck = true;
@@ -189,6 +220,37 @@ gin_trgm_consistent(PG_FUNCTION_ARGS)
 				}
 			}
 			break;
+		case RegExpStrategyNumber:
+		case RegExpStrategyNumberICase:
+			if (nkeys < 1)
+			{
+				/* Regex processing gives no result: do full index scan */
+				res = true;
+				break;
+			}
+			/* Try to find path conforming this set of trigrams */
+			paths = (PackedTrgmPaths *)extra_data[0];
+			pathCount = paths->count;
+			res = false;
+			for (i = 0; i < pathCount; i++)
+			{
+				path = &paths->data[bitmaskLength * i];
+				f = true;
+				for (j = 0; j < nkeys; j++)
+				{
+					if (GETBIT(path, j) && !check[j])
+					{
+						f = false;
+						break;
+					}
+				}
+				if (f)
+				{
+					res = true;
+					break;
+				}
+			}
+			break;
 		default:
 			elog(ERROR, "unrecognized strategy number: %d", strategy);
 			res = false;		/* keep compiler quiet */
diff --git a/contrib/pg_trgm/trgm_op.c b/contrib/pg_trgm/trgm_op.c
index 87dffd1..71aa938 100644
--- a/contrib/pg_trgm/trgm_op.c
+++ b/contrib/pg_trgm/trgm_op.c
@@ -77,12 +77,6 @@ unique_array(trgm *a, int len)
 	return curend + 1 - a;
 }
 
-#ifdef KEEPONLYALNUM
-#define iswordchr(c)	(t_isalpha(c) || t_isdigit(c))
-#else
-#define iswordchr(c)	(!t_isspace(c))
-#endif
-
 /*
  * Finds first word in string, returns pointer to the word,
  * endword points to the character after word
@@ -92,7 +86,7 @@ find_word(char *str, int lenstr, char **endword, int *charlen)
 {
 	char	   *beginword = str;
 
-	while (beginword - str < lenstr && !iswordchr(beginword))
+	while (beginword - str < lenstr && !ISWORDCHR(beginword))
 		beginword += pg_mblen(beginword);
 
 	if (beginword - str >= lenstr)
@@ -100,7 +94,7 @@ find_word(char *str, int lenstr, char **endword, int *charlen)
 
 	*endword = beginword;
 	*charlen = 0;
-	while (*endword - str < lenstr && iswordchr(*endword))
+	while (*endword - str < lenstr && ISWORDCHR(*endword))
 	{
 		*endword += pg_mblen(*endword);
 		(*charlen)++;
@@ -109,8 +103,7 @@ find_word(char *str, int lenstr, char **endword, int *charlen)
 	return beginword;
 }
 
-#ifdef USE_WIDE_UPPER_LOWER
-static void
+void
 cnt_trigram(trgm *tptr, char *str, int bytelen)
 {
 	if (bytelen == 3)
@@ -131,7 +124,6 @@ cnt_trigram(trgm *tptr, char *str, int bytelen)
 		CPTRGM(tptr, &crc);
 	}
 }
-#endif
 
 /*
  * Adds trigrams from words (already padded).
@@ -287,7 +279,7 @@ get_wildcard_part(const char *str, int lenstr,
 	{
 		if (in_escape)
 		{
-			if (iswordchr(beginword))
+			if (ISWORDCHR(beginword))
 				break;
 			in_escape = false;
 			in_leading_wildcard_meta = false;
@@ -298,7 +290,7 @@ get_wildcard_part(const char *str, int lenstr,
 				in_escape = true;
 			else if (ISWILDCARDCHAR(beginword))
 				in_leading_wildcard_meta = true;
-			else if (iswordchr(beginword))
+			else if (ISWORDCHR(beginword))
 				break;
 			else
 				in_leading_wildcard_meta = false;
@@ -341,7 +333,7 @@ get_wildcard_part(const char *str, int lenstr,
 		clen = pg_mblen(endword);
 		if (in_escape)
 		{
-			if (iswordchr(endword))
+			if (ISWORDCHR(endword))
 			{
 				memcpy(s, endword, clen);
 				(*charlen)++;
@@ -369,7 +361,7 @@ get_wildcard_part(const char *str, int lenstr,
 				in_trailing_wildcard_meta = true;
 				break;
 			}
-			else if (iswordchr(endword))
+			else if (ISWORDCHR(endword))
 			{
 				memcpy(s, endword, clen);
 				(*charlen)++;
diff --git a/contrib/pg_trgm/trgm_regexp.c b/contrib/pg_trgm/trgm_regexp.c
new file mode 100644
index 0000000..be7d846
--- /dev/null
+++ b/contrib/pg_trgm/trgm_regexp.c
@@ -0,0 +1,1209 @@
+/*
+ * contrib/pg_trgm/trgm_regexp.c - regular expression matching using trigrams
+ *
+ * The general idea of index support for a regular expression (regex) search
+ * is to transform regex to a logical expression on trigrams. For example:
+ *
+ *   (ab|cd)efg => ((abe & bef) | (cde & def)) & efg
+ *
+ * If a string matches the regex, then it must match the logical expression of
+ * trigrams. The opposite is not necessary true, however: a string that matches
+ * the logical expression might not match the original regex. Such false
+ * positives are removed during recheck.
+ *
+ * The algorithm to convert a regex to a logical expression is based on
+ * analysis of an automaton that corresponds to regex. The algorithm consists
+ * of two stages:
+ * 1) Transform the automaton to an automaton-like graph of trigrams.
+ * 2) Collect all minimal paths of that graph into a matrix.
+ *
+ * Automaton we have after processing a regular expression is a graph where
+ * vertices are "states" and arcs are labeled with characters. There are
+ * two special states: "initial" and "final". If you can traverse from the
+ * initial state to the final state, and type given string by arc labels then
+ * the string matches the regular expression.
+ *
+ * We use CNFA (colored non-deterministic finite-state automaton) produced by
+ * the PostgreSQL regex library. CNFA means that:
+ * 1) Characters are grouped into colors, so arcs are labeled with colors.
+ * 2) Multiple outgoing arcs from same state can be labeled with the same color.
+ *    This makes the automaton non-deterministic, because it can be in many
+ *    states simultaneously.
+ * 3) It has finite number of states (actually infinite-state automata are
+ *    almost never considered).
+ *
+ * As result of the first stage we have a CNFA-like graph with the following
+ * property: If you can traverse from the initial state to the final state, via
+ * arcs labeled with trigrams that are present in the string, then the string
+ * might match the regex. Otherwise, it does not. Actually, this graph is a
+ * form of representation of logical expression we need.
+ *
+ * States of the graph produced in the first stage are marked with "keys". Key is a pair
+ * of a "prefix" and a state of the original automaton. "Prefix" is a last
+ * characters. So, knowing the prefix is enough to know what is a trigram when we read some new
+ * character. However, we can know single character of prefix or don't know any
+ * characters of it. Each state of resulting graph have an "enter key" (with that
+ * key we've entered this state) and a set of keys which are reachable without
+ * reading any predictable trigram. The algorithm of processing each state
+ * of resulting graph are so:
+ * 1) Add all keys which achievable without reading of any predictable trigram.
+ * 2) Add outgoing arcs labeled with trigrams.
+ * Step 2 leads to creation of new states and recursively processing them. So,
+ * we use depth-first algorithm.
+ *
+ * At the second stage we collect all the paths in graph from first stage. We
+ * only need "minimal" paths. For example, if we have two paths "abc & bcd" and
+ * "abc & bcd & cde" then then second one doesn't matter because the first one
+ * includes all the strings which the second one does. In order to evade
+ * enumeration of too many non-minimal paths we use breadth-first search with
+ * keeping matrix of minimal paths in each state.
+ */
+#include "postgres.h"
+
+#include "trgm.h"
+
+#include "catalog/pg_collation.h"
+#include "fmgr.h"
+#include "miscadmin.h"
+#include "mb/pg_wchar.h"
+#include "nodes/pg_list.h"
+#include "regex/regex.h"
+#undef INFINITY /* avoid conflict of INFINITY definition */
+#include "regex/regguts.h"
+#include "tsearch/ts_locale.h"
+#include "utils/hsearch.h"
+
+/*
+ * Uncomment to print intermediate stages, for exploring and debugging the
+ * algorithm implementation.
+ */
+/* #define TRGM_REGEXP_DEBUG */
+
+/* How big colors we're considering as separate arcs */
+#define MAX_COLOR_CHARS		4
+
+/*---
+ * Following group of parameters are used in order to limit our computations.
+ * Otherwise regex processing could be too slow and memory-consuming.
+ *
+ *  MAX_RESULT_STATES - How many states we allow in result CNFA-like graph
+ *  MAX_RESULT_ARCS - How many arcs we allow in result CNFA-like graph
+ *  MAX_RESULT_PATHS - How many paths we allow in single path matrix
+ */
+#define MAX_RESULT_STATES	128
+#define MAX_RESULT_ARCS		1024
+#define MAX_RESULT_PATHS	256
+
+/*
+ * Widechar trigram datatype for holding trigram before possible conversion into
+ * CRC32
+ */
+typedef pg_wchar Trgm[3];
+
+/*
+ * Maximum length of multibyte encoding character is 4. So, we can hold it in
+ * 32 bit integer for handling simplicity.
+ */
+typedef uint32 mb_char;
+
+/*----
+ * Attributes of CNFA colors:
+ *
+ *  containAlpha - flag indicates if color might contain alphanumeric characters
+ *                 (which are extracted into trigrams)
+ *  charsCount   - count of characters in color
+ *  chars        - characters of color
+ *
+ * All non alphanumeric character are treated as same zero character, because
+ * there are no difference between them for trigrams. Exact value of
+ * "charsCount" and value of "chars" is meaningful only when
+ * charsCount <= MAX_COLOR_CHARS. When charsCount > MAX_COLOR_CHARS we can
+ * expect any characters from this color.
+ */
+typedef struct
+{
+	int			charsCount;
+	bool		containAlpha;
+	mb_char		chars[MAX_COLOR_CHARS];
+} ColorInfo;
+
+/*
+ * Prefix is information about last two read characters when coming into
+ * specific CNFA state. "s" contain that characters itself. But s[0] or both
+ * s[0] and s[1] could be zeros. "ambiguity" flag tells us how to treat that.
+ * If "ambiguity" is false then zeros in s indicates start of trigram. When
+ * "ambiguity" is true then zeros in s indicates that it could be any
+ * characters. Having "ambiguity" flag this structure actually express a class
+ * of prefixes.
+ */
+typedef struct
+{
+	mb_char	s[2];
+	bool	ambiguity;
+} TrgmPrefix;
+
+/*
+ * "Key" of resulting state: pair of prefix and source CNFA state.
+ */
+typedef struct
+{
+	TrgmPrefix prefix;
+	int        nstate;
+} TrgmStateKey;
+
+/*---
+ * State of resulting graph.
+ *
+ *  enterKey - a key with which we can enter this state
+ *  keys     - all keys achievable without reading any predictable trigram
+ *  arcs     - outgoing arcs of this state
+ *  fin      - flag indicated this state if final
+ *  queued   - flag indicated this states is queued in path matrix collection
+ *             algorithm
+ */
+typedef struct
+{
+	TrgmStateKey	enterKey;
+	List		   *keys;
+	List		   *arcs;
+	List		   *path;
+	bool			fin;
+	bool			queued;
+} TrgmState;
+
+/*
+ * Arc of trigram CNFA-like structure. Arc is labeled with trigram.
+ */
+typedef struct
+{
+	TrgmState  *target;
+	Trgm		trgm;
+} TrgmArc;
+
+/*---
+ * A single path is a path matrix of some state.
+ *
+ *  queued - flag indicated that this path is new since last processing of this
+ *           state and it's queued for processing.
+ *  path   - bit array representing a path itself.
+ */
+typedef struct
+{
+	bool queued;
+	char path[0];
+} TrgmStatePath;
+
+/*---
+ * Data structure representing all the data we need during regex processing.
+ *
+ *  states     - hash of states of resulting graph
+ *  cnfa       - source CFNA of regex
+ *  colorInfo  - processed information of regex colors
+ *  initState  - pointer to initial state of resulting graph
+ *  trgms      - array of all trigrams presented in graph
+ *  trgmCount  - count of that trigrams
+ *  arcsCount  - total number of arcs of resulting graph (for resouces limiting)
+ *  bitmaskLen - length of bitmask representing single path in path matrix
+ *  path       - resulting path matrix
+ *  queue      - queue for path matrix producing
+ */
+typedef struct
+{
+	HTAB	       *states;
+	struct cnfa    *cnfa;
+	ColorInfo	   *colorInfo;
+	TrgmState	   *initState;
+	Trgm		   *trgms;
+	int				trgmCount;
+	int				arcsCount;
+	int				bitmaskLen;
+	List		   *path;
+	List		   *queue;
+} TrgmCNFA;
+
+static TrgmState *getState(TrgmCNFA *trgmCNFA, TrgmStateKey *key);
+
+/*
+ * Convert pg_wchar to multibyte character.
+ */
+static mb_char
+convertPgWchar(pg_wchar c)
+{
+	/*
+	 * "s" has enough of space for, at maximum 4 byte multibyte character and
+	 * a zero-byte at the end.
+	 */
+	char		s[5];
+	char	   *lowerCased;
+	mb_char		result;
+
+	if (c == 0)
+		return 0;
+
+	MemSet(s, 0, sizeof(s));
+	pg_wchar2mb_with_len(&c, s, 1);
+
+	/* Convert to lowercase if needed */
+#ifdef IGNORECASE
+	lowerCased = lowerstr(s);
+#else
+	lowerCased = s;
+#endif
+	strncpy((char *)&result, lowerCased, 4);
+	return result;
+}
+
+/*
+ * Recursive function of colormap scanning.
+ */
+static void
+scanColorMap(union tree	tree[NBYTS], union tree *t, ColorInfo *colorInfos,
+			 int level, pg_wchar p)
+{
+	int			i;
+
+	check_stack_depth();
+
+	if (level < NBYTS - 1)
+	{
+		for (i = 0; i < BYTTAB; i++)
+		{
+			/*
+			 * This condition checks if all underlying levels express zero
+			 * color. Zero color uses multiple links to same color table. So,
+			 * avoid scanning it because it's expensive.
+			 */
+			if (t->tptr[i] == &tree[level + 1])
+				continue;
+			/* Recursive scanning of next level color table */
+			scanColorMap(tree, t->tptr[i], colorInfos, level + 1, (p << 8) | i);
+		}
+	}
+	else
+	{
+		p <<= 8;
+		for (i = 0; i < BYTTAB; i++)
+		{
+			ColorInfo *colorInfo = &colorInfos[t->tcolor[i]];
+			int j;
+			pg_wchar c;
+
+			/* Convert to multibyte character */
+			c = convertPgWchar(p | i);
+
+			/* Update color attributes according to next character */
+			if (ISWORDCHR((char *)&c))
+				colorInfo->containAlpha = true;
+			else
+				c = 0;
+			if (colorInfo->charsCount <= MAX_COLOR_CHARS)
+			{
+				bool found = false;
+				for (j = 0; j < colorInfo->charsCount; j++)
+				{
+					if (colorInfo->chars[j] == c)
+					{
+						found = true;
+						break;
+					}
+				}
+				if (found)
+					continue;
+			}
+			if (colorInfo->charsCount < MAX_COLOR_CHARS)
+				colorInfo->chars[colorInfo->charsCount] = c;
+			colorInfo->charsCount++;
+		}
+	}
+}
+
+/*
+ * Obtain attributes of colors.
+ */
+static ColorInfo *
+getColorInfo(regex_t *regex)
+{
+	struct guts *g;
+	struct colormap *cm;
+	ColorInfo  *result;
+	int			colorsCount;
+
+	g = (struct guts *) regex->re_guts;
+	cm = &g->cmap;
+	colorsCount = cm->max + 1;
+
+	result = (ColorInfo *) palloc0(colorsCount * sizeof(ColorInfo));
+
+	/*
+	 * Zero color is a default color which contains all character which aren't
+	 * in explicitly expressed classes. Mark that we can expect everything
+	 * from it.
+	 */
+	result[0].containAlpha = true;
+	result[0].charsCount = MAX_COLOR_CHARS + 1;
+	scanColorMap(cm->tree, &cm->tree[0], result, 0, 0);
+
+#ifdef TRGM_REGEXP_DEBUG
+	{
+		int i;
+		for (i = 0; i < colorsCount; i++)
+		{
+			ColorInfo *colorInfo = &result[i];
+			elog(NOTICE, "COLOR %d %d %d %08X %08X %08X %08X", i,
+				colorInfo->charsCount, colorInfo->containAlpha,
+				colorInfo->chars[0], colorInfo->chars[1],
+				colorInfo->chars[2], colorInfo->chars[3]);
+		}
+	}
+#endif
+	return result;
+}
+
+/*
+ * Check if prefix1 "contains" prefix2. "contains" mean that any exact prefix
+ * (which no ambiguity) which satisfy to prefix2 also satisfy to prefix1.
+ */
+static bool
+prefixContains(TrgmPrefix *prefix1, TrgmPrefix *prefix2)
+{
+	if (prefix1->ambiguity)
+	{
+		if (prefix1->s[1] == 0)
+		{
+			/* Fully ambiguous prefix contains everything */
+			return true;
+		}
+		else
+		{
+			/*
+			 * Prefix with only first ambiguous characters contains every prefix
+			 * with same second character.
+			 */
+			if (prefix1->s[1] == prefix2->s[1])
+				return true;
+			else
+				return false;
+		}
+	}
+	else
+	{
+		/* Exact prefix contains only exactly same prefix */
+		if (prefix1->s[0] == prefix2->s[0] && prefix1->s[1] == prefix2->s[1]
+			&& !prefix2->ambiguity)
+			return true;
+		else
+			return false;
+	}
+}
+
+/*
+ * Add all keys which can be achieved without reading any trigram to state of
+ * CNFA-like graph on trigrams.
+ */
+static void
+addKeys(TrgmCNFA *trgmCNFA, TrgmState *state, TrgmStateKey *key)
+{
+	struct carc *s;
+	TrgmStateKey destKey;
+	ListCell *cell, *prev, *next;
+	TrgmStateKey *keyCopy;
+
+	MemSet(&destKey, 0, sizeof(TrgmStateKey));
+
+	/* Adjust list of keys with new one */
+	prev = NULL;
+	cell = list_head(state->keys);
+	while (cell)
+	{
+		TrgmStateKey *listKey = (TrgmStateKey *) lfirst(cell);
+		next = lnext(cell);
+		if (listKey->nstate == key->nstate)
+		{
+			if (prefixContains(&listKey->prefix, &key->prefix))
+			{
+				/* Already had this key: nothing to do */
+				return;
+			}
+			if (prefixContains(&key->prefix, &listKey->prefix))
+				state->keys = list_delete_cell(state->keys, cell, prev);
+			else
+				prev = cell;
+		}
+		else
+			prev = cell;
+		cell = next;
+	}
+	keyCopy = (TrgmStateKey *) palloc(sizeof(TrgmStateKey));
+	memcpy(keyCopy, key, sizeof(TrgmStateKey));
+	state->keys = lappend(state->keys, keyCopy);
+
+	/* Mark final state */
+	if (key->nstate == trgmCNFA->cnfa->post)
+	{
+		state->fin = true;
+		return;
+	}
+
+	s = trgmCNFA->cnfa->states[key->nstate];
+	while (s->co != COLORLESS)
+	{
+		ColorInfo *colorInfo;
+
+		if (s->co == trgmCNFA->cnfa->bos[1])
+		{
+			/* Start of line (^) */
+			destKey.nstate = s->to;
+
+			/* Mark prefix as start of new trigram */
+			destKey.prefix.s[0] = 0;
+			destKey.prefix.s[1] = 0;
+			destKey.prefix.ambiguity = false;
+
+			/* Add key to this state */
+			addKeys(trgmCNFA, state, &destKey);
+			if (state->fin)
+				return;
+		}
+		else if (s->co == trgmCNFA->cnfa->eos[1])
+		{
+			/* End of string ($) */
+			if (key->prefix.ambiguity)
+			{
+				destKey.nstate = s->to;
+
+				/*
+				 * Let's think prefix to become ambiguous (in order to prevent
+				 * latter fiddling around with keys).
+				 */
+				destKey.prefix.s[1] = 0;
+				destKey.prefix.s[0] = 0;
+				destKey.prefix.ambiguity = true;
+
+				/* Prefix is ambiguous, add key to the same state */
+				addKeys(trgmCNFA, state, &destKey);
+				if (state->fin)
+					return;
+			}
+		}
+		else
+		{
+			/* Regular color */
+			colorInfo = &trgmCNFA->colorInfo[s->co];
+
+			if (colorInfo->charsCount > 0 &&
+				colorInfo->charsCount <= MAX_COLOR_CHARS)
+			{
+				/* We can enumerate characters of this color */
+				int i;
+				for (i = 0; i < colorInfo->charsCount; i++)
+				{
+					mb_char c = colorInfo->chars[i];
+
+					/*
+					 * ----
+					 * Create new prefix
+					 * 1 (end of prefix)   - current character "c"
+					 * 0 (start of prefix) - end of previous prefix
+					 *
+					 * Zero "c" means non alphanumeric character, this means
+					 * new prefix should indicate start of new trigram.
+					 */
+					destKey.prefix.s[1] = c;
+					destKey.prefix.s[0] = c ? key->prefix.s[1] : 0;
+
+					destKey.nstate = s->to;
+
+					if (destKey.prefix.s[0] || c == 0)
+						destKey.prefix.ambiguity = false;
+					else
+						destKey.prefix.ambiguity = key->prefix.ambiguity;
+
+					if (key->prefix.ambiguity ||
+											(key->prefix.s[1] == 0 && c == 0))
+					{
+						/*
+						 * If we have ambiguity or start of new trigram then add
+						 * corresponding keys to same state.
+						 */
+						addKeys(trgmCNFA, state, &destKey);
+						if (state->fin)
+							return;
+					}
+				}
+			}
+			else
+			{
+				/*
+				 * Can't enumerate characters. Add corresponding key to this
+				 * state.
+				 */
+				destKey.nstate = s->to;
+				destKey.prefix.s[0] = 0;
+				destKey.prefix.s[1] = 0;
+				destKey.prefix.ambiguity = colorInfo->containAlpha;
+				addKeys(trgmCNFA, state, &destKey);
+				if (state->fin)
+					return;
+			}
+		}
+		s++;
+	}
+}
+
+/*
+ * Add outgoing arc from state if needed.
+ */
+static void
+addArc(TrgmCNFA *trgmCNFA, TrgmState *state, TrgmStateKey *key,
+	   TrgmStateKey *destKey, mb_char c)
+{
+	TrgmArc *arc;
+	ListCell *cell2;
+
+	if (key->prefix.ambiguity || (key->prefix.s[1] == 0 && c == 0))
+		return;
+
+	/* If we have the same key here, we don't need to add new arc */
+	foreach(cell2, state->keys)
+	{
+		TrgmStateKey *key2 = (TrgmStateKey *) lfirst(cell2);
+		if (key2->nstate == destKey->nstate &&
+			prefixContains(&key2->prefix, &destKey->prefix))
+		{
+			return;
+		}
+	}
+
+	/* Not found, add new arc */
+	arc = (TrgmArc *) palloc(sizeof(TrgmArc));
+	arc->target = getState(trgmCNFA, destKey);
+	arc->trgm[0] = key->prefix.s[0];
+	arc->trgm[1] = key->prefix.s[1];
+	arc->trgm[2] = c;
+	state->arcs = lappend(state->arcs, arc);
+	trgmCNFA->arcsCount++;
+	if (trgmCNFA->arcsCount > MAX_RESULT_ARCS)
+		ereport(ERROR,
+				(errcode(ERRCODE_TRGM_REGEX_TOO_COMPLEX),
+				 errmsg("Too many resulting arcs.")));
+}
+
+/*
+ * Add outgoing arcs from given state.
+ */
+static void
+addArcs(TrgmCNFA *trgmCNFA, TrgmState *state)
+{
+	struct carc *s;
+	TrgmStateKey destKey;
+	ListCell *cell;
+
+	MemSet(&destKey, 0, sizeof(TrgmStateKey));
+
+	/*
+	 * Iterate over keys associated with this output state.
+	 */
+	foreach(cell, state->keys)
+	{
+		TrgmStateKey *key = (TrgmStateKey *) lfirst(cell);
+		s = trgmCNFA->cnfa->states[key->nstate];
+		while (s->co != COLORLESS)
+		{
+			ColorInfo *colorInfo;
+			if (s->co == trgmCNFA->cnfa->bos[1])
+			{
+				/* Should be already handled by addKeys. */
+			}
+			else if (s->co == trgmCNFA->cnfa->eos[1])
+			{
+				/* End of the string ($) */
+				destKey.nstate = s->to;
+
+				/* Assume prefix to become ambiguous after end of the string */
+				destKey.prefix.s[1] = 0;
+				destKey.prefix.s[0] = 0;
+				destKey.prefix.ambiguity = true;
+
+				addArc(trgmCNFA, state, key, &destKey, 0);
+			}
+			else
+			{
+				/* Regular color */
+				colorInfo = &trgmCNFA->colorInfo[s->co];
+
+				if (colorInfo->charsCount > 0
+					&& colorInfo->charsCount <= MAX_COLOR_CHARS)
+				{
+					/* We can enumerate characters of this color */
+					int i;
+					for (i = 0; i < colorInfo->charsCount; i++)
+					{
+						mb_char c = colorInfo->chars[i];
+
+						/*
+						 * ----
+						 * Create new prefix
+						 * 1 (end of prefix)   - current character "c"
+						 * 0 (start of prefix) - end of previous prefix
+						 *
+						 * Zero "c" means non alphanumeric character, this means
+						 * new prefix should indicate start of new trigram.
+						 */
+						destKey.prefix.s[1] = c;
+						destKey.prefix.s[0] = c ? key->prefix.s[1] : 0;
+
+						destKey.nstate = s->to;
+
+						if (destKey.prefix.s[0] || c == 0)
+							destKey.prefix.ambiguity = false;
+						else
+							destKey.prefix.ambiguity = key->prefix.ambiguity;
+
+						addArc(trgmCNFA, state, key, &destKey, c);
+					}
+				}
+			}
+			s++;
+		}
+	}
+}
+
+/*
+ * Get state of trigram CNFA-like graph of given enter key and process it if
+ * needed.
+ */
+static TrgmState *
+getState(TrgmCNFA *trgmCNFA, TrgmStateKey *key)
+{
+	bool		found;
+	TrgmState  *state;
+
+	state = hash_search(trgmCNFA->states, key, HASH_ENTER, &found);
+	if (found)
+		return state;
+	else
+	{
+		if (hash_get_num_entries(trgmCNFA->states) > MAX_RESULT_STATES)
+			ereport(ERROR,
+					(errcode(ERRCODE_TRGM_REGEX_TOO_COMPLEX),
+					 errmsg("Too many resulting states.")));
+		state->arcs = NIL;
+		state->keys = NIL;
+		state->path = NIL;
+		state->fin = false;
+		state->queued = false;
+		addKeys(trgmCNFA, state, key);
+		if (!state->fin)
+			addArcs(trgmCNFA, state);
+	}
+	return state;
+}
+
+#ifdef TRGM_REGEXP_DEBUG
+/*
+ * Log source CNFA.
+ */
+static void
+printCNFA(struct cnfa *cnfa)
+{
+	int state;
+	for (state = 0; state < cnfa->nstates; state++)
+	{
+		struct carc *s;
+		elog(NOTICE, "STATE %d", state);
+		s = cnfa->states[state];
+		while (s->co != COLORLESS)
+		{
+			elog(NOTICE, "ARC %d %d", s->co, s->to);
+			s++;
+		}
+	}
+}
+
+/*
+ * Log resulting trigram-based CNFA-like structure.
+ */
+static void
+printTrgmCNFA(TrgmCNFA *trgmCNFA)
+{
+	HASH_SEQ_STATUS scan_status;
+	TrgmState *state;
+
+	elog(NOTICE, "INITSTATE %p", (void *)trgmCNFA->initState);
+
+	hash_seq_init(&scan_status, trgmCNFA->states);
+	while ((state = (TrgmState *) hash_seq_search(&scan_status)) != NULL)
+	{
+		ListCell *cell;
+		elog(NOTICE, "STATE %p %d", (void *)state, (int)state->fin);
+		foreach(cell, state->keys)
+		{
+			TrgmStateKey *key = (TrgmStateKey *) lfirst(cell);
+			elog(NOTICE, "KEY %08X %08X %d %d", key->prefix.s[0],
+				key->prefix.s[1], (int)key->prefix.ambiguity, key->nstate);
+		}
+
+		foreach(cell, state->arcs)
+		{
+			TrgmArc *arc = (TrgmArc *) lfirst(cell);
+			elog(NOTICE, "ARC %p %08X %08X %08X", (void *)arc->target,
+					(uint32)arc->trgm[0], (uint32)arc->trgm[1], arc->trgm[2]);
+		}
+	}
+}
+
+/*
+ * Log path matrix on trigrams.
+ */
+static void
+printTrgm(TRGM *trg, char *paths)
+{
+	int			i,
+				pathsCount,
+				trgmCount,
+				bitmaskSize,
+				j;
+	for (i = 0; i < ARRNELEM(trg); i++)
+	{
+		elog(NOTICE, "TRGM %c %c %c",
+			 GETARR(trg)[i][0], GETARR(trg)[i][1], GETARR(trg)[i][2]);
+	}
+
+	trgmCount = ARRNELEM(trg);
+	bitmaskSize = (trgmCount + 7) / 8;
+	pathsCount = *((int *)paths);
+	for (i = 0; i < pathsCount; i++)
+	{
+		char *path = paths + sizeof(int) + i * bitmaskSize;
+		char msg[1024], *p;
+		p = msg;
+
+		for (j = 0; j < trgmCount; j++)
+		{
+			if (GETBIT(path, j))
+				*p++ = '1';
+			else
+				*p++ = '0';
+		}
+		*p = 0;
+		elog(NOTICE, "%s", msg);
+	}
+}
+#endif
+
+/*
+ * Compare function for sorting of Trgm datatype.
+ */
+static int
+trgmCmp(const void *p1, const void *p2)
+{
+	return memcmp(p1, p2, sizeof(Trgm));
+}
+
+/*
+ * Calculate vector of all unique trigrams which are used
+ */
+static void
+getTrgmVector(TrgmCNFA *trgmCNFA)
+{
+	HASH_SEQ_STATUS scan_status;
+	int			totalCount = 0, i = 0;
+	Trgm	   *p1, *p2;
+	TrgmState  *state;
+
+	hash_seq_init(&scan_status, trgmCNFA->states);
+	while ((state = (TrgmState *) hash_seq_search(&scan_status)) != NULL)
+	{
+		ListCell *cell;
+		foreach(cell, state->arcs)
+		{
+			totalCount++;
+		}
+	}
+	trgmCNFA->trgms = (Trgm *) palloc(sizeof(Trgm) * totalCount);
+
+	hash_seq_init(&scan_status, trgmCNFA->states);
+	while ((state = (TrgmState *) hash_seq_search(&scan_status)) != NULL)
+	{
+		ListCell *cell;
+		foreach(cell, state->arcs)
+		{
+			TrgmArc *arc = (TrgmArc *) lfirst(cell);
+			memcpy(&trgmCNFA->trgms[i], &arc->trgm, sizeof(Trgm));
+			i++;
+		}
+	}
+
+	if (totalCount < 2)
+	{
+		trgmCNFA->trgmCount = totalCount;
+		return;
+	}
+
+	qsort(trgmCNFA->trgms, totalCount, sizeof(Trgm), trgmCmp);
+
+	/* Remove duplicates */
+	p1 = trgmCNFA->trgms;
+	p2 = trgmCNFA->trgms;
+	while (p1 - trgmCNFA->trgms < totalCount)
+	{
+		if (memcmp(p1, p2, sizeof(Trgm)) != 0)
+		{
+			p2++;
+			memcpy(p2, p1, sizeof(Trgm));
+		}
+		p1++;
+	}
+	trgmCNFA->trgmCount = p2 + 1 - trgmCNFA->trgms;
+}
+
+/*
+ * Compare two paths in trigram CNFA-like structure. "contain" means that "new"
+ * path contain all trigrams from "origin" path. "contained" means that "origin"
+ * cotain all trigrams from "new" path.
+ */
+static void
+compareMasks(char *new, char *origin, int len, bool *contain, bool *contained)
+{
+	int			i;
+	*contain   = true;
+	*contained = true;
+	for (i = 0; i < len; i++)
+	{
+		if ((~new[i]) & origin[i])
+			*contain = false;
+		if (new[i] & (~origin[i]))
+			*contained = false;
+	}
+}
+
+/*
+ * Add new path into path matrix.
+ */
+static void
+addPath(List **pathMatrix, TrgmStatePath *path, int len, bool *modify)
+{
+	ListCell   *cell, *prev, *next;
+	int			count = 0;
+
+	*modify = false;
+	prev = NULL;
+	cell = list_head(*pathMatrix);
+	while(cell)
+	{
+		bool contain, contained;
+
+		next = lnext(cell);
+		compareMasks(path->path,
+					 ((TrgmStatePath *) lfirst(cell))->path,
+					 len, &contain, &contained);
+
+		if (contain)
+		{
+			/* We already have same or wider path in matrix. Nothing to do. */
+			return;
+		}
+		if (contained)
+		{
+			/* New path is wider than other path in matrix. Delete latter. */
+			*pathMatrix = list_delete_cell(*pathMatrix, cell, prev);
+		}
+		else
+		{
+			prev = cell;
+			count++;
+		}
+
+		cell = next;
+	}
+	*modify = true;
+	if (count >= MAX_RESULT_PATHS)
+		ereport(ERROR,
+				(errcode(ERRCODE_TRGM_REGEX_TOO_COMPLEX),
+				 errmsg( "Too many paths.")));
+	*pathMatrix = lappend(*pathMatrix, path);
+}
+
+/*
+ * Add path to path matrix of corresponding path.
+ */
+static void
+adjustPaths(TrgmCNFA *trgmCNFA, TrgmState *state, TrgmStatePath *path)
+{
+	bool		modify;
+
+	if (state->fin)
+	{
+		/*
+		 * It's a final state. Add path to the final path matrix.
+		 */
+		addPath(&trgmCNFA->path, path, trgmCNFA->bitmaskLen, &modify);
+	}
+	else
+	{
+		addPath(&state->path, path, trgmCNFA->bitmaskLen, &modify);
+
+		/* Did we actually change anything? */
+		if (!modify)
+			return;
+
+		/*
+		 * Plan to scan outgoing arcs from this state if it's not done already.
+		 */
+		if (!state->queued)
+		{
+			trgmCNFA->queue = lappend(trgmCNFA->queue, state);
+			state->queued = true;
+		}
+	}
+}
+
+/*
+ * Process queue of trigram CNFA-like states until we collect all the paths.
+ */
+static void
+processQueue(TrgmCNFA *trgmCNFA)
+{
+	while (trgmCNFA->queue != NIL)
+	{
+		TrgmState *state = (TrgmState *) linitial(trgmCNFA->queue);
+		ListCell *arcCell, *pathCell;
+
+		state->queued = false;
+		trgmCNFA->queue = list_delete_first(trgmCNFA->queue);
+
+		foreach(pathCell, state->path)
+		{
+			TrgmStatePath *path = (TrgmStatePath *) lfirst(pathCell);
+			if (!path->queued)
+				continue;
+			foreach(arcCell, state->arcs)
+			{
+				TrgmArc *arc = (TrgmArc *) lfirst(arcCell);
+				int index;
+				size_t size;
+				TrgmStatePath *pathCopy;
+
+				/* Create path according to arc (with corresponding bit set) */
+				size = sizeof(bool) + sizeof(char) * trgmCNFA->bitmaskLen;
+				pathCopy = (TrgmStatePath *)palloc(size);
+				memcpy(pathCopy, path, size);
+				index = (Trgm *)bsearch(&arc->trgm, trgmCNFA->trgms,
+									trgmCNFA->trgmCount, sizeof(Trgm), trgmCmp)
+						- trgmCNFA->trgms;
+				SETBIT(pathCopy->path, index);
+				adjustPaths(trgmCNFA, arc->target, pathCopy);
+			}
+			path->queued = false;
+		}
+	}
+}
+
+/*
+ * Convert trigram into trgm datatype.
+ */
+static void
+fillTrgm(trgm *ptrgm, Trgm trgm)
+{
+	char		text[14], *p;
+	int			i;
+
+	/* Write multibyte string into "text". */
+	p = text;
+	for (i = 0; i < 3; i++)
+	{
+		int len;
+		if (trgm[i] != 0)
+		{
+			len = strnlen((char *)&trgm[i], 4);
+			memcpy(p, &trgm[i], len);
+			p += len;
+		}
+		else
+		{
+			*p++ = ' ';
+		}
+	}
+	*p = 0;
+
+	/* Extract trigrams from "text" */
+	cnt_trigram(ptrgm, text, p - text);
+}
+
+/*
+ * Final pack of path matrix: convert trigrams info trgm datatype and remove
+ * empty columns from the matrix.
+ */
+static TRGM *
+finalPack(TrgmCNFA *trgmCNFA, MemoryContext context, PackedTrgmPaths **pathsOut)
+{
+	ListCell   *cell;
+	char	   *unionPath;
+	int			i, nonEmptyCount = 0, j;
+	TRGM	   *trg;
+	trgm	   *trgms;
+	int			newBitMaskLen, pathIndex = 0;
+	PackedTrgmPaths *newPaths;
+
+	/* Calculate union of all path of order to detect empty columns */
+	unionPath = (char *) palloc0(sizeof(char) * trgmCNFA->bitmaskLen);
+	foreach(cell, trgmCNFA->path)
+	{
+		char *path = ((TrgmStatePath *) lfirst(cell))->path;
+		for (i = 0; i < trgmCNFA->bitmaskLen; i++)
+			unionPath[i] |= path[i];
+	}
+
+	/* Count non-empty columns */
+	for (i = 0; i < trgmCNFA->trgmCount; i++)
+	{
+		if (GETBIT(unionPath, i))
+			nonEmptyCount++;
+	}
+
+	/* Convert trigrams into trgm datatype */
+	trg = (TRGM *) palloc0(TRGMHDRSIZE + nonEmptyCount * sizeof(trgm));
+	trg->flag = ARRKEY;
+	SET_VARSIZE(trg, CALCGTSIZE(ARRKEY, nonEmptyCount));
+	trgms = GETARR(trg);
+	j = 0;
+	for (i = 0; i < trgmCNFA->trgmCount; i++)
+	{
+		if (GETBIT(unionPath, i))
+		{
+			fillTrgm(&trgms[j], trgmCNFA->trgms[i]);
+			j++;
+		}
+	}
+
+	/* Fill new matrix without empty columns */
+	newBitMaskLen = (nonEmptyCount + 7) / 8;
+	newPaths = (PackedTrgmPaths *)
+		MemoryContextAllocZero(context,
+							   offsetof(PackedTrgmPaths, data)
+			+ newBitMaskLen * sizeof(char) * list_length(trgmCNFA->path));
+	newPaths->count = list_length(trgmCNFA->path);
+	foreach(cell, trgmCNFA->path)
+	{
+		char *path = ((TrgmStatePath *) lfirst(cell))->path;
+		char *path2 = &newPaths->data[newBitMaskLen * pathIndex];
+		j = 0;
+		for (i = 0; i < trgmCNFA->trgmCount; i++)
+		{
+			if (GETBIT(unionPath, i))
+			{
+				if (GETBIT(path, i))
+					SETBIT(path2, j);
+				j++;
+			}
+		}
+		pathIndex++;
+	}
+	*pathsOut = newPaths;
+	return trg;
+}
+
+/*
+ * Main function of regex processing. Returns an array of trigrams and a paths
+ * matrix of those trigrams.
+ */
+TRGM *
+createTrgmCNFA(text *text_re, MemoryContext context, PackedTrgmPaths **pathsOut)
+{
+	HASHCTL		   hashCtl;
+	struct guts   *g;
+	TrgmStateKey   key;
+	TrgmCNFA	   trgmCNFA;
+	TrgmStatePath *path;
+	regex_t		  *regex;
+	TRGM		  *trg;
+	MemoryContext  ccxt = CurrentMemoryContext;
+
+	PG_TRY();
+	{
+#ifdef IGNORECASE
+		regex = RE_compile_and_cache(text_re, REG_ADVANCED | REG_ICASE, DEFAULT_COLLATION_OID);
+#else
+		regex = RE_compile_and_cache(text_re, REG_ADVANCED, DEFAULT_COLLATION_OID);
+#endif
+		g = (struct guts *) regex->re_guts;
+
+		/* Collect color info */
+		trgmCNFA.cnfa = &g->search;
+		trgmCNFA.path = NIL;
+		trgmCNFA.queue = NIL;
+		trgmCNFA.colorInfo = getColorInfo(regex);
+		trgmCNFA.arcsCount = 0;
+
+#ifdef TRGM_REGEXP_DEBUG
+		printCNFA(&g->search);
+#endif
+
+		/* Create hash of states */
+		hashCtl.keysize = sizeof(TrgmStateKey);
+		hashCtl.entrysize = sizeof(TrgmState);
+		hashCtl.hcxt = CurrentMemoryContext;
+		hashCtl.hash = tag_hash;
+		hashCtl.match = memcmp;
+		trgmCNFA.states = hash_create("Trigram CNFA",
+		   1024,
+		   &hashCtl,
+		   HASH_ELEM | HASH_CONTEXT
+		   | HASH_FUNCTION | HASH_COMPARE);
+
+		/* Create initial state of CNFA-like graph on trigrams */
+		MemSet(&key, 0, sizeof(TrgmStateKey));
+		key.prefix.s[0] = 0;
+		key.prefix.s[1] = 0;
+		key.nstate = trgmCNFA.cnfa->pre;
+		key.prefix.ambiguity = true;
+
+		/* Recursively build CNFA-like graph on trigrams */
+		trgmCNFA.initState = getState(&trgmCNFA, &key);
+
+#ifdef TRGM_REGEXP_DEBUG
+		printTrgmCNFA(&trgmCNFA);
+#endif
+
+		/* Get vector of unique trigrams */
+		getTrgmVector(&trgmCNFA);
+		trgmCNFA.bitmaskLen = (trgmCNFA.trgmCount + 7) / 8;
+
+		/*
+		 * Create add empty path to initial state, and create matrix by
+		 * processing queue (BFS search).
+		 */
+		path = (TrgmStatePath *) palloc0(sizeof(bool) +
+											sizeof(char) * trgmCNFA.bitmaskLen);
+		path->queued = true;
+		adjustPaths(&trgmCNFA, trgmCNFA.initState, path);
+		processQueue(&trgmCNFA);
+
+		/* Final pack of paths matrix */
+		trg = finalPack(&trgmCNFA, context, pathsOut);
+
+#ifdef TRGM_REGEXP_DEBUG
+		printTrgm(trg, *pathsOut);
+#endif
+	}
+	PG_CATCH();
+ 	{
+		ErrorData  *errdata;
+		MemoryContext ecxt;
+
+		ecxt = MemoryContextSwitchTo(ccxt);
+		errdata = CopyErrorData();
+		if (errdata->sqlerrcode == ERRCODE_TRGM_REGEX_TOO_COMPLEX)
+		{
+			trg = NULL;
+			FlushErrorState();
+		}
+		else
+		{
+			MemoryContextSwitchTo(ecxt);
+			PG_RE_THROW();
+		}
+ 	}
+ 	PG_END_TRY();
+	return trg;
+}
diff --git a/doc/src/sgml/pgtrgm.sgml b/doc/src/sgml/pgtrgm.sgml
index 30e5355..c4105e1 100644
--- a/doc/src/sgml/pgtrgm.sgml
+++ b/doc/src/sgml/pgtrgm.sgml
@@ -145,9 +145,10 @@
    operator classes that allow you to create an index over a text column for
    the purpose of very fast similarity searches.  These index types support
    the above-described similarity operators, and additionally support
-   trigram-based index searches for <literal>LIKE</> and <literal>ILIKE</>
-   queries.  (These indexes do not support equality nor simple comparison
-   operators, so you may need a regular B-tree index too.)
+   trigram-based index searches for <literal>LIKE</>, <literal>ILIKE</>,
+   <literal>~</> and <literal>~*</> queries.  (These indexes do not
+   support equality nor simple comparison operators, so you may need a
+   regular B-tree index too.)
   </para>
 
   <para>
@@ -203,6 +204,23 @@ SELECT * FROM test_trgm WHERE t LIKE '%foo%bar';
   </para>
 
   <para>
+   Beginning in <productname>PostgreSQL</> 9.3, these index types also support
+   index searches for <literal>~</> and <literal>~*</> (regular expression
+   matching), for example
+<programlisting>
+SELECT * FROM test_trgm WHERE t ~ '(foo|bar)';
+</programlisting>
+   The index search works by extracting trigrams from the regular expression
+   and then looking these up in the index.  The more trigrams could be
+   extracted from regular expression, the more effective the index search is. 
+   Unlike B-tree based searches, the search string need not be left-anchored.
+   However, sometimes regular expression is too complex for analysis, then
+   it performs the same as when no trigrams can be extracted from regular
+   expression. In this situation full index scan or sequential scan will
+   be performed depending on query plan.   
+  </para>
+  
+  <para>
    The choice between GiST and GIN indexing depends on the relative
    performance characteristics of GiST and GIN, which are discussed elsewhere.
    As a rule of thumb, a GIN index is faster to search than a GiST index, but
diff --git a/src/backend/utils/adt/regexp.c b/src/backend/utils/adt/regexp.c
index 92dfbb1..b30e753 100644
--- a/src/backend/utils/adt/regexp.c
+++ b/src/backend/utils/adt/regexp.c
@@ -128,7 +128,7 @@ static Datum build_regexp_split_result(regexp_matches_ctx *splitctx);
  * Pattern is given in the database encoding.  We internally convert to
  * an array of pg_wchar, which is what Spencer's regex package wants.
  */
-static regex_t *
+regex_t *
 RE_compile_and_cache(text *text_re, int cflags, Oid collation)
 {
 	int			text_re_len = VARSIZE_ANY_EXHDR(text_re);
diff --git a/src/include/regex/regex.h b/src/include/regex/regex.h
index 616c2c6..7e19e8a 100644
--- a/src/include/regex/regex.h
+++ b/src/include/regex/regex.h
@@ -171,5 +171,6 @@ extern int	pg_regprefix(regex_t *, pg_wchar **, size_t *);
 extern void pg_regfree(regex_t *);
 extern size_t pg_regerror(int, const regex_t *, char *, size_t);
 extern void pg_set_regex_collation(Oid collation);
+regex_t *RE_compile_and_cache(text *text_re, int cflags, Oid collation);
 
 #endif   /* _REGEX_H_ */
#25Alexander Korotkov
aekorotkov@gmail.com
In reply to: Heikki Linnakangas (#24)
1 attachment(s)
Re: WIP: index support for regexp search

On Mon, Nov 26, 2012 at 4:55 PM, Heikki Linnakangas <hlinnakangas@vmware.com

wrote:

Great, that top-level comment helped tremendously! I feel enlightened.

I fixed some spelling, formatting etc. trivial stuff while reading through
the patch, see attached. Below is some feedback on the details:

* I don't like the PG_TRY/CATCH trick. It's not generally safe to catch an
error, without propagating it further or rolling back the whole
(sub)transation. It might work in this case, as you're only suppressing
errors with the special sqlcode that are used in the same file, but it
nevertheless feels naughty. I believe none of the limits that are being
checked are strict; it's OK to exceed the limits somewhat, as long as you
terminate the processing in a reasonable time, in case of pathological
input. I'd suggest putting an explicit check for the limits somewhere, and
not rely on ereport(). Something like this, in the code that recurses:

if (trgmCNFA->arcsCount > MAX_RESULT_ARCS ||
hash_get_num_entries(trgmCNFA-**>states) > MAX_RESULT_STATES)
{
trgmCNFA->overflowed = true;
return;
}

PG_TRY/CATCH trick is replaced with some number of if/return. Code becomes
a bit more complicated, but your notes does matter.

And then check for the overflowed flag at the top level.

* This part of the high-level comment was not clear to me:

* States of the graph produced in the first stage are marked with

"keys". Key is a pair
* of a "prefix" and a state of the original automaton. "Prefix" is a last
* characters. So, knowing the prefix is enough to know what is a trigram
when we read some new
* character. However, we can know single character of prefix or don't
know any
* characters of it. Each state of resulting graph have an "enter key"
(with that
* key we've entered this state) and a set of keys which are reachable
without
* reading any predictable trigram. The algorithm of processing each state
* of resulting graph are so:
* 1) Add all keys which achievable without reading of any predictable
trigram.
* 2) Add outgoing arcs labeled with trigrams.
* Step 2 leads to creation of new states and recursively processing
them. So,
* we use depth-first algorithm.

I didn't understand that. Can you elaborate? It might help to work through
an example, with some ascii art depicting the graph.

This comment is extended with example.

* It would be nice to add some comments to TrgmCNFA struct, explaining
which fields are valid at which stages. For example, it seems that 'trgms'
array is calculated only after building the CNFA, by getTrgmVector()
function, while arcsCount is updated on the fly, while recursing in the
getState() function.

TrgmCNFA comment is extended with this.

* What is the representation used for the path matrix? Needs a comment.

Comments are added to PackedTrgmPaths and TrgmStatePath.

* What do the getColorinfo()

getColorInfo comment now references to ColorInfo struct which have comment.

and scanColorMap() functions do?

scanColorMap comment now have description of colormap structure.

What exactly does a color represent?

This is added to the top comment.

What's the tradeoff in choosing MAX_COLOR_CHARS?

Comment is added to the macro.

------
With best regards,
Alexander Korotkov.

Attachments:

trgm-regexp-0.6.patch.gzapplication/x-gzip; name=trgm-regexp-0.6.patch.gzDownload
�+��P�<kw�H������MX`��d�sh�$�ql/v&3��r
���D����N�������v��]���[�n�w�*���SQ���P�=�sC���-g���-�>�K5�%&����J����h���v���Z�����V�?��z�Vk��zR�T����Z�n����C����!���#���������=��y�T����sh�����y�mfa���y�c��������I����A�P�6j�Z��I"w)�K9SV�I�E�����S�_}5S���Z�mJS*3TV�P��p����mS�^����W�)Uo��
���zE[�S:(�D`/lG�vx]����v������)�"::m�[����wUf��������t<�
B�����!�~*~6��u�%���;��Q���&$42�����+���Q������D�pE��j�|%B�\�����/&�4�R�i��L�?!���_�r�����+�����O����~6lP�JJK3��v�K�D��iQ��h�����,�M�~�VMQJ�
���n��]����]�|�����;�6^'|M��b��=���x�zd��s8|���Z�)�5:_�������Y�R����r������S��V�/��6�sl��R�'&�c�������`p#��t�y��A����X�Z����)�� p��p,o��sN:�-�����~���8=��#�v������1��9��N�a�&�D���OK1&�8���~�]��1�
p��F������������ck�6��f��w���o����$��z��Al�q����k�}�'����c\��y�?��@�i�3�[$�;�4��p�a������>��-5�Gc���_��'w���9�?�;u�Fg?�������+�����&\�n�9����L	���'e�����:�1�c���2��&'�R!L_�P��
B��m��LPX~&�����r��Q�@}
L�����[>Y�|����m���i�o�j�N��07�w�h�W���j#�F��Gl�t" �(MS����u]v-�]A������D�%|bw5���@�����`���o���������g�?@*Q(4iY@iS��/�:�=��JM��o��I�Dc<��H�T��z0�>��#���`}��B+p��
JC��l�}���qt U�2O�7�^*�\�T����r��E����4�{�\he�:��F'������fB�3{���m8<;=9��������b��FG'��F%Y.���������"7�g����J�EY�x!J���b#�o���y�z�Q������������d���1/��	>[6<����r�����������HR���JHr�7���b��C)D����RI��5M[Avwj� ���h[������X��}�Q��*��7�����nx1�J��X
�!�)���wq��G�G�j��0�dx<�C>V������o�M	�^�.��~V������WK_�
%��M�R��@,$���5Q4��
� a!�(�	�Y��b|1��+0��B�9P��LcK���Tf�����uPCi�i���o���4�d��Z��h���u0+��D }�������
(��rMi^�����0�,=�:d!4_p�H���<�_���p'���c��Z�~d���+�+�]0e��1����/��C�I�RY��3�%1��|WLO�m.5;�R��(���*3�*�����>����i`"E���W�c����8'��4��(L7C6YBl��H�7	t�y��1FU	k�'�����o�m1n�|����i��5�S����sd�����-�������� l7���sl����y��HP��q����E}k�B'����;�%1�F{:���j�i������ls"��k�L���i:{7~�������d<�;/s��1�I�s(�O5�����M��SQ@���`:�Zh� g�n|1�����T�bu�C5p.K8�ZW�����J
��'�1�#N�|��n��
 bT]���_�&�����Z�W�	<��� k����1�@@�;�����Hfw#�y��Yp�dt��@I��@}���.��DI#S�|<>����@���q��Q
�@�N� ���Bpe#+K�P
�r~
:�����B�~*�����U�~��W�R�7��&�ZK�U-`��,�I��+�W��,��)VA�����v��h�6�U��Q�
��2y]��I�	i��X�,��!�B����%P���do��<b��/R"�4��vIyC�������KL������������`p>���x��p4:��Ir��\B����D^�l'�C��J�"Y��.�����cq�~����-���1��\��bj������:��/L��/�@L cN��z���sY��2���Jo$q��{9��A=$u�A���SN;9{��T�)���jI������/!���zI'���,b��?+��W[�z>�`��������iw��*e�(��dH)/�l�~���<����	"'|I��=ay����mj��g�g=�y�A�;:���������-���F������chl�UR����NK$�MbE�#�W�7s��V��]�>��*IklR����x��J-!'\,!������,v������B {��h���$whp
L������
���sE���Ku�@�ZMi�yP�sQ��t���L�����r�:��
fo�����#�������&������4rM�s�&�	�q;�de�al�p��F�����ilMyz_�>���W�*~��u�F����q��	4���O���5p�����1o��:����/�=������,�1���S6�F����O��C�t"wR�GW��[����DX�7�%�������[���&B^�>^�r�.z
88v!b,�z1��
�wqOf���q^�����DVe���U��U�������[�a+A�
Y1����:�W�����Y��$"�8CS��S�S�P�k�yHf`t?]���#~���SR���|IBi2�f�.,'�D�'�1�1�M����K6��=j���L�-7W)�o�A��5�Z�Zm�!e���V� \[j��X�����T$�5!�% ,�pab����@��0�]aF>d����QK�)���V�T��Ie��<�2��J�U]:�4:W���It��p��d��Hp���c���l^K �:����sE`��4� �#�>}!��Ax�
�Z D�d����!�9H+p|r�o����"���3Q�������8�^�Q�Jio{�l=�c���N�0�a�t�v1�a�8�@#�O�����L,�u�~3��Fzz��'�� q���z�^��-��dV�<H8�O�����Tn1PY�������@�v�x���.'z}��������R���q(~�t�F���{��E�`]�����p���T���������z<�1���'�7���*��5�r�x�Z�������8��B�cO���]3o[
��J�a��3>?�!/L�dy� ����c�C,p�I&E�)p��(I�u
Y�e)�\cV5Au���^v�����~����.��fo�h�5w���!,ZA��T�c��{6���$9���9q�k�����P���`|UR�^������.��({��=�Uo���JI����Wtt|x0�U
�-k����
���N���2CV\�:(R7�c�w�������$�V�a���`rI<������������Ba�����{
+>Z�"^>�Z-���-?�����B������N��`�b;�������h=�'�.�Hw?g7����q�O���q��o���j�N�.'�:	���������z�p�hO��wV�/��%����gK0�+��
K#|O1����^����ja[Jb�D�g����C���y��.�}3:�wb�t���ch�6��	�d0�5��r�[������SL��dc��i��t&^�%xT�$`S����i����2|Pf����-%�B�K$������`�t{�:�_�A�y����;�tF�
K_+T`��{W�V&"��cJ4��.��<$�)]Ln�G����g���Q1Ts�����,��f�U�ZN����p�@���!K{��`�n�eL����G�BF�d�tq��#RM���������+���
XD�,.�Bvdf�Vf���h��r����E�,<�.K�F�����AG�y08n������� ��J��W2���C��7]�bl�s��b+�VFEX�
&�:��0�O+��!t�qm�LV��^�"���1��U�Hw���H`�h����;mz#�,4��B�����o�H�3�don����1��,�?)�]J��)����e:�l)�J/����UU&5��2J��L���D�yA8���kEw��f[�i
��� U����$���EKe��U��.�1����d\����M�%L��~���(�(�y�V8������ANr���B8k��X#_�K����n�������_<��!��N����>@�t�����UGx�h��:-rE+g"�i��(S�F�9�8Y�U��>�=3����d����HR[%1g�D��)x�
�=��-����[�������S��Vo����Jdn^�&��U����R�Hc�v���5M�gy��j��f��g%���&26��tY +vMv�JYY���\5�{b�z9Y��j���yQ���MS�I:�wim�)�0���������-���J�D�L��:�@8�0;�I�_���s��.I��\H�r�h6G�b?�nf0�wf�P>W���s��P�90��a�p����k�c���G�<w'dh��������p�F�V@�p$V|W����EQ�j��g�j`���gi���xb9���)����y9�
�%#�g>o_�`X�e�!��dQ���P�]�����j/����p�%2_�m-U�������^���v��m-�|�M��vJr����T������E~����TnAJ��8�Yj��l3	��&w�!&�)tz�GN>���{~���B���c���|�j~���lC������w���FEPy��8������MBt��L*(�39O��x��e6dG�v;
����Z,�(�e�0D�6�@9�*X,��k���N����6jYj�1>b!�����7�XG�r�D���u���x��u�Gw��T�d<y����5�o4����ZL(�,[��	DA�9(��
&�]j����$.d�
�d1($"�R������>	��;�Z`h�X���=��������i��ch��&.O��B
�;k�W�]��C/F�&5)��,m�����~	�a���,c��>q
`	��&�)'f:M;&��!jm<��7V'nm��x�o��R?
���IGc�����J���NL��
���Q�U?�:*h�of�u���tX�he#��������Q���"^�JX���HL!������%�1m�����I���d{�������?aJ�'P���"�dq��`�aG��^F���A~	-�J�{LIx
=��z��n�u�����!.��0>�A�7ux�P�b��<}](}�s��1z��^aN��]���?R�R
���`)�t1��m;0���������|��?�=kwG���_��l�dd��dx�1|bc�<����r�n�+j	��L~��g���nI@fv>,'���z�����&���v(���%��=�������O��_���3=����H	��{K��D�&����<�{������ply���.��O�����h�"E.&�e�@&������� ?2+w��\\_�"|�C���J
~�a	�K����:�:?��>�<~��K����`F2��)�����0���"p �����a1��F6q�9p9W�d0��5�����e���%��4���
��N�!}O�)������<�w9������QB\����o����$���4���|}��x�T���'���
�I�����l�@�`���p��7��t���b1Km�������G/O^�u�2v�q��w��g��g5D�{5J��d��,�0
(��f�`�Q��	�v*^�2"�u;G����EM��s����{~qx�9Ov	��	[�El
�(�U�������������^^<Zrx�5����/��`������q�������4������S�#�F	5g�=I�8�f2�I/��8.����u�����������*RN.4�=�����h12��������\B��b5��{,���#E
I&*��m�lx
�i2*������>����W�OF�]���9�����f!����f\bF���`0�]�1&�d��*FV�H������g}#`�KH5/�{�CZL�Pu���lcq��F���y@��v��)|AY`c��������<q����{
��q��M���"�-�IK�G��%g���������i��I_�
�F1@E� �������=|�K�7)���9��\*��7�|D�H��N��4�zcc��I���po���J�7��$^�{=&�Q|��e���)Q�R�tc�h��Gd�<�9�|�^A��J�(7��(����Z�������2�z���@��'������0G��.C�Rh�� ���(�0sO��6'�0�C�J
AS(z.i�f���,�6��2��>����J=���U��V7�%}�*o�c�;�W�N��������<���r��Gmd���=��i~EJ{h��H�(��V����T�C�c$%6�b�M��.�F<��P��Y���2�]�:,:{
��$�%�N��\����`Jc��pc�S�d�3P}����j`$?$�K�_�
,��#DKA�#�R�������?'R����[����' �q�0�F��p�G.^�1��S@��<�D"(>���	7��;oM*��+��c��d��u�����QJ���^��{0�bW��A�5(�,�W���1S��H*��.�{����;����LDzB"�����:A`s�S�����<�(��HZ
��L�18-r,��8��f.��4z�li�\I��%9U>#�
�yx��*��K�� ��uO���i@���[��?��y�P�Rb�u��R��V<�m�
�83��34�����]�/�-����& *@�I���M���q"aW����@��4��IF],�Ak%��������X8a$��8"�Ef��`:d2p��$��#�d��f�	k������`�&p�|���?�E�������8�mm��K���YXC��NH�M�r����:��8RQHwp��o�+@��J%�C���
-9����b��d5������XCD��(��*1RPB�������l*S=;���H��4��8U(��[y�����<y�~���Z�:6���o��?�E��#J�}D"��cV����/�;��p�I8�P6�_>����0�9�IpEu����
;��ba[���}�7�����h�-����t�<����]<O��}�9E��o���%���.G����-hu����6H |?<��W�?���k�_�����G��W�xU �@A��FB�����G2e�3��_���K�{lJ���5YK����o�q\�F7_��/Y � �c8�d����}}�"��s�W�o$��"�\�mhY�.��o����=����Q�D~���e`PLn���<��pFj��-�lA�<�h���o-�Z�m�}#����H������gDg�����Y��@o�V�zS�j��!�z^9��8w�-�|�M�����><�
p8�< �Ph�i�U{@2j����I\h�G�cd0T���9EW����"�?��u#��(:& N5�^�r
n��,�;uC��frR�,/�<��
J�&s�o����X>`��!�
�i �:�5�����e��-������F��K
2_���%��h(`
��C`C;��7�-�9���~�9}�����F���k��d�\-60wE!�7<��:��h;�cI��]|�N�nq��������!p�{�	�2i$F^��$;����[�R���E�-���o<�N_����`u`��n����3�D��a6~O[Bb��7�9�F�V�K?&���8����1K����5$��(�=��B���(��}�u���\���l���Y���%��_��D�lX����]5�#1���14��4y�0�2��Cy�C&o�|�	A���2��<~8op����2�i�	G:�6"QFuY��j*��n�����~�������h�6��C������\1c��g� |*&�&R"rk�/S�G)5H0@��8E�.�����q�7���e�3�� ��:�3��k/:!�\�4+�Qyi}�����J`�UpR"����J�'Nh��_����7'[�p�Qw���0�(�Obcc�������G���yz��Q�]h�c��f���.0���{0K������kX6�����p�G���"���&��9�M�f��(k�J�
�(��A����<*�H�3H�"�g�����:����No ���h @W	��r���X�U������Dl���lnyr������*aJx@/�]���Z3E����P#Q�8�}]>a�~)��wL9���6)����>�������Q��l��������o�>�I��8����W���)<l��,�.+�mLP���Jt8��Y�zZ�	d@��G��}�X��#p���q{b�Og���0X&��^5�2��|R|�*�&�0��_�`j���#5I�a�3��im������f��O�:&O�I��O����	����n�O���8Z\�Ked� N^<�]������[�&8f���B�J�/�����c�
yi8�*N�c@�O�fL�i�RB��t?)<��N���G��t��&J��gY�d	y.	�����b��M�j�p^�*�.g6�7>2"��������+�D=W���H}��w"=)tnM�G)�{��
:��M��y�&vs4���W�:���U��z��B��@�!]�12�hC�\�����U����hv�>�T���
��������z2�C������.��}N�-7�{�vq���g��<�;l���������z1k��$���������C�&6I �{�/��>@4$'��u���J��<����mrG0�[W/��Q,S�W�d�,R��-d��V	��7A�h�*.�x��)��W���)�/�0����!����`<���O��]����d�Wp�F�c-���[{L(Scr�QB��I����\��9�'��K�p9���S�s����d��Xs4uQhy��r���-�K�����9��!j����������XA�
J�[(��9�0�{�-H[1�MZ��9���!I�.|Z���t�����_��0��SE>�6(H�}������1�+\�g�j��O}:��F��1�����7#}����<��7vT,�x=u{>7�Rn
�
:wC\$*`��W1��d���P��^V�2����p����V�$���m.��V���(��=�8�&��a���_G#hV��E�UV��KV���HJ��"G�ge�)�t��,+O�Z	����yuv�]�f����
[�-Sk�v�Q���M|C2/��j��p@�����}X���������7d	QSu)�m���G�Q�gU���5�(��}���k�#����=�&�?L�k����Jj<��B0<���V������D��u�p].��dVN@�p�m 4��v�������Du�+h��\T���QC�PK��wavJ�}�,������]M���*\�*���#0���+�f�8+IW��M�K���Y�s�]��F
_8I��w'��'y����mk��:��������0:a�1(���W�+!������$��c�z��C���"�z���H��n���X�J'������1�m�HW-�#��8��%:���2�(�>~����	{�B7(
G��������	��&��5�o��(Y��73��g���Q�fs��E?�I�����eZq��'�����W�H�i�����\�� ��.�2/`[�d'�K�����8�e��L|]�P$�G3g�e�d=����*�!.@	s&L�N����~F~��t���$�:d���`=����V���y���>�J�7.������*�|DH����0�K��;��Mn6+K�#$'�y����2���������b��'A�2��p�+����
<Z����GU.�~���\��a!y�4!�s��'��r�g�F,�Q7!���T��Lq�s�]#�~���%"o ��z�@�]C���w}�7�|�H�]���@��W��,k���*7�g��Y�J��\>U�X|R%���0
�3a��d��;�'��o� (��
9����V��h�.gC1���_������n�%�=c���*�,���^��d��P�ws��6

��C��\Xc=�L9�C����Nu����2p�x����B?�����l�1M�Kd_��R��z\�[�</�U�8����u���U�`�C��%�Dz�N&�6������<tS��z����l����;S��0a�o,�/�X���
�B��D���k�EF�X�Og��~@�b�'�+6����Da��>�Ip�.��.�]�����"jr;@8���7:�����}���H���R8mL%K<����{��A�E'9"���.��m�~IwX�����[=q�	��-���x
�E�
���v������us��������g�~�����l��b�����l����5h�`�����0EU�E����C4-:
�
��n���k�V�5
Oq�V{{��� �|���;z5D�t��~#�y3��)�Kv�'.(OH@�y��T���s����(r�W}�oK�(���3�R�e��U|�����CEE#"�O����U�B;5�Y���].]vie,r�����������(��������7���`���������<vq���c*�c�?<����T��3�s������������m���L�&!���0B���%pj�����)��k�N&�������2d ?#��h*���Y��I��;�
�n?P	N��z��r��mo�_�H���L���I���Da�V�Q��@-}	���L��
���$s�B��9�B�i/g��#I�zh�/A��1�=���0��uL������Q����E���mG�J�b���o�h �a�.�X�������/�$j�(�f8��b	��wF��$W� 1S�L[����O�/d��xoln-<����,�A�����������r�f0������b�aR|�m��b$(��g���%�w��[�j�dk�~���jI�gA��g��&����5L#b��R�dR�v�-U��>����\����rQ���������2��'�����}�������W�Oc��Y��0F8�x�0�����FNu�J�_)��*,s�'����eZ��0�N��
�\�C��j�&�a>���0(�o�h��W{9��T:�K�?%��'��`%V���	j���H��Ew�]��y��k��bLD���z\��y��d����D�q�O����}H5T��2�kj�	��{�to�+���U���<u@�K?�	�����rMR����2'�N��n�ou�'Ky���=�Y�[�ZT��*��3<*���{|�T�b�~/c�E������%Xo�e��G�!��	��F����e.�R�4�!��m
.����WEH������F�1��>��7&T��4o����-_�^�}`��' �}4�3����)'!����oy^�����a���C��K$L����I0�H�V�GVu���
k'y��!z��c}~JXB\_�e���H�Hl+��lXy�C�����6�L�6��-2b�9��!,=C�<7%K�E��#!�0�#�Y��,R�3�3�+�y��R����s���3�(�6h�;n1���U�]�rkQ���5��'�xoO��x���P���I�x`Z��i������!H��C���|�c��<�?��q"� n�{�r�$���,���l���&���TS���{\���R�t#����EKD�*��U+�������������-������m����ca<<�U�%j����\}�PPf�$�7�������W��8O���7-�R�!OK7}����t�XK�HT�����E�����/��9�����vc�1�}���Hy�Z�������}�mH�<�]�����MnGdt��0��#�iI4m�x���5�	|
��J�V�&>�	]ao������k��"����P��������w-F��_7Y!�����F�
Q�e��2�������F���+�@�O����b^)~>p��O(���u�tY��4�f��.8\M�H����h�[��q6�<��X0+�c����N��)�4�j��j��=���K� �f�(U@��kY�;���w��s��e=Q��S��[Jt�?��������I�;�^U�4��;NQ�#V7 ��	�����p
�)F�24xF$�N��/�������w�P�P�����.��P��M��}�gzT���!5S#[����������#��#%�1��w���%4���6����-0�E���T�'I�Pk&����(����f���,��b��������$k��<�d2�[�� 0X���#��7b�9	o-:��`����xnI��Q�����~���T���`�ipXb�-;���,���3�bM��":�"������0�Ry��3�\���#TM�.���|��Q��n����E���f���H�����;�M9�S%�5"�;���`��'�h�=�8�#�V��9So�����������1�j#I����%�L���SN���������my�%g�.��Az���v�ph��[�������O�:O����1��H�t����������������'af�O�by���j��q�����'������I��]������=W�A��
%(&�C��>6J1�{�]m"�eI��c��O�|�.,�Gy�yi����ty"Z=k�
�%o�d�8b������pd 6����5x�W�>��p�d&���'��ua�b[�>3�}[�����|�y`O��^�^t~��������#�R_�����N�}���PI�'��{�*:��J�w�W�����A ��nU��M.;�-�\d��5��:���XK����F.��:
D1���	���:'��7��������'v��a��;a{~	�=��4���ro�;A��+�xe�PM�5�^�)PJy��4a��alV{��\.�����J�e$��b�����+������������l�����,x�����Y}��)6r�,+ey��Y��8��S������n!��c����dw���������=�M�qDM��\V��D�f�����*�����{��G�����{�~��������6wvv������/�i'�G����o���M�]Y1�b\���]���t�o�%��s6f]*G���QC������M'|Q
%j�eMy6����P>^��5��?�4�"u����t2���z���.���e�p0LC:���8 �nN63m����I��;��a�!������;��=��X�rcp@1�F_3����&d3�����Eo����&�],�3Y>s[f���{����{��Q���]��.�4�4��:������?���=�A��]���Fq���{�G���G+��[Y�7�Y����x��T"��|�����z����s�I�	�@r��!����F{�[FS��{�v�kS��������L������3�F��+����o'��i����88]��,5�l/�v���&�����$!��[���{�!�G���x��Y�f$�k����K �d�U)4��	&�|����p/���p"����_�
�p2y/���".��i�}�����]�zA7]^���l"�>EI��&���
��+��'Q����*b*"(G�y�&�t0����7��u&xO5f�m����l�_$]�2�������c��,m8jxT�S���w�W\�.��i���x,��|���
��.y\��,�������p�MAO2,�/��=.�b`k�=�$��cw�=�c(`���k��e�/��OyD�6���hBp6���r+2�^������23�b�x�_eyA)�Q����4��Ct�-���q�]*��ns�ZG���z���kdB���K�M����l�����{�d�6��-/���K�jpy�j6/�+���]��V4���B1^����|1b	��e��PZ��
k3f���6Zw�9n'yE�zt8pZP�a���k��~L����X.��?�%�l�KBt���Y��)^z=������w#~���9m7���tN�BxQ�3�G������evE�:t������P��e���G���?w;?=r��5����5S���f���U8\��?\\�����/}��H}������l~����~�3G��-����	�A�
����R����z��L|��i5Z���?p�4FqQ��(�o��� .��f�F�ih���m&
�`��~�t������n.r��/������`r8����]���a;��h�
#26er
er@xs4all.nl
In reply to: Alexander Korotkov (#25)
Re: WIP: index support for regexp search

On Mon, November 26, 2012 20:49, Alexander Korotkov wrote:

trgm-regexp-0.6.patch.gz

I ran the simple-minded tests against generated data (similar to the ones I did in January 2012).
The problems of that older version seem pretty much all removed. (although I didn't do much work
on it -- just reran these tests).

I used two 2 instances, 'HEAD' and 'trgm_regex', which were both compiled with

'--enable-depend' '--with-openssl' '--with-perl' '--with-libxml'

Tables used:

rowcount size table size index (trgm)

azjunk4 10^4 rows 1,171,456 | 9,781,248
azjunk5 10^5 rows 11,706,368 | 65,093,632
azjunk6 10^6 rows 117,030,912 | 726,310,912
azjunk7 10^7 rows 1,170,292,736 | 4,976,189,440

(See my previous emails for a generating script)

Tables contain random generated text:

table azjunk7 limit 5;
txt
----------------------------------------------------------------------------------
i kzzhv ssaa zv x xlepzxsgbdkxev v wn dmvqkuwb qxkyvgab gpidaosaqbewqimmai jxj
bvwn zbevtzyhibbn hoctxurutn pvlatjjyxf f runa owpltbcunrbq ux peoook rxwoscbytz
bbjlbbhhkivjivklgbh tvapzogh rj ky ahvgkvvlfudotvqapznludohdoyqrp kvothyclbckbxu
hvic gomewbp izsjifqggyqgzcghdat lb kud ltfqaxqxjjom qkw wqggikgvph yi sftmbjt
edbjfl vtcasudjpgfgjaf swooxygsse flnqd pxzsdmesqhqbzgirswysote muakq agk p w uq
(5 rows)

with index on column 'txt':

create index az7_idx on azjunk7 using gin (txt gin_trgm_ops);

Queries were of the form:

explain analyze select txt from azjunkXX where txt ~ '$REGEX';

The main problem with the January version was that it chose to use the trgm index even when it
could take a long time (hours). This has been resolved as far as I can see, and the results are
now very attractive.

(There does seem to be a very slight regression on the seqscan, but it's so small that I'm not yet
sure it's not noise)

Hardware: AMD FX-8120 with Linux 2.6.32-279.14.1.el6.x86_64 x86_64 GNU/Linux

PostgreSQL 9.3devel-trgm_regex-20121127_2353-e78d288c895bd296e3cb1ca29c7fe2431eef3fcd on
x86_64-unknown-linux-gnu, compiled by gcc (GCC) 4.7.2, 64-bit

port instance table regex rows method expl.analyze timing

6543 HEAD azjunk4 x[ae]q 46 Seq Scan 12.962 ms
6554 trgm_regex azjunk4 x[ae]q 46 Bitmap Heap Scan 0.800 ms

6543 HEAD azjunk4 x[ae]{1}q 46 Seq Scan 12.487 ms
6554 trgm_regex azjunk4 x[ae]{1}q 46 Bitmap Heap Scan 0.209 ms

6543 HEAD azjunk4 x[ae]{1,1}q 46 Seq Scan 12.266 ms
6554 trgm_regex azjunk4 x[ae]{1,1}q 46 Bitmap Heap Scan 0.210 ms

6543 HEAD azjunk4 x[ae]{,2}q 0 Seq Scan 14.322 ms
6554 trgm_regex azjunk4 x[ae]{,2}q 0 Bitmap Heap Scan 0.610 ms

6543 HEAD azjunk4 x[ae]{,10}q 0 Seq Scan 20.503 ms
6554 trgm_regex azjunk4 x[ae]{,10}q 0 Bitmap Heap Scan 0.511 ms

6543 HEAD azjunk4 x[ae]{1,2}q 49 Seq Scan 13.060 ms
6554 trgm_regex azjunk4 x[ae]{1,2}q 49 Bitmap Heap Scan 0.429 ms

6543 HEAD azjunk4 x[aei]q 81 Seq Scan 12.487 ms
6554 trgm_regex azjunk4 x[aei]q 81 Bitmap Heap Scan 0.367 ms

6543 HEAD azjunk4 x[aei]{1}q 81 Seq Scan 12.132 ms
6554 trgm_regex azjunk4 x[aei]{1}q 81 Bitmap Heap Scan 0.336 ms

6543 HEAD azjunk4 x[aei]{1,1}q 81 Seq Scan 12.168 ms
6554 trgm_regex azjunk4 x[aei]{1,1}q 81 Bitmap Heap Scan 0.319 ms

6543 HEAD azjunk4 x[aei]{,2}q 0 Seq Scan 14.586 ms
6554 trgm_regex azjunk4 x[aei]{,2}q 0 Bitmap Heap Scan 0.621 ms

6543 HEAD azjunk4 x[aei]{,10}q 0 Seq Scan 20.134 ms
6554 trgm_regex azjunk4 x[aei]{,10}q 0 Bitmap Heap Scan 0.552 ms

6543 HEAD azjunk4 x[aei]{1,2}q 89 Seq Scan 12.553 ms
6554 trgm_regex azjunk4 x[aei]{1,2}q 89 Bitmap Heap Scan 0.916 ms

6543 HEAD azjunk4 x[aei]{1,3}q 89 Seq Scan 13.055 ms
6554 trgm_regex azjunk4 x[aei]{1,3}q 89 Seq Scan 13.064 ms

6543 HEAD azjunk4 x[aei]q 81 Seq Scan 11.856 ms
6554 trgm_regex azjunk4 x[aei]q 81 Bitmap Heap Scan 0.398 ms

6543 HEAD azjunk4 x[aei]{1}q 81 Seq Scan 11.951 ms
6554 trgm_regex azjunk4 x[aei]{1}q 81 Bitmap Heap Scan 0.369 ms

6543 HEAD azjunk4 x[aei]{1,1}q 81 Seq Scan 12.750 ms
6554 trgm_regex azjunk4 x[aei]{1,1}q 81 Bitmap Heap Scan 0.355 ms

6543 HEAD azjunk4 x[aei]{,2}q 0 Seq Scan 14.032 ms
6554 trgm_regex azjunk4 x[aei]{,2}q 0 Bitmap Heap Scan 0.540 ms

6543 HEAD azjunk4 x[aei]{,10}q 0 Seq Scan 20.377 ms
6554 trgm_regex azjunk4 x[aei]{,10}q 0 Bitmap Heap Scan 0.550 ms

6543 HEAD azjunk4 x[aei]{1,2}q 89 Seq Scan 12.706 ms
6554 trgm_regex azjunk4 x[aei]{1,2}q 89 Bitmap Heap Scan 0.969 ms

6543 HEAD azjunk4 x[aei]{1,3}q 89 Seq Scan 13.127 ms
6554 trgm_regex azjunk4 x[aei]{1,3}q 89 Seq Scan 13.025 ms

6543 HEAD azjunk4 x[aeio]q 105 Seq Scan 12.533 ms
6554 trgm_regex azjunk4 x[aeio]q 105 Bitmap Heap Scan 0.391 ms

6543 HEAD azjunk4 x[aeio]{1}q 105 Seq Scan 12.532 ms
6554 trgm_regex azjunk4 x[aeio]{1}q 105 Bitmap Heap Scan 0.362 ms

6543 HEAD azjunk4 x[aeio]{1,1}q 105 Seq Scan 12.323 ms
6554 trgm_regex azjunk4 x[aeio]{1,1}q 105 Bitmap Heap Scan 0.449 ms

6543 HEAD azjunk4 x[aeio]{,2}q 0 Seq Scan 14.417 ms
6554 trgm_regex azjunk4 x[aeio]{,2}q 0 Bitmap Heap Scan 0.844 ms

6543 HEAD azjunk4 x[aeio]{,10}q 0 Seq Scan 23.056 ms
6554 trgm_regex azjunk4 x[aeio]{,10}q 0 Bitmap Heap Scan 0.668 ms

6543 HEAD azjunk4 x[aeio]{1,2}q 121 Seq Scan 13.072 ms
6554 trgm_regex azjunk4 x[aeio]{1,2}q 121 Seq Scan 13.750 ms

6543 HEAD azjunk4 x[aeio]{1,3}q 123 Seq Scan 12.916 ms
6554 trgm_regex azjunk4 x[aeio]{1,3}q 123 Seq Scan 13.078 ms

6543 HEAD azjunk4 x[aeio]{1,4}q 124 Seq Scan 13.478 ms
6554 trgm_regex azjunk4 x[aeio]{1,4}q 124 Seq Scan 14.334 ms

6543 HEAD azjunk4 x[aeio]{2,4}q 19 Seq Scan 13.922 ms
6554 trgm_regex azjunk4 x[aeio]{2,4}q 19 Seq Scan 13.503 ms

6543 HEAD azjunk4 x[aeio]{3,4}q 3 Seq Scan 14.325 ms
6554 trgm_regex azjunk4 x[aeio]{3,4}q 3 Seq Scan 13.429 ms

6543 HEAD azjunk4 x[aeiou]q 134 Seq Scan 12.356 ms
6554 trgm_regex azjunk4 x[aeiou]q 134 Seq Scan 13.215 ms

6543 HEAD azjunk4 x[aeiou]{1}q 134 Seq Scan 13.005 ms
6554 trgm_regex azjunk4 x[aeiou]{1}q 134 Seq Scan 12.893 ms

6543 HEAD azjunk4 x[aeiou]{1,1}q 134 Seq Scan 12.430 ms
6554 trgm_regex azjunk4 x[aeiou]{1,1}q 134 Seq Scan 13.108 ms

6543 HEAD azjunk4 x[aeiou]{,2}q 0 Seq Scan 14.486 ms
6554 trgm_regex azjunk4 x[aeiou]{,2}q 0 Bitmap Heap Scan 0.349 ms

6543 HEAD azjunk4 x[aeiou]{,10}q 0 Seq Scan 21.597 ms
6554 trgm_regex azjunk4 x[aeiou]{,10}q 0 Bitmap Heap Scan 0.363 ms

6543 HEAD azjunk4 x[aeiou]{1,2}q 156 Seq Scan 13.069 ms
6554 trgm_regex azjunk4 x[aeiou]{1,2}q 156 Seq Scan 13.879 ms

6543 HEAD azjunk4 x[aeiou]{1,3}q 160 Seq Scan 13.005 ms
6554 trgm_regex azjunk4 x[aeiou]{1,3}q 160 Seq Scan 14.016 ms

6543 HEAD azjunk4 x[aeiou]{1,4}q 161 Seq Scan 13.603 ms
6554 trgm_regex azjunk4 x[aeiou]{1,4}q 161 Seq Scan 14.667 ms

6543 HEAD azjunk4 x[aeiou]{2,4}q 27 Seq Scan 13.656 ms
6554 trgm_regex azjunk4 x[aeiou]{2,4}q 27 Seq Scan 14.113 ms

6543 HEAD azjunk4 x[aeiou]{3,4}q 5 Seq Scan 13.541 ms
6554 trgm_regex azjunk4 x[aeiou]{3,4}q 5 Seq Scan 14.265 ms

6543 HEAD azjunk4 x[aeiou]{1,5}q 162 Seq Scan 13.750 ms
6554 trgm_regex azjunk4 x[aeiou]{1,5}q 162 Seq Scan 13.858 ms

6543 HEAD azjunk4 x[aeiou]{2,5}q 28 Seq Scan 13.745 ms
6554 trgm_regex azjunk4 x[aeiou]{2,5}q 28 Seq Scan 13.680 ms

6543 HEAD azjunk4 x[aeiou]{4,5}q 2 Seq Scan 13.577 ms
6554 trgm_regex azjunk4 x[aeiou]{4,5}q 2 Seq Scan 13.755 ms

6543 HEAD azjunk4 x[aeiouy]q 173 Seq Scan 12.106 ms
6554 trgm_regex azjunk4 x[aeiouy]q 173 Seq Scan 12.655 ms

6543 HEAD azjunk4 x[aeiouy]{1}q 173 Seq Scan 12.488 ms
6554 trgm_regex azjunk4 x[aeiouy]{1}q 173 Seq Scan 12.723 ms

6543 HEAD azjunk4 x[aeiouy]{1,1}q 173 Seq Scan 12.525 ms
6554 trgm_regex azjunk4 x[aeiouy]{1,1}q 173 Seq Scan 13.957 ms

6543 HEAD azjunk4 x[aeiouy]{,2}q 0 Seq Scan 14.574 ms
6554 trgm_regex azjunk4 x[aeiouy]{,2}q 0 Bitmap Heap Scan 0.295 ms

6543 HEAD azjunk4 x[aeiouy]{,10}q 0 Seq Scan 20.916 ms
6554 trgm_regex azjunk4 x[aeiouy]{,10}q 0 Bitmap Heap Scan 0.311 ms

6543 HEAD azjunk4 x[aeiouy]{1,2}q 204 Seq Scan 12.730 ms
6554 trgm_regex azjunk4 x[aeiouy]{1,2}q 204 Seq Scan 13.392 ms

6543 HEAD azjunk4 x[aeiouy]{1,3}q 215 Seq Scan 12.824 ms
6554 trgm_regex azjunk4 x[aeiouy]{1,3}q 215 Seq Scan 13.083 ms

6543 HEAD azjunk4 x[aeiouy]{1,4}q 218 Seq Scan 13.985 ms
6554 trgm_regex azjunk4 x[aeiouy]{1,4}q 218 Seq Scan 13.890 ms

6543 HEAD azjunk4 x[aeiouy]{2,4}q 46 Seq Scan 13.735 ms
6554 trgm_regex azjunk4 x[aeiouy]{2,4}q 46 Seq Scan 13.724 ms

6543 HEAD azjunk4 x[aeiouy]{3,4}q 14 Seq Scan 13.470 ms
6554 trgm_regex azjunk4 x[aeiouy]{3,4}q 14 Seq Scan 14.046 ms

6543 HEAD azjunk4 x[aeiouy]{1,5}q 219 Seq Scan 14.245 ms
6554 trgm_regex azjunk4 x[aeiouy]{1,5}q 219 Seq Scan 14.370 ms

6543 HEAD azjunk4 x[aeiouy]{2,5}q 47 Seq Scan 13.483 ms
6554 trgm_regex azjunk4 x[aeiouy]{2,5}q 47 Seq Scan 15.065 ms

6543 HEAD azjunk4 x[aeiouy]{4,5}q 4 Seq Scan 13.394 ms
6554 trgm_regex azjunk4 x[aeiouy]{4,5}q 4 Seq Scan 14.158 ms

6543 HEAD azjunk5 x[ae]q 677 Seq Scan 114.862 ms
6554 trgm_regex azjunk5 x[ae]q 677 Bitmap Heap Scan 2.213 ms

6543 HEAD azjunk5 x[ae]{1}q 677 Seq Scan 119.024 ms
6554 trgm_regex azjunk5 x[ae]{1}q 677 Bitmap Heap Scan 1.800 ms

6543 HEAD azjunk5 x[ae]{1,1}q 677 Seq Scan 118.500 ms
6554 trgm_regex azjunk5 x[ae]{1,1}q 677 Bitmap Heap Scan 1.788 ms

6543 HEAD azjunk5 x[ae]{,2}q 0 Seq Scan 138.023 ms
6554 trgm_regex azjunk5 x[ae]{,2}q 0 Bitmap Heap Scan 9.822 ms

6543 HEAD azjunk5 x[ae]{,10}q 0 Seq Scan 223.479 ms
6554 trgm_regex azjunk5 x[ae]{,10}q 0 Bitmap Heap Scan 9.141 ms

6543 HEAD azjunk5 x[ae]{1,2}q 723 Seq Scan 122.973 ms
6554 trgm_regex azjunk5 x[ae]{1,2}q 723 Bitmap Heap Scan 3.865 ms

6543 HEAD azjunk5 x[aei]q 982 Seq Scan 121.424 ms
6554 trgm_regex azjunk5 x[aei]q 982 Bitmap Heap Scan 2.639 ms

6543 HEAD azjunk5 x[aei]{1}q 982 Seq Scan 119.213 ms
6554 trgm_regex azjunk5 x[aei]{1}q 982 Bitmap Heap Scan 2.769 ms

6543 HEAD azjunk5 x[aei]{1,1}q 982 Seq Scan 121.673 ms
6554 trgm_regex azjunk5 x[aei]{1,1}q 982 Bitmap Heap Scan 2.657 ms

6543 HEAD azjunk5 x[aei]{,2}q 0 Seq Scan 142.256 ms
6554 trgm_regex azjunk5 x[aei]{,2}q 0 Bitmap Heap Scan 5.588 ms

6543 HEAD azjunk5 x[aei]{,10}q 0 Seq Scan 214.769 ms
6554 trgm_regex azjunk5 x[aei]{,10}q 0 Bitmap Heap Scan 9.007 ms

6543 HEAD azjunk5 x[aei]{1,2}q 1075 Seq Scan 128.672 ms
6554 trgm_regex azjunk5 x[aei]{1,2}q 1075 Bitmap Heap Scan 8.079 ms

6543 HEAD azjunk5 x[aei]{1,3}q 1086 Seq Scan 127.069 ms
6554 trgm_regex azjunk5 x[aei]{1,3}q 1086 Bitmap Heap Scan 27.654 ms

6543 HEAD azjunk5 x[aei]q 982 Seq Scan 121.431 ms
6554 trgm_regex azjunk5 x[aei]q 982 Bitmap Heap Scan 2.782 ms

6543 HEAD azjunk5 x[aei]{1}q 982 Seq Scan 121.270 ms
6554 trgm_regex azjunk5 x[aei]{1}q 982 Bitmap Heap Scan 2.603 ms

6543 HEAD azjunk5 x[aei]{1,1}q 982 Seq Scan 120.032 ms
6554 trgm_regex azjunk5 x[aei]{1,1}q 982 Bitmap Heap Scan 2.627 ms

6543 HEAD azjunk5 x[aei]{,2}q 0 Seq Scan 143.379 ms
6554 trgm_regex azjunk5 x[aei]{,2}q 0 Bitmap Heap Scan 4.906 ms

6543 HEAD azjunk5 x[aei]{,10}q 0 Seq Scan 196.212 ms
6554 trgm_regex azjunk5 x[aei]{,10}q 0 Bitmap Heap Scan 4.707 ms

6543 HEAD azjunk5 x[aei]{1,2}q 1075 Seq Scan 127.050 ms
6554 trgm_regex azjunk5 x[aei]{1,2}q 1075 Bitmap Heap Scan 8.474 ms

6543 HEAD azjunk5 x[aei]{1,3}q 1086 Seq Scan 127.090 ms
6554 trgm_regex azjunk5 x[aei]{1,3}q 1086 Bitmap Heap Scan 27.646 ms

6543 HEAD azjunk5 x[aeio]q 1292 Seq Scan 119.951 ms
6554 trgm_regex azjunk5 x[aeio]q 1292 Bitmap Heap Scan 3.881 ms

6543 HEAD azjunk5 x[aeio]{1}q 1292 Seq Scan 123.444 ms
6554 trgm_regex azjunk5 x[aeio]{1}q 1292 Bitmap Heap Scan 3.346 ms

6543 HEAD azjunk5 x[aeio]{1,1}q 1292 Seq Scan 124.024 ms
6554 trgm_regex azjunk5 x[aeio]{1,1}q 1292 Bitmap Heap Scan 3.681 ms

6543 HEAD azjunk5 x[aeio]{,2}q 0 Seq Scan 152.181 ms
6554 trgm_regex azjunk5 x[aeio]{,2}q 0 Bitmap Heap Scan 5.774 ms

6543 HEAD azjunk5 x[aeio]{,10}q 0 Seq Scan 214.168 ms
6554 trgm_regex azjunk5 x[aeio]{,10}q 0 Bitmap Heap Scan 12.074 ms

6543 HEAD azjunk5 x[aeio]{1,2}q 1441 Seq Scan 128.491 ms
6554 trgm_regex azjunk5 x[aeio]{1,2}q 1441 Bitmap Heap Scan 22.538 ms

6543 HEAD azjunk5 x[aeio]{1,3}q 1461 Seq Scan 132.987 ms
6554 trgm_regex azjunk5 x[aeio]{1,3}q 1461 Seq Scan 125.682 ms

6543 HEAD azjunk5 x[aeio]{1,4}q 1464 Seq Scan 132.729 ms
6554 trgm_regex azjunk5 x[aeio]{1,4}q 1464 Seq Scan 133.625 ms

6543 HEAD azjunk5 x[aeio]{2,4}q 175 Seq Scan 135.328 ms
6554 trgm_regex azjunk5 x[aeio]{2,4}q 175 Seq Scan 134.194 ms

6543 HEAD azjunk5 x[aeio]{3,4}q 23 Seq Scan 131.590 ms
6554 trgm_regex azjunk5 x[aeio]{3,4}q 23 Seq Scan 135.435 ms

6543 HEAD azjunk5 x[aeiou]q 1598 Seq Scan 124.063 ms
6554 trgm_regex azjunk5 x[aeiou]q 1598 Seq Scan 124.983 ms

6543 HEAD azjunk5 x[aeiou]{1}q 1598 Seq Scan 134.563 ms
6554 trgm_regex azjunk5 x[aeiou]{1}q 1598 Seq Scan 128.089 ms

6543 HEAD azjunk5 x[aeiou]{1,1}q 1598 Seq Scan 124.158 ms
6554 trgm_regex azjunk5 x[aeiou]{1,1}q 1598 Seq Scan 128.355 ms

6543 HEAD azjunk5 x[aeiou]{,2}q 0 Seq Scan 144.541 ms
6554 trgm_regex azjunk5 x[aeiou]{,2}q 0 Bitmap Heap Scan 2.369 ms

6543 HEAD azjunk5 x[aeiou]{,10}q 0 Seq Scan 208.091 ms
6554 trgm_regex azjunk5 x[aeiou]{,10}q 0 Bitmap Heap Scan 2.528 ms

6543 HEAD azjunk5 x[aeiou]{1,2}q 1838 Seq Scan 130.474 ms
6554 trgm_regex azjunk5 x[aeiou]{1,2}q 1838 Seq Scan 130.433 ms

6543 HEAD azjunk5 x[aeiou]{1,3}q 1886 Seq Scan 134.002 ms
6554 trgm_regex azjunk5 x[aeiou]{1,3}q 1886 Seq Scan 134.786 ms

6543 HEAD azjunk5 x[aeiou]{1,4}q 1892 Seq Scan 137.588 ms
6554 trgm_regex azjunk5 x[aeiou]{1,4}q 1892 Seq Scan 145.194 ms

6543 HEAD azjunk5 x[aeiou]{2,4}q 299 Seq Scan 136.125 ms
6554 trgm_regex azjunk5 x[aeiou]{2,4}q 299 Seq Scan 138.212 ms

6543 HEAD azjunk5 x[aeiou]{3,4}q 54 Seq Scan 135.205 ms
6554 trgm_regex azjunk5 x[aeiou]{3,4}q 54 Seq Scan 134.146 ms

6543 HEAD azjunk5 x[aeiou]{1,5}q 1895 Seq Scan 137.151 ms
6554 trgm_regex azjunk5 x[aeiou]{1,5}q 1895 Seq Scan 140.986 ms

6543 HEAD azjunk5 x[aeiou]{2,5}q 302 Seq Scan 142.189 ms
6554 trgm_regex azjunk5 x[aeiou]{2,5}q 302 Seq Scan 137.368 ms

6543 HEAD azjunk5 x[aeiou]{4,5}q 9 Seq Scan 138.165 ms
6554 trgm_regex azjunk5 x[aeiou]{4,5}q 9 Seq Scan 137.122 ms

6543 HEAD azjunk5 x[aeiouy]q 1913 Seq Scan 126.283 ms
6554 trgm_regex azjunk5 x[aeiouy]q 1913 Seq Scan 130.424 ms

6543 HEAD azjunk5 x[aeiouy]{1}q 1913 Seq Scan 125.947 ms
6554 trgm_regex azjunk5 x[aeiouy]{1}q 1913 Seq Scan 131.957 ms

6543 HEAD azjunk5 x[aeiouy]{1,1}q 1913 Seq Scan 126.529 ms
6554 trgm_regex azjunk5 x[aeiouy]{1,1}q 1913 Seq Scan 130.958 ms

6543 HEAD azjunk5 x[aeiouy]{,2}q 0 Seq Scan 147.704 ms
6554 trgm_regex azjunk5 x[aeiouy]{,2}q 0 Bitmap Heap Scan 2.331 ms

6543 HEAD azjunk5 x[aeiouy]{,10}q 0 Seq Scan 221.774 ms
6554 trgm_regex azjunk5 x[aeiouy]{,10}q 0 Bitmap Heap Scan 2.522 ms

6543 HEAD azjunk5 x[aeiouy]{1,2}q 2275 Seq Scan 134.044 ms
6554 trgm_regex azjunk5 x[aeiouy]{1,2}q 2275 Seq Scan 136.827 ms

6543 HEAD azjunk5 x[aeiouy]{1,3}q 2358 Seq Scan 135.599 ms
6554 trgm_regex azjunk5 x[aeiouy]{1,3}q 2358 Seq Scan 134.196 ms

6543 HEAD azjunk5 x[aeiouy]{1,4}q 2376 Seq Scan 138.685 ms
6554 trgm_regex azjunk5 x[aeiouy]{1,4}q 2376 Seq Scan 141.408 ms

6543 HEAD azjunk5 x[aeiouy]{2,4}q 474 Seq Scan 142.223 ms
6554 trgm_regex azjunk5 x[aeiouy]{2,4}q 474 Seq Scan 143.439 ms

6543 HEAD azjunk5 x[aeiouy]{3,4}q 103 Seq Scan 138.690 ms
6554 trgm_regex azjunk5 x[aeiouy]{3,4}q 103 Seq Scan 136.192 ms

6543 HEAD azjunk5 x[aeiouy]{1,5}q 2381 Seq Scan 140.836 ms
6554 trgm_regex azjunk5 x[aeiouy]{1,5}q 2381 Seq Scan 143.374 ms

6543 HEAD azjunk5 x[aeiouy]{2,5}q 479 Seq Scan 140.223 ms
6554 trgm_regex azjunk5 x[aeiouy]{2,5}q 479 Seq Scan 139.995 ms

6543 HEAD azjunk5 x[aeiouy]{4,5}q 23 Seq Scan 139.976 ms
6554 trgm_regex azjunk5 x[aeiouy]{4,5}q 23 Seq Scan 138.114 ms

6543 HEAD azjunk6 x[ae]q 6448 Seq Scan 1219.490 ms
6554 trgm_regex azjunk6 x[ae]q 6448 Bitmap Heap Scan 23.452 ms

6543 HEAD azjunk6 x[ae]{1}q 6448 Seq Scan 1153.371 ms
6554 trgm_regex azjunk6 x[ae]{1}q 6448 Bitmap Heap Scan 18.492 ms

6543 HEAD azjunk6 x[ae]{1,1}q 6448 Seq Scan 1189.951 ms
6554 trgm_regex azjunk6 x[ae]{1,1}q 6448 Bitmap Heap Scan 24.596 ms

6543 HEAD azjunk6 x[ae]{,2}q 0 Seq Scan 1423.474 ms
6554 trgm_regex azjunk6 x[ae]{,2}q 0 Bitmap Heap Scan 41.593 ms

6543 HEAD azjunk6 x[ae]{,10}q 0 Seq Scan 1957.142 ms
6554 trgm_regex azjunk6 x[ae]{,10}q 0 Bitmap Heap Scan 45.238 ms

6543 HEAD azjunk6 x[ae]{1,2}q 6886 Seq Scan 1253.761 ms
6554 trgm_regex azjunk6 x[ae]{1,2}q 6886 Bitmap Heap Scan 31.247 ms

6543 HEAD azjunk6 x[aei]q 9600 Seq Scan 1203.022 ms
6554 trgm_regex azjunk6 x[aei]q 9600 Bitmap Heap Scan 31.467 ms

6543 HEAD azjunk6 x[aei]{1}q 9600 Seq Scan 1213.834 ms
6554 trgm_regex azjunk6 x[aei]{1}q 9600 Bitmap Heap Scan 26.008 ms

6543 HEAD azjunk6 x[aei]{1,1}q 9600 Seq Scan 1244.158 ms
6554 trgm_regex azjunk6 x[aei]{1,1}q 9600 Bitmap Heap Scan 25.997 ms

6543 HEAD azjunk6 x[aei]{,2}q 0 Seq Scan 1432.935 ms
6554 trgm_regex azjunk6 x[aei]{,2}q 0 Bitmap Heap Scan 44.843 ms

6543 HEAD azjunk6 x[aei]{,10}q 0 Seq Scan 1940.611 ms
6554 trgm_regex azjunk6 x[aei]{,10}q 0 Bitmap Heap Scan 45.838 ms

6543 HEAD azjunk6 x[aei]{1,2}q 10604 Seq Scan 1235.913 ms
6554 trgm_regex azjunk6 x[aei]{1,2}q 10604 Bitmap Heap Scan 78.764 ms

6543 HEAD azjunk6 x[aei]{1,3}q 10704 Seq Scan 1244.960 ms
6554 trgm_regex azjunk6 x[aei]{1,3}q 10704 Bitmap Heap Scan 272.049 ms

6543 HEAD azjunk6 x[aei]q 9600 Seq Scan 1211.965 ms
6554 trgm_regex azjunk6 x[aei]q 9600 Bitmap Heap Scan 26.230 ms

6543 HEAD azjunk6 x[aei]{1}q 9600 Seq Scan 1218.431 ms
6554 trgm_regex azjunk6 x[aei]{1}q 9600 Bitmap Heap Scan 25.462 ms

6543 HEAD azjunk6 x[aei]{1,1}q 9600 Seq Scan 1250.050 ms
6554 trgm_regex azjunk6 x[aei]{1,1}q 9600 Bitmap Heap Scan 25.711 ms

6543 HEAD azjunk6 x[aei]{,2}q 0 Seq Scan 1457.725 ms
6554 trgm_regex azjunk6 x[aei]{,2}q 0 Bitmap Heap Scan 43.491 ms

6543 HEAD azjunk6 x[aei]{,10}q 0 Seq Scan 2034.895 ms
6554 trgm_regex azjunk6 x[aei]{,10}q 0 Bitmap Heap Scan 46.139 ms

6543 HEAD azjunk6 x[aei]{1,2}q 10604 Seq Scan 1250.820 ms
6554 trgm_regex azjunk6 x[aei]{1,2}q 10604 Bitmap Heap Scan 78.067 ms

6543 HEAD azjunk6 x[aei]{1,3}q 10704 Seq Scan 1265.146 ms
6554 trgm_regex azjunk6 x[aei]{1,3}q 10704 Bitmap Heap Scan 274.109 ms

6543 HEAD azjunk6 x[aeio]q 12784 Seq Scan 1235.647 ms
6554 trgm_regex azjunk6 x[aeio]q 12784 Bitmap Heap Scan 35.613 ms

6543 HEAD azjunk6 x[aeio]{1}q 12784 Seq Scan 1206.185 ms
6554 trgm_regex azjunk6 x[aeio]{1}q 12784 Bitmap Heap Scan 39.618 ms

6543 HEAD azjunk6 x[aeio]{1,1}q 12784 Seq Scan 1210.467 ms
6554 trgm_regex azjunk6 x[aeio]{1,1}q 12784 Bitmap Heap Scan 34.513 ms

6543 HEAD azjunk6 x[aeio]{,2}q 0 Seq Scan 1457.918 ms
6554 trgm_regex azjunk6 x[aeio]{,2}q 0 Bitmap Heap Scan 55.732 ms

6543 HEAD azjunk6 x[aeio]{,10}q 0 Seq Scan 2104.860 ms
6554 trgm_regex azjunk6 x[aeio]{,10}q 0 Bitmap Heap Scan 62.129 ms

6543 HEAD azjunk6 x[aeio]{1,2}q 14538 Seq Scan 1286.881 ms
6554 trgm_regex azjunk6 x[aeio]{1,2}q 14538 Bitmap Heap Scan 182.161 ms

6543 HEAD azjunk6 x[aeio]{1,3}q 14761 Seq Scan 1291.199 ms
6554 trgm_regex azjunk6 x[aeio]{1,3}q 14761 Bitmap Heap Scan 1445.593 ms

6543 HEAD azjunk6 x[aeio]{1,4}q 14791 Seq Scan 1331.960 ms
6554 trgm_regex azjunk6 x[aeio]{1,4}q 14791 Seq Scan 1340.845 ms

6543 HEAD azjunk6 x[aeio]{2,4}q 2024 Seq Scan 1337.631 ms
6554 trgm_regex azjunk6 x[aeio]{2,4}q 2024 Seq Scan 1354.844 ms

6543 HEAD azjunk6 x[aeio]{3,4}q 257 Seq Scan 1321.271 ms
6554 trgm_regex azjunk6 x[aeio]{3,4}q 257 Seq Scan 1335.737 ms

6543 HEAD azjunk6 x[aeiou]q 15976 Seq Scan 1237.313 ms
6554 trgm_regex azjunk6 x[aeiou]q 15976 Seq Scan 1268.531 ms

6543 HEAD azjunk6 x[aeiou]{1}q 15976 Seq Scan 1251.777 ms
6554 trgm_regex azjunk6 x[aeiou]{1}q 15976 Seq Scan 1268.431 ms

6543 HEAD azjunk6 x[aeiou]{1,1}q 15976 Seq Scan 1243.416 ms
6554 trgm_regex azjunk6 x[aeiou]{1,1}q 15976 Seq Scan 1263.152 ms

6543 HEAD azjunk6 x[aeiou]{,2}q 0 Seq Scan 1476.587 ms
6554 trgm_regex azjunk6 x[aeiou]{,2}q 0 Bitmap Heap Scan 19.583 ms

6543 HEAD azjunk6 x[aeiou]{,10}q 0 Seq Scan 2084.845 ms
6554 trgm_regex azjunk6 x[aeiou]{,10}q 0 Bitmap Heap Scan 21.377 ms

6543 HEAD azjunk6 x[aeiou]{1,2}q 18692 Seq Scan 1302.585 ms
6554 trgm_regex azjunk6 x[aeiou]{1,2}q 18692 Seq Scan 1330.683 ms

6543 HEAD azjunk6 x[aeiou]{1,3}q 19128 Seq Scan 1290.309 ms
6554 trgm_regex azjunk6 x[aeiou]{1,3}q 19128 Seq Scan 1317.831 ms

6543 HEAD azjunk6 x[aeiou]{1,4}q 19202 Seq Scan 1347.727 ms
6554 trgm_regex azjunk6 x[aeiou]{1,4}q 19202 Seq Scan 1361.307 ms

6543 HEAD azjunk6 x[aeiou]{2,4}q 3268 Seq Scan 1362.704 ms
6554 trgm_regex azjunk6 x[aeiou]{2,4}q 3268 Seq Scan 1372.468 ms

6543 HEAD azjunk6 x[aeiou]{3,4}q 523 Seq Scan 1321.774 ms
6554 trgm_regex azjunk6 x[aeiou]{3,4}q 523 Seq Scan 1346.200 ms

6543 HEAD azjunk6 x[aeiou]{1,5}q 19214 Seq Scan 1367.949 ms
6554 trgm_regex azjunk6 x[aeiou]{1,5}q 19214 Seq Scan 1428.444 ms

6543 HEAD azjunk6 x[aeiou]{2,5}q 3280 Seq Scan 1349.375 ms
6554 trgm_regex azjunk6 x[aeiou]{2,5}q 3280 Seq Scan 1375.887 ms

6543 HEAD azjunk6 x[aeiou]{4,5}q 88 Seq Scan 1324.008 ms
6554 trgm_regex azjunk6 x[aeiou]{4,5}q 88 Seq Scan 1394.067 ms

6543 HEAD azjunk6 x[aeiouy]q 19168 Seq Scan 1262.363 ms
6554 trgm_regex azjunk6 x[aeiouy]q 19168 Seq Scan 1248.167 ms

6543 HEAD azjunk6 x[aeiouy]{1}q 19168 Seq Scan 1257.760 ms
6554 trgm_regex azjunk6 x[aeiouy]{1}q 19168 Seq Scan 1276.502 ms

6543 HEAD azjunk6 x[aeiouy]{1,1}q 19168 Seq Scan 1282.770 ms
6554 trgm_regex azjunk6 x[aeiouy]{1,1}q 19168 Seq Scan 1284.173 ms

6543 HEAD azjunk6 x[aeiouy]{,2}q 0 Seq Scan 1483.940 ms
6554 trgm_regex azjunk6 x[aeiouy]{,2}q 0 Bitmap Heap Scan 20.634 ms

6543 HEAD azjunk6 x[aeiouy]{,10}q 0 Seq Scan 2058.701 ms
6554 trgm_regex azjunk6 x[aeiouy]{,10}q 0 Bitmap Heap Scan 21.596 ms

6543 HEAD azjunk6 x[aeiouy]{1,2}q 23069 Seq Scan 1340.593 ms
6554 trgm_regex azjunk6 x[aeiouy]{1,2}q 23069 Seq Scan 1322.919 ms

6543 HEAD azjunk6 x[aeiouy]{1,3}q 23844 Seq Scan 1321.853 ms
6554 trgm_regex azjunk6 x[aeiouy]{1,3}q 23844 Seq Scan 1333.974 ms

6543 HEAD azjunk6 x[aeiouy]{1,4}q 23993 Seq Scan 1377.787 ms
6554 trgm_regex azjunk6 x[aeiouy]{1,4}q 23993 Seq Scan 1389.073 ms

6543 HEAD azjunk6 x[aeiouy]{2,4}q 4903 Seq Scan 1392.936 ms
6554 trgm_regex azjunk6 x[aeiouy]{2,4}q 4903 Seq Scan 1399.154 ms

6543 HEAD azjunk6 x[aeiouy]{3,4}q 944 Seq Scan 1342.379 ms
6554 trgm_regex azjunk6 x[aeiouy]{3,4}q 944 Seq Scan 1375.420 ms

6543 HEAD azjunk6 x[aeiouy]{1,5}q 24028 Seq Scan 1402.588 ms
6554 trgm_regex azjunk6 x[aeiouy]{1,5}q 24028 Seq Scan 1482.936 ms

6543 HEAD azjunk6 x[aeiouy]{2,5}q 4938 Seq Scan 1378.311 ms
6554 trgm_regex azjunk6 x[aeiouy]{2,5}q 4938 Seq Scan 1402.020 ms

6543 HEAD azjunk6 x[aeiouy]{4,5}q 189 Seq Scan 1348.171 ms
6554 trgm_regex azjunk6 x[aeiouy]{4,5}q 189 Seq Scan 1392.002 ms

6543 HEAD azjunk7 x[ae]q 63781 Seq Scan 11722.978 ms
6554 trgm_regex azjunk7 x[ae]q 63781 Bitmap Heap Scan 418.407 ms

6543 HEAD azjunk7 x[ae]{1}q 63781 Seq Scan 11787.311 ms
6554 trgm_regex azjunk7 x[ae]{1}q 63781 Bitmap Heap Scan 423.027 ms

6543 HEAD azjunk7 x[ae]{1,1}q 63781 Seq Scan 11902.061 ms
6554 trgm_regex azjunk7 x[ae]{1,1}q 63781 Bitmap Heap Scan 420.819 ms

6543 HEAD azjunk7 x[ae]{,2}q 0 Seq Scan 14144.148 ms
6554 trgm_regex azjunk7 x[ae]{,2}q 0 Bitmap Heap Scan 343.806 ms

6543 HEAD azjunk7 x[ae]{,10}q 0 Seq Scan 20390.872 ms
6554 trgm_regex azjunk7 x[ae]{,10}q 0 Bitmap Heap Scan 370.856 ms

6543 HEAD azjunk7 x[ae]{1,2}q 68145 Seq Scan 12569.198 ms
6554 trgm_regex azjunk7 x[ae]{1,2}q 68145 Bitmap Heap Scan 571.570 ms

6543 HEAD azjunk7 x[aei]q 95281 Seq Scan 12027.646 ms
6554 trgm_regex azjunk7 x[aei]q 95281 Bitmap Heap Scan 579.807 ms

6543 HEAD azjunk7 x[aei]{1}q 95281 Seq Scan 12213.674 ms
6554 trgm_regex azjunk7 x[aei]{1}q 95281 Bitmap Heap Scan 581.085 ms

6543 HEAD azjunk7 x[aei]{1,1}q 95281 Seq Scan 12121.898 ms
6554 trgm_regex azjunk7 x[aei]{1,1}q 95281 Bitmap Heap Scan 587.568 ms

6543 HEAD azjunk7 x[aei]{,2}q 0 Seq Scan 14519.020 ms
6554 trgm_regex azjunk7 x[aei]{,2}q 0 Bitmap Heap Scan 440.596 ms

6543 HEAD azjunk7 x[aei]{,10}q 0 Seq Scan 20829.970 ms
6554 trgm_regex azjunk7 x[aei]{,10}q 0 Bitmap Heap Scan 443.136 ms

6543 HEAD azjunk7 x[aei]{1,2}q 105054 Seq Scan 12967.634 ms
6554 trgm_regex azjunk7 x[aei]{1,2}q 105054 Bitmap Heap Scan 1151.202 ms

6543 HEAD azjunk7 x[aei]{1,3}q 106031 Seq Scan 12601.485 ms
6554 trgm_regex azjunk7 x[aei]{1,3}q 106031 Bitmap Heap Scan 3084.092 ms

6543 HEAD azjunk7 x[aei]q 95281 Seq Scan 12251.805 ms
6554 trgm_regex azjunk7 x[aei]q 95281 Bitmap Heap Scan 579.398 ms

6543 HEAD azjunk7 x[aei]{1}q 95281 Seq Scan 12251.196 ms
6554 trgm_regex azjunk7 x[aei]{1}q 95281 Bitmap Heap Scan 579.351 ms

6543 HEAD azjunk7 x[aei]{1,1}q 95281 Seq Scan 12176.216 ms
6554 trgm_regex azjunk7 x[aei]{1,1}q 95281 Bitmap Heap Scan 577.931 ms

6543 HEAD azjunk7 x[aei]{,2}q 0 Seq Scan 14632.855 ms
6554 trgm_regex azjunk7 x[aei]{,2}q 0 Bitmap Heap Scan 434.758 ms

6543 HEAD azjunk7 x[aei]{,10}q 0 Seq Scan 20637.829 ms
6554 trgm_regex azjunk7 x[aei]{,10}q 0 Bitmap Heap Scan 440.237 ms

6543 HEAD azjunk7 x[aei]{1,2}q 105054 Seq Scan 12967.108 ms
6554 trgm_regex azjunk7 x[aei]{1,2}q 105054 Bitmap Heap Scan 1166.260 ms

6543 HEAD azjunk7 x[aei]{1,3}q 106031 Seq Scan 12820.629 ms
6554 trgm_regex azjunk7 x[aei]{1,3}q 106031 Bitmap Heap Scan 3079.662 ms

6543 HEAD azjunk7 x[aeio]q 126868 Seq Scan 12535.441 ms
6554 trgm_regex azjunk7 x[aeio]q 126868 Bitmap Heap Scan 737.634 ms

6543 HEAD azjunk7 x[aeio]{1}q 126868 Seq Scan 12338.188 ms
6554 trgm_regex azjunk7 x[aeio]{1}q 126868 Bitmap Heap Scan 749.844 ms

6543 HEAD azjunk7 x[aeio]{1,1}q 126868 Seq Scan 12579.271 ms
6554 trgm_regex azjunk7 x[aeio]{1,1}q 126868 Bitmap Heap Scan 731.667 ms

6543 HEAD azjunk7 x[aeio]{,2}q 0 Seq Scan 14806.573 ms
6554 trgm_regex azjunk7 x[aeio]{,2}q 0 Bitmap Heap Scan 555.302 ms

6543 HEAD azjunk7 x[aeio]{,10}q 0 Seq Scan 22000.135 ms
6554 trgm_regex azjunk7 x[aeio]{,10}q 0 Bitmap Heap Scan 560.526 ms

6543 HEAD azjunk7 x[aeio]{1,2}q 144180 Seq Scan 12919.840 ms
6554 trgm_regex azjunk7 x[aeio]{1,2}q 144180 Bitmap Heap Scan 2245.885 ms

6543 HEAD azjunk7 x[aeio]{1,3}q 146526 Seq Scan 12807.513 ms
6554 trgm_regex azjunk7 x[aeio]{1,3}q 146526 Bitmap Heap Scan 15261.582 ms

6543 HEAD azjunk7 x[aeio]{1,4}q 146834 Seq Scan 13179.285 ms
6554 trgm_regex azjunk7 x[aeio]{1,4}q 146834 Seq Scan 13874.164 ms

6543 HEAD azjunk7 x[aeio]{2,4}q 20220 Seq Scan 13365.779 ms
6554 trgm_regex azjunk7 x[aeio]{2,4}q 20220 Seq Scan 13544.404 ms

6543 HEAD azjunk7 x[aeio]{3,4}q 2697 Seq Scan 13224.408 ms
6554 trgm_regex azjunk7 x[aeio]{3,4}q 2697 Seq Scan 13699.898 ms

6543 HEAD azjunk7 x[aeiou]q 158778 Seq Scan 12753.739 ms
6554 trgm_regex azjunk7 x[aeiou]q 158778 Seq Scan 12736.813 ms

6543 HEAD azjunk7 x[aeiou]{1}q 158778 Seq Scan 12385.108 ms
6554 trgm_regex azjunk7 x[aeiou]{1}q 158778 Seq Scan 12852.739 ms

6543 HEAD azjunk7 x[aeiou]{1,1}q 158778 Seq Scan 12665.614 ms
6554 trgm_regex azjunk7 x[aeiou]{1,1}q 158778 Seq Scan 12482.476 ms

6543 HEAD azjunk7 x[aeiou]{,2}q 0 Seq Scan 14886.647 ms
6554 trgm_regex azjunk7 x[aeiou]{,2}q 0 Bitmap Heap Scan 197.807 ms

6543 HEAD azjunk7 x[aeiou]{,10}q 0 Seq Scan 21428.416 ms
6554 trgm_regex azjunk7 x[aeiou]{,10}q 0 Bitmap Heap Scan 210.265 ms

6543 HEAD azjunk7 x[aeiou]{1,2}q 185669 Seq Scan 12896.338 ms
6554 trgm_regex azjunk7 x[aeiou]{1,2}q 185669 Seq Scan 13354.702 ms

6543 HEAD azjunk7 x[aeiou]{1,3}q 190274 Seq Scan 12730.517 ms
6554 trgm_regex azjunk7 x[aeiou]{1,3}q 190274 Seq Scan 13026.644 ms

6543 HEAD azjunk7 x[aeiou]{1,4}q 191017 Seq Scan 13664.473 ms
6554 trgm_regex azjunk7 x[aeiou]{1,4}q 191017 Seq Scan 13743.875 ms

6543 HEAD azjunk7 x[aeiou]{2,4}q 32732 Seq Scan 13360.429 ms
6554 trgm_regex azjunk7 x[aeiou]{2,4}q 32732 Seq Scan 13804.770 ms

6543 HEAD azjunk7 x[aeiou]{3,4}q 5449 Seq Scan 13170.928 ms
6554 trgm_regex azjunk7 x[aeiou]{3,4}q 5449 Seq Scan 13394.707 ms

6543 HEAD azjunk7 x[aeiou]{1,5}q 191160 Seq Scan 13591.866 ms
6554 trgm_regex azjunk7 x[aeiou]{1,5}q 191160 Seq Scan 14158.325 ms

6543 HEAD azjunk7 x[aeiou]{2,5}q 32878 Seq Scan 13507.736 ms
6554 trgm_regex azjunk7 x[aeiou]{2,5}q 32878 Seq Scan 13687.159 ms

6543 HEAD azjunk7 x[aeiou]{4,5}q 903 Seq Scan 13329.291 ms
6554 trgm_regex azjunk7 x[aeiou]{4,5}q 903 Seq Scan 13645.331 ms

6543 HEAD azjunk7 x[aeiouy]q 190245 Seq Scan 12331.375 ms
6554 trgm_regex azjunk7 x[aeiouy]q 190245 Seq Scan 12726.390 ms

6543 HEAD azjunk7 x[aeiouy]{1}q 190245 Seq Scan 12752.629 ms
6554 trgm_regex azjunk7 x[aeiouy]{1}q 190245 Seq Scan 12712.805 ms

6543 HEAD azjunk7 x[aeiouy]{1,1}q 190245 Seq Scan 12500.269 ms
6554 trgm_regex azjunk7 x[aeiouy]{1,1}q 190245 Seq Scan 12863.557 ms

6543 HEAD azjunk7 x[aeiouy]{,2}q 0 Seq Scan 14746.988 ms
6554 trgm_regex azjunk7 x[aeiouy]{,2}q 0 Bitmap Heap Scan 194.024 ms

6543 HEAD azjunk7 x[aeiouy]{,10}q 0 Seq Scan 21648.192 ms
6554 trgm_regex azjunk7 x[aeiouy]{,10}q 0 Bitmap Heap Scan 208.955 ms

6543 HEAD azjunk7 x[aeiouy]{1,2}q 228677 Seq Scan 13359.817 ms
6554 trgm_regex azjunk7 x[aeiouy]{1,2}q 228677 Seq Scan 13358.769 ms

6543 HEAD azjunk7 x[aeiouy]{1,3}q 236512 Seq Scan 13191.587 ms
6554 trgm_regex azjunk7 x[aeiouy]{1,3}q 236512 Seq Scan 13504.745 ms

6543 HEAD azjunk7 x[aeiouy]{1,4}q 238061 Seq Scan 13756.733 ms
6554 trgm_regex azjunk7 x[aeiouy]{1,4}q 238061 Seq Scan 13929.557 ms

6543 HEAD azjunk7 x[aeiouy]{2,4}q 48681 Seq Scan 13766.984 ms
6554 trgm_regex azjunk7 x[aeiouy]{2,4}q 48681 Seq Scan 14135.231 ms

6543 HEAD azjunk7 x[aeiouy]{3,4}q 9602 Seq Scan 13429.259 ms
6554 trgm_regex azjunk7 x[aeiouy]{3,4}q 9602 Seq Scan 13539.163 ms

6543 HEAD azjunk7 x[aeiouy]{1,5}q 238407 Seq Scan 13863.009 ms
6554 trgm_regex azjunk7 x[aeiouy]{1,5}q 238407 Seq Scan 14091.161 ms

6543 HEAD azjunk7 x[aeiouy]{2,5}q 49031 Seq Scan 14006.522 ms
6554 trgm_regex azjunk7 x[aeiouy]{2,5}q 49031 Seq Scan 14105.039 ms

6543 HEAD azjunk7 x[aeiouy]{4,5}q 1935 Seq Scan 13718.130 ms
6554 trgm_regex azjunk7 x[aeiouy]{4,5}q 1935 Seq Scan 14032.751 ms

(You asked also for testing against real text, I'll probably some of that too (although I do not
expect all that many differences).

Thanks, great work!

Erik Rijkers

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#27Heikki Linnakangas
hlinnakangas@vmware.com
In reply to: Alexander Korotkov (#25)
Re: WIP: index support for regexp search

One thing that bothers me with this algoritm is that the overflow
mechanism is all-or-nothing. In many cases, even when there is a huge
number of states in the diagram, you could still extract at least a few
trigrams that must be present in any matching string, with little
effort. At least, it seems like that to a human :-).

For example, consider this:

explain analyze select count(*) from azjunk4 where txt ~
('^aabaacaadaaeaafaagaahaaiaajaakaalaamaanaaoaapaaqaaraasaataauaavaawaaxaayaazabaabbabcabdabeabfabgabhabiabjabkablabmabnaboabpabqabrabsabtabuabvabwabxabyabzacaacbaccacdaceacfacgachaciacjackaclacmacnacoacpacqacracsactacuacvacwacxacyaczadaadbadcaddadeadfadgadhadiadjadkadladmadnadoadpadqadradsadtaduadvadwadxadyadzaeaaebaecaedaeeaefaegaehaeiaejaekaelaemaenaeoaepaeqaeraesaetaeuaevaewaexaeyaezafaafbafcafdafeaffafgafhafiafjafkaflafmafnafoafpafqafrafsaftafuafvafwafxafyafzagaagbagcagdageagfaggaghagiagjagkaglagmagnagoagpagqagragsagtaguagvagwagxagyagzahaahbahcahdaheahfahgahhahiahjahkahlahmahnahoahpahqahrahs$');

you get a query plan like this (the long regexp string edited out):

Aggregate (cost=228148.02..228148.03 rows=1 width=0) (actual
time=131.100..131
.101 rows=1 loops=1)
-> Bitmap Heap Scan on azjunk4 (cost=228144.01..228148.02 rows=1
width=0) (
actual time=131.096..131.096 rows=0 loops=1)
Recheck Cond: (txt ~ <ridiculously long regexp>)
Rows Removed by Index Recheck: 10000
-> Bitmap Index Scan on azjunk4_trgmrgx_txt_01_idx
(cost=0.00..228144
.01 rows=1 width=0) (actual time=82.914..82.914 rows=10000 loops=1)
Index Cond: (txt ~ <ridiculously long regexp>)
Total runtime: 131.230 ms
(7 rows)

That ridiculously long string exceeds the number of states (I think,
could be number of paths or arcs too), and the algorithm gives up,
resorting to scanning the whole index as can be seen by the "Rows
Removed by Index Recheck" line. However, it's easy to see that any
matching string must contain *any* of the possible trigrams the
algorithm extracts. If it could safely return just a few of them, say
"aab" and "abz", and discard the rest, that would already be much better
than a full index scan.

Would it be safe to simply stop short the depth-first search on
overflow, and proceed with the graph that was constructed up to that point?

- Heikki

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#28Alexander Korotkov
aekorotkov@gmail.com
In reply to: Heikki Linnakangas (#27)
1 attachment(s)
Re: WIP: index support for regexp search

On Thu, Nov 29, 2012 at 5:25 PM, Heikki Linnakangas <hlinnakangas@vmware.com

wrote:

One thing that bothers me with this algoritm is that the overflow
mechanism is all-or-nothing. In many cases, even when there is a huge
number of states in the diagram, you could still extract at least a few
trigrams that must be present in any matching string, with little effort.
At least, it seems like that to a human :-).

For example, consider this:

explain analyze select count(*) from azjunk4 where txt ~ ('^**
aabaacaadaaeaafaagaahaaiaajaak**aalaamaanaaoaapaaqaaraasaataau**
aavaawaaxaayaazabaabbabcabdabe**abfabgabhabiabjabkablabmabnabo**
abpabqabrabsabtabuabvabwabxaby**abzacaacbaccacdaceacfacgachaci**
acjackaclacmacnacoacpacqacracs**actacuacvacwacxacyaczadaadbadc**
addadeadfadgadhadiadjadkadladm**adnadoadpadqadradsadtaduadvadw**
adxadyadzaeaaebaecaedaeeaefaeg**aehaeiaejaekaelaemaenaeoaepaeq**
aeraesaetaeuaevaewaexaeyaezafa**afbafcafdafeaffafgafhafiafjafk**
aflafmafnafoafpafqafrafsaftafu**afvafwafxafyafzagaagbagcagdage**
agfaggaghagiagjagkaglagmagnago**agpagqagragsagtaguagvagwagxagy**
agzahaahbahcahdaheahfahgahhahi**ahjahkahlahmahnahoahpahqahrahs**$');

you get a query plan like this (the long regexp string edited out):

Aggregate (cost=228148.02..228148.03 rows=1 width=0) (actual
time=131.100..131
.101 rows=1 loops=1)
-> Bitmap Heap Scan on azjunk4 (cost=228144.01..228148.02 rows=1
width=0) (
actual time=131.096..131.096 rows=0 loops=1)
Recheck Cond: (txt ~ <ridiculously long regexp>)
Rows Removed by Index Recheck: 10000
-> Bitmap Index Scan on azjunk4_trgmrgx_txt_01_idx
(cost=0.00..228144
.01 rows=1 width=0) (actual time=82.914..82.914 rows=10000 loops=1)
Index Cond: (txt ~ <ridiculously long regexp>)
Total runtime: 131.230 ms
(7 rows)

That ridiculously long string exceeds the number of states (I think, could
be number of paths or arcs too), and the algorithm gives up, resorting to
scanning the whole index as can be seen by the "Rows Removed by Index
Recheck" line. However, it's easy to see that any matching string must
contain *any* of the possible trigrams the algorithm extracts. If it could
safely return just a few of them, say "aab" and "abz", and discard the
rest, that would already be much better than a full index scan.

Would it be safe to simply stop short the depth-first search on overflow,
and proceed with the graph that was constructed up to that point?

For depth-first it's not. But your proposal naturally makes sense. I've
changed it to breadth-first search. And then it's safe to mark all
unprocessed states as final when overflow. It means that we assume every
unprocessed branch to immediately finish with matching (this can give us
more false positives but no false negatives).
For overflow of matrix collection, it's safe to do just OR between all the
trigrams.
New version of patch is attached.

------
With best regards,
Alexander Korotkov.

Attachments:

trgm-regexp-0.7.patch.gzapplication/x-gzip; name=trgm-regexp-0.7.patch.gzDownload
�;��P�<kWK�������� /Q�1kq�$�����LN.��.�c�M��='�����~���������U�v����U��E�:�C!wL�
}{�3�C2�y/���v���z��kA03�R�Q�w��'�k����[���V���Z{���J��a�'�ju�L����0�=�L�)��?;�p����8��Sq��_/�����������w��1��?.���g�B�.{iC����k�W'm���4��DYI'-����O����j����Z�MJS*3TV�P��p��W�mR���U7�~��T��j��(�J��m%hN�D��=������u�]o[���G�U~Et���N=V�RC��u��~8��.�����I_�*i�R���0��������K�}o&�,��
�"MHhdH	�����Q����U2��a)������s�.<�R�-h����+��B���a���T�?��Wb1sA+�O����~6�Q�JJK3��v�+�D��iQk��2��>k�T7�vc�j�R�
P�WO��o��4�b����k��z��:�k�hK���X~���#�������G'���g����:��H�}����m��K%�'X�O��Z�������Y��{s���m�;��W�����r�
�A6�zgoduj5SvG��k��
���
����.8����F��w���\����?�]�
������
`�PG�@|�8>}�M�wt�x��?-�	����oR��QB�h�{4�=��^5��4��������[����+��ypg��<�6*8�M�?�����G�j�V���ec��F��Wkw��e6~�������)��7���jr��&�OE�FlK��������o���8uz�O�N�Mcw/�������VD�����J�^��s������W�O���g�5u�c6t���Oe2wMN6�B����Z���s5�(����6�4�LB[�e
���������=���[>Y�t����M���q�k�j��v�a�s��j��;W�F��F+)����D@@Q��
�*L����0������a��3��s���j�;
m'�N�	m7����S�<�=7����]%N�!�T�Ph�����X�_�u4��V+5����j'e���#]S]�>��dq�F�G��Y�����V�x%D�4��I��<�{���T��<��p1W.����2�������l7l5h�����<�u(nw��_�{�n'b��c��o������?{'��g{q>8>�t��7(�r�$�@�m�D���=q�ETV��/���Q��fka~�}e���$������������A����!b�O%<!|�l0:x�M�3��`s��d=�O��`.M����oXM�����R�4�	���/,k�6�l7��$�A�y=Z���/�����u�F��MU�Qo�%����m��7����RC�S���o�J�
.����4�a�i����
 ��#(|���a;����r��mp����CoL����
�J�)������Ip��k�hz�A�B
PQ�)���S��b�cW`
�!$�ts���#������Tf�����"���4�4BL�7��Q�`2S�-bH����u0+��D }�������
(��r�i^�����0��=�:d!4_p�H���<�_���p+���c��Z�~d����+�]0e��1��O����C�K�JY���s�%1��|W�O�m.5;�R��(���*�*�����>����i`"E�����c����8'�X7��(L7B6YBl��H�7	t�y��!FU	k
G��C��7���f�v��w����-B��m���\�xx��G{K���2�{5���!��&y������5��	
��!N5|7��oM^���\�Zp��$��h�G{��Z���
sC���Od4@��a
B����t"�@�o�o>�^��{��e�zv�n���0�S�,0m��;x*
�s�L'��QY�r�o���\�Ku*V8T�W��T���uy��x�����q�y#=��t��������"F���*s�e��`2j����U~���C�= �M��c5��,�dv7r�7������N(�����O�Y�aV�(id���''����5#4n0?jA��i��T�mde)*C�7�OA����A:U(�O��!U��J����*V*b�:�Z�X+	����s��)t��� ��09�*�s��������7*7����U&����`RB�h?V ���	����yp	T�l$�>A�������0� �]Q�P0a��~'�l{�b�q���l�?�]�i`A9�����s����,����GE���W!�	�������HAVg��t�M��D\�|��ge/y�#�a����;������t�3#��8��`��d��\�E�� ��G���	C\D��G��tPI��m�������N�^1-�n� ��Z�����u�sHp=�^����(������j����&X���-���fh��.��J2����R��8���&*�/q�o��	_R�-BOX��9���E�Zf��Y�i^vo�O���������Q�C�g@��A����4�[y�T��h���c�X������M\����e��O<��F��k#9#^��Rs�	gs��|�5�ag�]�-��6���^�*��*v�;48&���g����PM��"qu��ZK���VD`�x�\��#]���2����&.������,�|��[iF*��@b�=n��o ��6^��G�I{N�$�>�;nG��9���^�h�'�k?��)O����s\�2S��_�o?QI-�J��A�+�����x�{P��3\����c�l�����z����{�%�C��f������ke����@�!n:�;�����C����������",���A�_o������P!/S/f�E=���1fT������8�'3pE�8�?�T�uUB/�)���!bG&~��5S!�]�D��t1��1#G�(%�k3D��W&�R�9�u���p�����L��f�f��%�u!���Z��H�!�&q7�]!�e�%�K>W�51O�%�,��N+F���?A�]CL$I�@�T��$�e/P���5���T_x�/)���a8�_�/KT1_������e��y���=�c|c�RXB�#fw6�~������7__��������j�j{
)���!���D�7F\b��
���&����6.���IR��0�]aF>� z4`�"���c:�ZqRRM��vp���9��pLQ���F��������ex�v-�H[��cY����tO����SE`��4� ��-��}!��A���Z}�F~{���Z-�9H��|J�m����!��?RF��\G��\OQ�Jio{�l=�c���N^�0�a�t]y���@�ia~��z�2�`�ct�q�~4�����D���&k4��;lX���R�Y��Tp  �MT��d����r������Hf����+�����9��BN]�gN8��T\�C���5�N��--���v^.������p~�O�>���Y�I�xK�����S��H�M�VY�Ztz��h|�����+b�m�a4Z���px�g�4����,�D5=��x��:I��
.9%�@����X���5fUT��]�e'*L�ns���O����h����|Ck'r�����*9���>tyC�`H���rY<rL��)�fj0���������([�"���1��o���TS�)��.V	���������jYHf|O���Uv�n�-3d����"u������*�{��Ao�F��q
&����/;����R<)h�(fjf����S6pX�16�����V�he���/e����0�w�Fko7gi�c����tSS~����AT�����S����}���\����7��j�����FV��x�L��y	LN�o=s����cLz?h��x�9�u��c��s�Z���r��H/a���b��-%�L�ka�|����j�\��Ds��30:�wb�t���#h�6��	�d0����"�������^L��dc��i��x"^�<*��1lLE���	r�r>(3�x����Y��%U_6��E`�|�����-!�<`P`�}\�u$\�eF��@�CL�k�
+	�T�1%��	g�d��.&�]�#�kx�6�x����ob��W3��VD3�
p-'z�Lm8���@������Al������$P���j�BF�d�tq��u.RM����������k���
XD�,.�Bvdf��f���s��|�����E�,=�.cK�F�����XG�y08n���G��\/��Z�	W2���C7�7]�cl�s��b+�VFEX�
&�:��Xw������j�2FE\�+��1���+�;~��8F*����	,x��
���nz|P�cDq���s�A������
H�L3�����jc��)���
|�x@
��9tq�![
8��p�7FbU�IM4���"�NIR"�� ����?O��;�����4\G=HU�0�9�c�{�\Y�!DU���e�tQ2W6D��.m�d	S���#'��
/
'��#1r��hP��*b6��Z2�%�G���f~jD7xjNSFt�2�����.l�c�2P*]�E�������o5Z8�N�\��J���.���*�T��e��Nt�����{��a�`�-Y��"9��VI�Y/�pl���Fk��{s|��Fk���|����(�eA��kr<��[����h�60>�i����,�k��,O��X��7�\J�9�D�F��.f�o ���NW)+�����=cO,P/'+\�L�W1/�x���oj��xo�&��������9j~������tM�5���3<�B7���%Wz���%�B�IP�M�(X��-���~�5��Z1���!{��j���"2�V��x���yz�(��n��x)������v�F�V@'�$V|W����EQ�j��g�j`��������xb9�d������y9�
��"#��>o_�`X�e���������$����n��n�{��Y��,a���o+��G��������J��������������*m;���!!������TnFJ��9�YjN�l3	��&w�!&�)tz�J�>���{~�������c���|�r~���lM������w���FEPy��8����k��uB�>��<TP"�gr���,��8l����(_[�bEa,��!���e�
�3������f�q�Z�gl7��C,���r���=�Q��2���b{�8��b��&.*O^�rdjA����g�#h1���l='I��D���k�I�����	7�����TK�[J(��$HJ�k��]bM�F�$�C�b.{�Z����������<Q*
Q4���Q^6v
 h�U����r��3��p[�%H�)Ww2�����5�%,����T��4���]�Qk�����:qk���|S'���Q���L:[���6Pj������-Q�z�Z�C�s��V��ff_G<~%��V�1����o�uLfDQ��<x�*a`	+N"1�`�E��bdZ��0�����*&������23�32��)i���jh3F�����!��.��/������� Z��w���z%��X�� �?�=kWG���WL87����N����������X����F0��Q4��l~��gwu�����|�9�����~U�����7pl��=��5E���]B�
����f���)�c�PK������K�
4����\��o3_��g����0��2��G�������v$���%��m��������v���LT��_�b�F�Jp}�[
��h'�5q�/�"�u�{�=/����4n���W����_M��x�* e�&e�@&���	���?�(7��^,./E\����X����%B['�O~�}|���na�Br���D�������00��"1p`���G��b5��F�;���A��p���S8|��x[�F���tTB�V���d���J��$�|W�	kRc�%�� �9E�a�&)�<���6�r"���%���1�%�s\�"�E�,Yd��9�1�$�c;0�2�� �b�b!�A�X,F���|������']���r�8���P�r�E
1��^�Sg:Y�:�D�3��-{T�v�l)Y8G\F$`�n���
�c�Hb�	���::������&[�pD�D�{�*	B�1�l-r���A���O�r��i��a�F�Y�O�4�v;�T�������t�U���u�����4JZ?+��H�@�W�(���H�����`�3�E�i'w;n*���D99���8��>d���d&�!*�0
`s�����j �X�G��LL�w;������d0-�H��>����b.b��/���w�Xl������XG�R0��q�����;����w����O�	����#���#�����Q�!5����Y1�B5u,��������!������Vd��
eA@���u�
ey������k����j�eC8R[��&�:���5k"��sH���{�����V&}-o(�
�������{g�6���aL/A���v�f/n"x�LgJ�lh��#��;���T���5�'��rr��6z,�+����In���l2����������!�R��������>�/O
��1|�s"����<��"�Q�n'�Pg9�y�V��\�Sz�{Y����l�	�`���|���hT�~{��!u)<��0�S/P�a����6'�0�c�j
(T=�@��gs?g������w�����Q�c��E��b�MzI��;�X�N�UH��S�w^{s�3�Pv�0g��FF>��o��Wl���FI�����n���(�b�#�aH���{�v�52�1H/��1�����-3���������d�d��L�K��5LF"��*'����+�x�5#�!E\��u�.���o
�hi]T�?�n��3�y����DPQ�����q����\�}��?U���)u"|��=r�[L9��X����S�P(���Y�P��<��MVmh��3~&�@m.S��g���Z��R���@���_}2���1�w��
, ��Y@�LH2e�F����[i�����L���M�����^,���0�S��C	Ma��<�S����zK�K��j��A3�����*��,�o�	�m(���#�A`��������!"<F����"����/���LB�L�%[�QJJi�����A>��� ���I,Nt#B�o�T�`�����JA7J��r��p�H{�9|�p|���e�!-�����	$
*��F��p2�
C8��q�(,cF#C�L�I`�DTr��\��M��ULBD�7	&<d�'�ep���^H����(�A�t�.e��a
�:%F6	�	>��[�|S����2���^qeB�LW>r;D��l���S���P�|������2v>6��%�R��*NL��+m���{(��\��mf�r1)
,H&gZz�W��6������O��m�!��6�?p-JG����f����KH^�3]������G�#���1j��g�X+�%��p{�tj���J�����Gk2�MFP�l	���&�{��@eW�1^�����	"�m��F��y��lIk�r��6AX�_
�����j"1�K�H�9��Ag�A�������2Q������	4�~S��������"	�@�Y�����b+� t��k��!>�5��@k������N��k�2������a.?�������gG���1�GJ�H������O�9;��)NRH�]��F9��q����=�
a�/?ZRqT�d�!�f8$�V����9$�S8�B��HY��Q������L��-�}+�����#S�����N4(��1`�	3���1�M��,��,*��eM�x��Z��@A�����9\8�fh����jz �yD��}�$�7�GI�d4T��	:�8�����%N��u#���=V�N�b���<4�;uC��vrT���9\~���|�
C��w��;��1B%�E���
�����\����G�]���nD��d]����@�=	%�B9xwmh������$�H�4]��?����u+������xzOqkX��Ra�[��M}b�����P�.��M<���	�*p8.\���qh����{-��lr`�~��H���etG�Fy]�����`[b�O����)�~b4�(���-!���,1vt��O��77���c,g�.m�R��Im�af"Lz���}�u����2����������K!W��D�l�D���]��+1���1���4y� ��2)�DE�_J0y{��C��r�-��?,��s���?a��*`���Y���Z�#�8�.Kk�E��M�{E��L}{}8�J�h�=�9@�q`��`�+��0�������EC��W�n���l�Q=����vPY���������F���
�w����t��%Tz�s�����KS�2k��W~�����WeL�
NJ������
���#���\YL���A�u8W�;�"P����d����2����6��H%��J*���.��	��
��5LXq������]|�b���%,t�O<,\����H��8���s3�Jw��M-]���E6��lR�E)s��!H�l;����\�a��v�z��G��YP@��S�&�������+��[����<�����:
aZxD/�]���Z3G��?P+Q�$�]>�KA-�PhM5��rmV 3s���:����g��d�&�|9���|�s���V��j�#���u_������m��j�u�P���Ju8��f�z�v�L���!�:m����l1A�D'0�cx�"���s`5U*S?rHA��P����%�����2��qNm�����������n�����
����O':&�/��;}�/
u�����c��
�;1kq��,����A�����^�7���C"���1��U!%K��E���J��b��4�@���yhP�O�fL����Kj4��x�����d�\x�X��=q�b�~��IV����
���3)^��/�>
�p�f3��##�\o0�z_n�;\��*b�}r��v������0��>��E��]������n��z���sK Z�����aX�7��<��|4���f��h��p��QP�A>���W�
Z��=��I�����L��������f2�C��3�h]��s�l��;�a��?*���Q�[�s~<������T���\�����E/���!���Dt/��� ���������t���..��`w�C�u�2���6�t��@���"} (X��,6j1P�.���������Z?g,�,�?�rldcp��������+�s����,Xe�l����")cs�����=&T�1��aB��������J*s�1N�����E�Y����4����7�
�h��$y��r���1&���������qzs�������XE�
Jsc(�E��0��{�-D[)��.��9���!I�.|Z����&�9UI�����`@;f�J|VmPP��(%c'%�chQ�/5lT4��t2�@F�"2�������xQ�r����+�m��:O�}���O9����f��!^%jp����	�X
�*
�R��^V�2����	�^���S������W�MQ���ab���F��>����Q4kT�������x�6FZZf�`8b�D:����������n7��?>���������]a��a����g��m%����1�3�,S�;��Kn<53���$�yB�']I{��S���������O��X�D�}����"G��U��=�.�?�l���_U�xp��`x���QZ	;jJ2�
��G�5��u� \7����R��( t���~���������������Kn��l�����U��M��4;��D0�2�)�`=n������"W��J���L!����F�J�
�e��}w��Tu��n@Q�Nu����Ja��o�:.��hr�c��R�s���8������/(��a]�x�
Ox��E�����[�~��^Z��
M�cTZln�YJ�H�}��1z��,�#���$��%:����jUL�Th��=x!���#I��t�D�x�
����+:������n��n�����lE��tH|��Y�@�L������8u�+����\��#w=���=�3�Dt�����zc��$
E��(�Z��`9��o](��\��\�:t�{����b��(�V�>�r�3�~�Wo�U*�/��J��^_�����i��Y��:�d�_o@����\Z��?�
�*�[�)L������Z_����\cSF���f*��1?Mi��OP���{�-����Tw�D��S�7��}���9
\ ��R�>C���w-��j\��}�"w�����N�S��y���k�"��U�d��Ka)�gT����\�z��H�w�M�����	E
%��T$�D�.�hxb�,U�������!�^k��@������~3"x����ik��o)�%I���G����P�F(�?��CWA�XnA��e���<��/k�����d�F���/D�_/#4B����`�@(q�	��_�@�X���_eU4����$��
�Wv�Je���Pl�s8��_	0�{���'kny�.&�tgF%�����}�7��{���Fc�(�D2��Gf#S%�rYMIE�|-
���k�����5��S�jK�XqP/��`a%��k�^�������|���&\�-K�
��d��ue�>
�	$^�s�$s_�#�'��$��G��(�b�,��c`v8�$A]�Z�}�k�\�
�uX*�||���]�T�:)����!���RI
�_�U�Z�"9�f��I�%�]3�z�B� ��z&CzAB.��q�ta�5N�6���d)�
�T�^=��W*j��W�Bx��[]�����!�=�rU�&��%!vJ��K[�����=�6���l���$�+��L�?$����V�c���C]�D�z�4za����<*������C�����*~��pq}B��Y[\��*�}��+�XFHH�9=�!��S���D��"��D�R8m,�&K<��7(/a��������"b��]|��e�m%%<��jB����f!6�D_Y�X6� ���S'%�^�4,�,7�(�|��'����hS���l�q��6$3��0ZA�G��)"I+MQ����t���M��������[kpE��5����8qk ��`+�cP�au��;z
$�t���0w���5�4��@/9&X���d} Y����R}��S�����V��4�/���
�-�;�O����5�e�h��HWSQ�'W?�F�o�dA|c{
�Yh��@���q!+��?����@�������G��`���������s���c����c����7#��"����X5$lN���wo�����n���Zx�-���~�5`�~[�H�u�S<�R�M���l��B`.��\	�3������r���n+	�����b,|�
�g�GXl����5�J�xp)�e��s�j5Kj�9���H��qqb1^�~�k�;�8D$����]b������q��=#��O��F�#R��F��-]����.�K��\`w������|���x����:�Gq/�QL��0�R�3���K�y��fE�	|
8�e!�W���F������?�gZ��/�����{��Z��<p�$H�#!1bP)�S;�$sg���D�Q���8i��z��/EI�u\�F�h��&}.�������I6�Y�!4���vq������Y��}��������'g��?h��|�<�������!�9Jd� :��)LZ��D��^>H:%#i <����!��r��2�|Bq%�&���E����J��N;���#S���7���C�a"��V�LO;�"��G�q���NwM��
q&�w��4j�(�{_T=�T�M5���0�5%���C$��WH���o��*�Vn����\
�eP5���|�\!|�Q9��q�$�(Y���a�'����N����{���>�Y>����V5��1���{�x����_�.0��W�
|���}�j"��a�5���U{��q`M�J;��d�����BcI�������x�9H����H]R�+$%X�+iH�J�L�10�;����:�q��T���M�'������-$���=a�-7�[��X�7O��0��l���T��%���-g%8��R>���o��L�js�};�+� .�W��1Y�%4�wi6�*7(@�RnP��[Jb|���w�*7�c�
��6�������(���8x������[i��8k�T��VW1
$�!!q�46�ua�Q����=��������a��V����!��";;�\D�KAI����a����O}�1h,T�oL��o|���-Gg��w�l�fY�����!	�H���U4�:����D����W��]y9����(�V���q3wa&k
�*�}�K�����M|����uV��+�J�2����uV�c�"�C������x�?�����v���eS��.�L#��m����-�������Z��1Z�Z# >��*�����������h��A��f$'n��G�����ph
�A�R~,�[�smY�yW��MouEi��w	T�1���jWL��[���3%�A�@���`��Bn�JCG��S�J[�`���6��]��[��|}�m�89�4\���X�?��$Q�p�Wq��|�:�������)b����H���uwf�:���,�>���q0���xR�kdk��G��a�%�RRyN�`������l���Q���y�
������"yZ*�9�0���al��������ihZ4P@�{�������z&��������eEXg��j~Z6���p]>-^m����g<r3�&Fkg��ip�c�
��:����)g?��J"e����P��=LZ8�������oUK���g�A��@�In@���1,�!��T�T��]�bbj�����J�V��F���8��S�U�0���y]��VZa�[{Si.��Jmh�=K��T�Mp�q��M\�z��Y�����������
%r�a���C`�0�V��G0�N�p3H������,7�QcP
S�%��G��-���q���|���"��7��
7r��W���m�|���(:��V!�ae���&a������3_
������������7!|�	}�������Q|=6u���cRxw`��{R����������*���������)��U�0R/B8��.7HUnh������b������<8;���n��9���!��%��RD����8��$q�"l���H����r9G/x�y�c���5o�������NP?��y�>��������Iw�����������g��<>�~m_/������8��x�8��}�.���Rx��'��(���F
�5i����'Y��.x������^���r���A��Q�Jx���vh��,+���;�|���ua-2�`��FP��!r��hQ�'�M1��q���OV�N�
�\�G�0��.��3x�w�?�0�p�d&�2�'��qfl;���C������9��=�=�>xq|v��������:>@,�����?9*��B�n�XRN�Ac��J��0�����5��om~Up(�0��.���Y�������"
������4R�����k<��m�i�w����'&���}�z��&P
�w����e����OuN]�<:�vIL��14q��:�	��%1���,I.m\�3�M�XL�a�V-������R�}�Q@��w�~��"T�U^�{V�z�������l��8c0����V�����g���yp������Y<Kz��k��0��
�a�i+:���^�jh��S������2f�������67�oK�p����&[[�x��� �o3���x�=����wrQ�ju�!Z��� �����{�lr�����{�~�����s?�]���\��������6��������wz@W��SL�Z ���X/]��1_�rP'lk�:�D�W�D)��opCw�b6���-J��tE6�F�Rw>�X�:9���M
ER,��|6��z��^�1�.0����L$������R8_�{�$����QP���Q�EF{G�~8|��G���g�������}�
r�II�I���7�aN0���k�����'����i�13�*��P����G[t��R����:����=���_����8���w�v�[�-n1(���2����V C�&,E�I��������O^<�}-0
�r������0�'���/�D(:;w[��o�P Nuv��:��<NUwz?J/3��d/�����7N�^���r�����o��X? F��-;K��e�5t��"�\O�8����k>�pC��mK�'�j��Hn7�y��H
�R��	&���goID���M��qR�M��D���rOyS
�����q>����
1 -9�Y������(=H��`6�jB�� *�D�7�%�H�<a9R��4���f�Bo�7����^�:�����A�-SyNgj��m��M�;�e�
G
o�+|��\�=��"q��������}�r��|��p1�QD�{�|�?z�q�p�=��0:���S����t��
�����14����U�O��3��'��yD�{)af#Jhf(2�Z�\�Dg���Bl�x�AV�������XU���1�f�q���b|���/�.�F0�
�qg��n�
�/{.�l6l/��������vd��
��b�����He_��+��
�,��h�e�<>��cVk���[L��u9#�1c��Mk��='�m&/)������h<I:����b����]czQC��V��H7�Pd8���tv�P�-��{}����n���9�{`�E�y��F1����!8�/�i,t����������90�6����=�������,O�����������/V�pe��h1Hw���+���w���W�_�;����������������OS��� �<hSa�����J�6"�M��������{�8G�Q�CG��`�\#	��f�l��0�P��L��5j���S�s>�]���psQ�p ?O�c���]@C��YO�>�"N��sX��
#29Alexander Korotkov
aekorotkov@gmail.com
In reply to: er (#26)
Re: WIP: index support for regexp search

Hi!

On Thu, Nov 29, 2012 at 12:58 PM, er <er@xs4all.nl> wrote:

On Mon, November 26, 2012 20:49, Alexander Korotkov wrote:

trgm-regexp-0.6.patch.gz

I ran the simple-minded tests against generated data (similar to the ones
I did in January 2012).
The problems of that older version seem pretty much all removed. (although
I didn't do much work
on it -- just reran these tests).

Thanks a lot for testing! Could you repeat for 0.7 version of patch which
has new overflow handling?

------
With best regards,
Alexander Korotkov.

#30Alexander Korotkov
aekorotkov@gmail.com
In reply to: Alexander Korotkov (#28)
Re: WIP: index support for regexp search

On Fri, Nov 30, 2012 at 3:20 PM, Alexander Korotkov <aekorotkov@gmail.com>wrote:

For depth-first it's not.

Oh, I didn't explained it.
In order to stop graph processing we need to be sure that we put all
outgoing arcs from state or assume that state to be final. In DFS we can be
in the final part of graph producing but still didn't add some arc (with
new trigram) from initial state directly to the final state. It obviously
leads to false negatives.

------
With best regards,
Alexander Korotkov.

#31Heikki Linnakangas
hlinnakangas@vmware.com
In reply to: Alexander Korotkov (#28)
Re: WIP: index support for regexp search

On 30.11.2012 13:20, Alexander Korotkov wrote:

On Thu, Nov 29, 2012 at 5:25 PM, Heikki Linnakangas<hlinnakangas@vmware.com

wrote:

Would it be safe to simply stop short the depth-first search on overflow,
and proceed with the graph that was constructed up to that point?

For depth-first it's not. But your proposal naturally makes sense. I've
changed it to breadth-first search. And then it's safe to mark all
unprocessed states as final when overflow. It means that we assume every
unprocessed branch to immediately finish with matching (this can give us
more false positives but no false negatives).
For overflow of matrix collection, it's safe to do just OR between all the
trigrams.
New version of patch is attached.

Thanks, sounds good.

I've spent quite a long time trying to understand the transformation the
getState/addKeys/addAcrs functions do to the original CNFA graph. I
think that still needs more comments to explain the steps involved in it.

One thing that occurs to me is that it might be better to delay
expanding colors to characters. You could build and transform the graph,
and even create the paths, all while operating on colors. You would end
up with lists of "color trigrams", consisting of sequences of three
colors that must appear in the source string. Only at the last step you
would expand the color trigrams to real character trigrams. I think that
would save a lot of processing while building the graph, if you have
colors that contain many characters. It would allow us to do better than
the fixed small MAX_COLOR_CHARS limit. For example with MAX_COLOR_CHARS
= 4 in the current patch, it's a shame that we can't do anything with a
fairly simple regexp like "^a[b-g]h$"

- Heikki

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#32Erik Rijkers
er@xs4all.nl
In reply to: Alexander Korotkov (#29)
1 attachment(s)
Re: WIP: index support for regexp search

On Fri, November 30, 2012 12:22, Alexander Korotkov wrote:

Hi!

On Thu, Nov 29, 2012 at 12:58 PM, er <er@xs4all.nl> wrote:

On Mon, November 26, 2012 20:49, Alexander Korotkov wrote:

I ran the simple-minded tests against generated data (similar to the ones
I did in January 2012).
The problems of that older version seem pretty much all removed. (although
I didn't do much work
on it -- just reran these tests).

Thanks a lot for testing! Could you repeat for 0.7 version of patch which
has new overflow handling?

I've attached a similar test re-run that compares HEAD with patch versions 0.6, and 0.7.

Erik Rijkers

Attachments:

trgm_compare.txt.gzapplication/x-gzip; name=trgm_compare.txt.gzDownload
#33Alexander Korotkov
aekorotkov@gmail.com
In reply to: Heikki Linnakangas (#31)
Re: WIP: index support for regexp search

On Fri, Nov 30, 2012 at 6:23 PM, Heikki Linnakangas <hlinnakangas@vmware.com

wrote:

On 30.11.2012 13:20, Alexander Korotkov wrote:

On Thu, Nov 29, 2012 at 5:25 PM, Heikki Linnakangas<hlinnakangas@**
vmware.com <hlinnakangas@vmware.com>

wrote:

Would it be safe to simply stop short the depth-first search on overflow,

and proceed with the graph that was constructed up to that point?

For depth-first it's not. But your proposal naturally makes sense. I've
changed it to breadth-first search. And then it's safe to mark all
unprocessed states as final when overflow. It means that we assume every
unprocessed branch to immediately finish with matching (this can give us
more false positives but no false negatives).
For overflow of matrix collection, it's safe to do just OR between all the
trigrams.
New version of patch is attached.

Thanks, sounds good.

I've spent quite a long time trying to understand the transformation the
getState/addKeys/addAcrs functions do to the original CNFA graph. I think
that still needs more comments to explain the steps involved in it.

One thing that occurs to me is that it might be better to delay expanding
colors to characters. You could build and transform the graph, and even
create the paths, all while operating on colors. You would end up with
lists of "color trigrams", consisting of sequences of three colors that
must appear in the source string. Only at the last step you would expand
the color trigrams to real character trigrams. I think that would save a
lot of processing while building the graph, if you have colors that contain
many characters. It would allow us to do better than the fixed small
MAX_COLOR_CHARS limit. For example with MAX_COLOR_CHARS = 4 in the current
patch, it's a shame that we can't do anything with a fairly simple regexp
like "^a[b-g]h$"

Nice idea to delay expanding colors to characters! Obviously, we should
delay expanding inly alphanumerical characters. Because non-alphanumberical
characters influence graph structure. Trying to implement...

------
With best regards,
Alexander Korotkov.

#34Alexander Korotkov
aekorotkov@gmail.com
In reply to: Erik Rijkers (#32)
Re: WIP: index support for regexp search

On Sat, Dec 1, 2012 at 3:22 PM, Erik Rijkers <er@xs4all.nl> wrote:

On Fri, November 30, 2012 12:22, Alexander Korotkov wrote:

Hi!

On Thu, Nov 29, 2012 at 12:58 PM, er <er@xs4all.nl> wrote:

On Mon, November 26, 2012 20:49, Alexander Korotkov wrote:

I ran the simple-minded tests against generated data (similar to the

ones

I did in January 2012).
The problems of that older version seem pretty much all removed.

(although

I didn't do much work
on it -- just reran these tests).

Thanks a lot for testing! Could you repeat for 0.7 version of patch which
has new overflow handling?

I've attached a similar test re-run that compares HEAD with patch versions
0.6, and 0.7.

Thanks! Did you write scripts for automated testing? I would be nice if you
share them.

------
With best regards,
Alexander Korotkov.

#35Tom Lane
tgl@sss.pgh.pa.us
In reply to: Alexander Korotkov (#33)
Re: WIP: index support for regexp search

Alexander Korotkov <aekorotkov@gmail.com> writes:

Nice idea to delay expanding colors to characters! Obviously, we should
delay expanding inly alphanumerical characters. Because non-alphanumberical
characters influence graph structure. Trying to implement...

Uh, why would that be? Colors are colors. The regexp machinery doesn't
care whether they represent alphanumerics or not. (Or to be more
precise, if there is a situation where it makes a difference, separate
colors will have been created for each set of characters that need to be
distinguished.)

regards, tom lane

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#36Erik Rijkers
er@xs4all.nl
In reply to: Alexander Korotkov (#34)
2 attachment(s)
Re: WIP: index support for regexp search

On Sun, December 2, 2012 19:07, Alexander Korotkov wrote:

I've attached a similar test re-run that compares HEAD with patch versions
0.6, and 0.7.

Thanks! Did you write scripts for automated testing? I would be nice if you
share them.

Sure, here they are.

The perl program does depend a bit on my particular setup (it reads the port from the
postgresql.conf of each instance, and the script knows the data_dir locations), but I suppose it's
easy enough to remove that.

(Just hardcode the %instances hash, instead of calling instances().)

If you need help to get them to run I can 'generalise' them, but for now I'll send them as they are.

Erik Rijkers

Attachments:

create_data.shapplication/x-shellscript; name=create_data.shDownload
trgm_regex_test.plapplication/x-perl; name=trgm_regex_test.plDownload
#37Heikki Linnakangas
hlinnakangas@vmware.com
In reply to: Tom Lane (#35)
Re: WIP: index support for regexp search

On 02.12.2012 20:19, Tom Lane wrote:

Alexander Korotkov<aekorotkov@gmail.com> writes:

Nice idea to delay expanding colors to characters! Obviously, we should
delay expanding inly alphanumerical characters. Because non-alphanumberical
characters influence graph structure. Trying to implement...

Uh, why would that be? Colors are colors. The regexp machinery doesn't
care whether they represent alphanumerics or not. (Or to be more
precise, if there is a situation where it makes a difference, separate
colors will have been created for each set of characters that need to be
distinguished.)

The regexp machinery doesn't care, but the trigrams that pg_trgm
extracts only contain alphanumeric characters. So if by looking at the
CNFA graph produced by the regexp machinery you conclude that any
matching strings must contain three-letter sequences "%oo" and "#oo",
you can just club them together into " oo" trigram.

I think you can run a pre-processing step to the colors, and merge
colors that are equivalent as far as trigrams are considered. For
example, if you have a color that contains only character '%', and
another that contains character '#', you can treat them as the same
hcolor. You might then be able to simplify the CNFA. Actually, it would
be even better if you could apply the pre-processing to the regexp
before the regexp machinery turns it into a CNFA. Not sure how easy it
would be to do such pre-processing.

BTW, why create the path matrix? You could check the "check" array of
trigrams in the consistent function directly against the graph.
Consistent should return true, iff there is a path through the graph
following only arcs that contain trigrams present in the check array.
Finding a path through a complex graph could be expensive, O(|E|), but
if the path is complex, the path matrix would be large as well, and
checking against a large matrix isn't exactly free either. It would
allow you to avoid "overflows" caused by having too many paths through
the graph.

- Heikki

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#38Alexander Korotkov
aekorotkov@gmail.com
In reply to: Heikki Linnakangas (#37)
Re: WIP: index support for regexp search

On Mon, Dec 3, 2012 at 2:05 PM, Heikki Linnakangas
<hlinnakangas@vmware.com>wrote:

On 02.12.2012 20:19, Tom Lane wrote:

Alexander Korotkov<aekorotkov@gmail.com> writes:

Nice idea to delay expanding colors to characters! Obviously, we should
delay expanding inly alphanumerical characters. Because
non-alphanumberical
characters influence graph structure. Trying to implement...

Uh, why would that be? Colors are colors. The regexp machinery doesn't
care whether they represent alphanumerics or not. (Or to be more
precise, if there is a situation where it makes a difference, separate
colors will have been created for each set of characters that need to be
distinguished.)

The regexp machinery doesn't care, but the trigrams that pg_trgm extracts
only contain alphanumeric characters. So if by looking at the CNFA graph
produced by the regexp machinery you conclude that any matching strings
must contain three-letter sequences "%oo" and "#oo", you can just club them
together into " oo" trigram.

I think you can run a pre-processing step to the colors, and merge colors
that are equivalent as far as trigrams are considered. For example, if you
have a color that contains only character '%', and another that contains
character '#', you can treat them as the same hcolor. You might then be
able to simplify the CNFA. Actually, it would be even better if you could
apply the pre-processing to the regexp before the regexp machinery turns it
into a CNFA. Not sure how easy it would be to do such pre-processing.

Treating colors as same should be possible only for colors which has no
alphanumeric characters, because colors are non-overlapping. However, this
optimization could be significant in some cases.

BTW, why create the path matrix? You could check the "check" array of

trigrams in the consistent function directly against the graph. Consistent
should return true, iff there is a path through the graph following only
arcs that contain trigrams present in the check array. Finding a path
through a complex graph could be expensive, O(|E|), but if the path is
complex, the path matrix would be large as well, and checking against a
large matrix isn't exactly free either. It would allow you to avoid
"overflows" caused by having too many paths through the graph.

Actually, I generally dislike path matrix for same reasons. But:
1) Output graphs could contain trigrams which are completely useless for
search. For example, for regex /(abcdefgh)*ijk/ we need only "ijk" trigram
while graph would contain much more.Path matrix is a method to get rid of
all of them.
2) If we use color trigrams then we need some criteria for which color
trigrams to expand into trigrams. Simultaneously, we shouldn't allow path
from initial state to the final by unexpanded trigrams. It seems much
harder to do with graph than with matrix.

------
With best regards,
Alexander Korotkov.

#39Alexander Korotkov
aekorotkov@gmail.com
In reply to: Alexander Korotkov (#38)
Re: WIP: index support for regexp search

On Mon, Dec 3, 2012 at 4:31 PM, Alexander Korotkov <aekorotkov@gmail.com>wrote:

Actually, I generally dislike path matrix for same reasons. But:
1) Output graphs could contain trigrams which are completely useless for
search. For example, for regex /(abcdefgh)*ijk/ we need only "ijk" trigram
while graph would contain much more.Path matrix is a method to get rid of
all of them.
2) If we use color trigrams then we need some criteria for which color
trigrams to expand into trigrams. Simultaneously, we shouldn't allow path
from initial state to the final by unexpanded trigrams. It seems much
harder to do with graph than with matrix.

Now, I have an idea about doing some not comprehensive but simple and fast
simplification of graph. I'm doing experiments now. In case of success we
could get rid of path matrix.

------
With best regards,
Alexander Korotkov.

#40Alexander Korotkov
aekorotkov@gmail.com
In reply to: Alexander Korotkov (#39)
1 attachment(s)
Re: WIP: index support for regexp search

On Fri, Dec 14, 2012 at 1:34 AM, Alexander Korotkov <aekorotkov@gmail.com>wrote:

On Mon, Dec 3, 2012 at 4:31 PM, Alexander Korotkov <aekorotkov@gmail.com>wrote:

Actually, I generally dislike path matrix for same reasons. But:
1) Output graphs could contain trigrams which are completely useless for
search. For example, for regex /(abcdefgh)*ijk/ we need only "ijk" trigram
while graph would contain much more.Path matrix is a method to get rid of
all of them.
2) If we use color trigrams then we need some criteria for which color
trigrams to expand into trigrams. Simultaneously, we shouldn't allow path
from initial state to the final by unexpanded trigrams. It seems much
harder to do with graph than with matrix.

Now, I have an idea about doing some not comprehensive but simple and fast
simplification of graph. I'm doing experiments now. In case of success we
could get rid of path matrix.

Attached patch have following changes:
1) Postphone expansion of colors. Graph are building on color trigrams.
2) Selective expansion of color trigrams into simple trigrams. All
non-expanded color trigrams are removed. Such removal leads to union of all
states pairs connected with corresponding arcs. Surely, this must no lead
to union of initial and final states: that could do all previous work
senseless.

------
With best regards,
Alexander Korotkov.

Attachments:

trgm-regexp-0.8.patch.gzapplication/x-gzip; name=trgm-regexp-0.8.patch.gzDownload
#41Erik Rijkers
er@xs4all.nl
In reply to: Alexander Korotkov (#40)
Re: WIP: index support for regexp search

On Sun, December 16, 2012 22:25, Alexander Korotkov wrote:

trgm-regexp-0.8.patch.gz 22 k

Hi Alexander,

I gave this a quick try; the patch works when compiled for DEBUG, but crashes as a
'speed'-compiled binary:

Compile for speed:

$ pg_config --configure
'--prefix=/home/aardvark/pg_stuff/pg_installations/pgsql.trgm_regex8' '--with-pgport=6556'
'--enable-depend' '--with-openssl' '--with-perl' '--with-libxml'

$ psql
psql (9.3devel-trgm_regex8-20121216_2336-c299477229559d4ee7db68720d86d3fb391db761)
Type "help" for help.

testdb=# explain analyze select txt from azjunk5 where txt ~ 'x[aeiouy]{2,5}q';
The connection to the server was lost. Attempting reset: Failed.
!> \q

log after such:
-----------------
2012-12-17 09:31:02.337 CET 15801 LOG: server process (PID 16903) was terminated by signal 11:
Segmentation fault
2012-12-17 09:31:02.337 CET 15801 DETAIL: Failed process was running: explain analyze select txt
from azjunk5 where txt ~ 'x[aeiouy]{2,5}q';
2012-12-17 09:31:02.347 CET 15801 LOG: terminating any other active server processes
2012-12-17 09:31:02.348 CET 17049 FATAL: the database system is in recovery mode
2012-12-17 09:31:02.722 CET 15801 LOG: all server processes terminated; reinitializing
2012-12-17 09:31:03.506 CET 17052 LOG: database system was interrupted; last known up at
2012-12-17 09:26:00 CET
2012-12-17 09:31:03.693 CET 17052 LOG: database system was not properly shut down; automatic
recovery in progress
2012-12-17 09:31:04.493 CET 17052 LOG: record with zero length at 2/7E3C7588
2012-12-17 09:31:04.494 CET 17052 LOG: redo is not required
2012-12-17 09:31:06.940 CET 15801 LOG: database system is ready to accept connections
----------------

A debug-compile with below options runs OK (so far):

Compile for debug:

$ pg_config --configure
'--prefix=/home/aardvark/pg_stuff/pg_installations/pgsql.trgm_regex8b' '--with-pgport=6560'
'--enable-depend' '--enable-cassert' '--enable-debug' '--with-openssl' '--with-perl'
'--with-libxml'

which does show some speed gain, I think. When I have time I'll post comparisons between HEAD,
versions 6, 7, 8. (BTW, is v6 still interesting?)

Thanks,

Erik Rijkers

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#42Alexander Korotkov
aekorotkov@gmail.com
In reply to: Erik Rijkers (#41)
Re: WIP: index support for regexp search

Hi!

On Mon, Dec 17, 2012 at 12:54 PM, Erik Rijkers <er@xs4all.nl> wrote:

On Sun, December 16, 2012 22:25, Alexander Korotkov wrote:

trgm-regexp-0.8.patch.gz 22 k

Hi Alexander,

I gave this a quick try; the patch works when compiled for DEBUG, but
crashes as a
'speed'-compiled binary:

Compile for speed:

$ pg_config --configure
'--prefix=/home/aardvark/pg_stuff/pg_installations/pgsql.trgm_regex8'
'--with-pgport=6556'
'--enable-depend' '--with-openssl' '--with-perl' '--with-libxml'

$ psql
psql
(9.3devel-trgm_regex8-20121216_2336-c299477229559d4ee7db68720d86d3fb391db761)
Type "help" for help.

testdb=# explain analyze select txt from azjunk5 where txt ~
'x[aeiouy]{2,5}q';
The connection to the server was lost. Attempting reset: Failed.
!> \q

Didn't reproduce it yet. Can you retry it with this line uncommented:
#define TRGM_REGEXP_DEBUG
Then we can see which stage it fails.

------
With best regards,
Alexander Korotkov.

#43Alexander Korotkov
aekorotkov@gmail.com
In reply to: Alexander Korotkov (#42)
1 attachment(s)
Re: WIP: index support for regexp search

On Mon, Dec 17, 2012 at 1:16 PM, Alexander Korotkov <aekorotkov@gmail.com>wrote:

Didn't reproduce it yet. Can you retry it with this line uncommented:
#define TRGM_REGEXP_DEBUG
Then we can see which stage it fails.

Bug is found and fixed in attached patch.

------
With best regards,
Alexander Korotkov.

Attachments:

trgm-regexp-0.9.patch.gzapplication/x-gzip; name=trgm-regexp-0.9.patch.gzDownload
#44Erik Rijkers
er@xs4all.nl
In reply to: Alexander Korotkov (#43)
1 attachment(s)
Re: WIP: index support for regexp search

On Tue, December 18, 2012 08:04, Alexander Korotkov wrote:

trgm-regexp-0.9.patch.gz 22 k

Hi.

I ran the same test again: HEAD versus trgm_regex v6, 7 and 9. In v9 there is some gain but also
some regression.

It remains a difficult problem...

If I get some time in the holidays I'll try to diversify the test program; it is now too simple.

Thanks,

Erik Rijkers

Attachments:

trgmre_6_7_9.txt.gzapplication/x-gzip; name=trgmre_6_7_9.txt.gzDownload
#45Alexander Korotkov
aekorotkov@gmail.com
In reply to: Erik Rijkers (#44)
Re: WIP: index support for regexp search

On Tue, Dec 18, 2012 at 11:45 AM, Erik Rijkers <er@xs4all.nl> wrote:

On Tue, December 18, 2012 08:04, Alexander Korotkov wrote:
I ran the same test again: HEAD versus trgm_regex v6, 7 and 9. In v9
there is some gain but also
some regression.

It remains a difficult problem...

If I get some time in the holidays I'll try to diversify the test program;
it is now too simple.

Note, that regexes which contains {,n} are likely not what do you expect.

test=# select 'xq' ~ 'x[aeiou]{,2}q';
?column?
----------
f
(1 row)

test=# select 'xa{,2}q' ~ 'x[aeiou]{,2}q';
?column?
----------
t
(1 row)

You should use {0,n} to express from 0 to n occurences.

------
With best regards,
Alexander Korotkov.

#46Erik Rijkers
er@xs4all.nl
In reply to: Alexander Korotkov (#45)
Re: WIP: index support for regexp search

On Tue, December 18, 2012 09:45, Alexander Korotkov wrote:

You should use {0,n} to express from 0 to n occurences.

Thanks, but I know that of course. It's a testing program; and in the end robustness with
unexpected or even wrong input is as important as performance. (to put it bluntly, I am also
trying to get your patch to fall over ;-))

Thanks,

Erik Rijkers

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#47Alexander Korotkov
aekorotkov@gmail.com
In reply to: Erik Rijkers (#46)
Re: WIP: index support for regexp search

On Tue, Dec 18, 2012 at 12:51 PM, Erik Rijkers <er@xs4all.nl> wrote:

On Tue, December 18, 2012 09:45, Alexander Korotkov wrote:

You should use {0,n} to express from 0 to n occurences.

Thanks, but I know that of course. It's a testing program; and in the end
robustness with
unexpected or even wrong input is as important as performance. (to put it
bluntly, I am also
trying to get your patch to fall over ;-))

I found most of regressions in 0.9 version to be in {,n} cases. New version
of patch use more of trigrams than previous versions.
For example for regex 'x[aeiou]{,2}q'.
In 0.7 version we use trigrams '__2', '_2_' and '__q'.
In 0.9 version we use trigrams 'xa_', 'xe_', 'xi_', 'xo_', 'xu_', '__2',
'_2_' and '__q'.

But, actually trigram '__2' or '_2_' never occurs. It enough to have one of
them, all others are just causing a slowdown. Simultaneously, we can't
decide reasonably which trigrams to use without knowing their frequencies.
For example, if trigrams 'xa_', 'xe_', 'xi_', 'xo_', 'xu_' were altogether
more rare than '__2', newer version of patch would be faster.

------
With best regards,
Alexander Korotkov.

#48Heikki Linnakangas
hlinnakangas@vmware.com
In reply to: Alexander Korotkov (#43)
5 attachment(s)
Re: WIP: index support for regexp search

On 18.12.2012 09:04, Alexander Korotkov wrote:

Bug is found and fixed in attached patch.

I finally got around to look at this. I like this new version, without
the path matrix, much better.

I spend quite some time honing the code and comments, trying to organize
it so that it's easier to understand. In particular, I divided the
processing more clearly into four separate stages, and added comments
indicating which functions and which fields in the structs are needed in
which state.

I understand the other stages fairly well now, but the transformation
from the source CNFA form into the transformed graph is still a black
box to me. The addKeys/addArcs functions still need more explanation.
Can you come up with some extra comments or refactoring to clarify those?

I'd like to see a few more regression test cases, to cover the various
overflow cases. In particular, I built with --enable-coverage and ran
"make installcheck", and it looks like the state merging code isn't
exercised at all. Report attached.

To visualize the graphs, I rewrote the debugging print* functions to
write the graphs in graphviz .dot format. That helped a lot. See
attached graphs, generated from the regexp '^(abc|def)(ghi|jk[lmn])$'.

There's still a lot of cleanup to do, I'm going to continue working on
this tomorrow, but wanted to shared what I have this far.

- Heikki

Attachments:

trgm-regexp-0.9-heikki-1.patchtext/x-diff; name=trgm-regexp-0.9-heikki-1.patchDownload
diff --git a/contrib/pg_trgm/Makefile b/contrib/pg_trgm/Makefile
index 64fd69f..8033733 100644
--- a/contrib/pg_trgm/Makefile
+++ b/contrib/pg_trgm/Makefile
@@ -1,7 +1,7 @@
 # contrib/pg_trgm/Makefile
 
 MODULE_big = pg_trgm
-OBJS = trgm_op.o trgm_gist.o trgm_gin.o
+OBJS = trgm_op.o trgm_gist.o trgm_gin.o trgm_regexp.o
 
 EXTENSION = pg_trgm
 DATA = pg_trgm--1.0.sql pg_trgm--unpackaged--1.0.sql
diff --git a/contrib/pg_trgm/expected/pg_trgm.out b/contrib/pg_trgm/expected/pg_trgm.out
index 81d0ca8..ee0131f 100644
--- a/contrib/pg_trgm/expected/pg_trgm.out
+++ b/contrib/pg_trgm/expected/pg_trgm.out
@@ -54,7 +54,7 @@ select similarity('wow',' WOW ');
 (1 row)
 
 CREATE TABLE test_trgm(t text);
-\copy test_trgm from 'data/trgm.data
+\copy test_trgm from 'data/trgm.data'
 select t,similarity(t,'qwertyu0988') as sml from test_trgm where t % 'qwertyu0988' order by sml desc, t;
       t      |   sml    
 -------------+----------
@@ -3515,6 +3515,47 @@ select * from test2 where t ilike 'qua%';
  quark
 (1 row)
 
+select * from test2 where t ~ '[abc]{3}';
+   t    
+--------
+ abcdef
+(1 row)
+
+select * from test2 where t ~ 'a[bc]+d';
+   t    
+--------
+ abcdef
+(1 row)
+
+select * from test2 where t ~* 'DEF';
+   t    
+--------
+ abcdef
+(1 row)
+
+select * from test2 where t ~ 'dEf';
+ t 
+---
+(0 rows)
+
+select * from test2 where t ~* '^q';
+   t   
+-------
+ quark
+(1 row)
+
+select * from test2 where t ~* '[abc]{3}[def]{3}';
+   t    
+--------
+ abcdef
+(1 row)
+
+select * from test2 where t ~ 'q.*rk$';
+   t   
+-------
+ quark
+(1 row)
+
 drop index test2_idx_gin;
 create index test2_idx_gist on test2 using gist (t gist_trgm_ops);
 set enable_seqscan=off;
diff --git a/contrib/pg_trgm/pg_trgm--1.0.sql b/contrib/pg_trgm/pg_trgm--1.0.sql
index 8067bd6..ca9bcaa 100644
--- a/contrib/pg_trgm/pg_trgm--1.0.sql
+++ b/contrib/pg_trgm/pg_trgm--1.0.sql
@@ -163,4 +163,6 @@ AS
 
 ALTER OPERATOR FAMILY gin_trgm_ops USING gin ADD
         OPERATOR        3       pg_catalog.~~ (text, text),
-        OPERATOR        4       pg_catalog.~~* (text, text);
+        OPERATOR        4       pg_catalog.~~* (text, text),
+        OPERATOR        5       pg_catalog.~ (text, text),
+        OPERATOR        6       pg_catalog.~* (text, text);
diff --git a/contrib/pg_trgm/sql/pg_trgm.sql b/contrib/pg_trgm/sql/pg_trgm.sql
index 81ab1e7..7d8a151 100644
--- a/contrib/pg_trgm/sql/pg_trgm.sql
+++ b/contrib/pg_trgm/sql/pg_trgm.sql
@@ -13,7 +13,7 @@ select similarity('wow',' WOW ');
 
 CREATE TABLE test_trgm(t text);
 
-\copy test_trgm from 'data/trgm.data
+\copy test_trgm from 'data/trgm.data'
 
 select t,similarity(t,'qwertyu0988') as sml from test_trgm where t % 'qwertyu0988' order by sml desc, t;
 select t,similarity(t,'gwertyu0988') as sml from test_trgm where t % 'gwertyu0988' order by sml desc, t;
@@ -52,6 +52,14 @@ select * from test2 where t like '%bcd%';
 select * from test2 where t like E'%\\bcd%';
 select * from test2 where t ilike '%BCD%';
 select * from test2 where t ilike 'qua%';
+
+select * from test2 where t ~ '[abc]{3}';
+select * from test2 where t ~ 'a[bc]+d';
+select * from test2 where t ~* 'DEF';
+select * from test2 where t ~ 'dEf';
+select * from test2 where t ~* '^q';
+select * from test2 where t ~* '[abc]{3}[def]{3}';
+select * from test2 where t ~ 'q.*rk$';
 drop index test2_idx_gin;
 create index test2_idx_gist on test2 using gist (t gist_trgm_ops);
 set enable_seqscan=off;
diff --git a/contrib/pg_trgm/trgm.h b/contrib/pg_trgm/trgm.h
index 067f29d..b3ce65b 100644
--- a/contrib/pg_trgm/trgm.h
+++ b/contrib/pg_trgm/trgm.h
@@ -7,7 +7,6 @@
 #include "access/gist.h"
 #include "access/itup.h"
 #include "storage/bufpage.h"
-#include "utils/builtins.h"
 
 /* options */
 #define LPADDING		2
@@ -28,6 +27,8 @@
 #define DistanceStrategyNumber		2
 #define LikeStrategyNumber			3
 #define ILikeStrategyNumber			4
+#define RegExpStrategyNumber		5
+#define RegExpStrategyNumberICase	6
 
 
 typedef char trgm[3];
@@ -46,8 +47,10 @@ uint32		trgm2int(trgm *ptr);
 
 #ifdef KEEPONLYALNUM
 #define ISPRINTABLECHAR(a)	( isascii( *(unsigned char*)(a) ) && (isalnum( *(unsigned char*)(a) ) || *(unsigned char*)(a)==' ') )
+#define ISWORDCHR(c)	(t_isalpha(c) || t_isdigit(c))
 #else
 #define ISPRINTABLECHAR(a)	( isascii( *(unsigned char*)(a) ) && isprint( *(unsigned char*)(a) ) )
+#define ISWORDCHR(c)	(!t_isspace(c))
 #endif
 #define ISPRINTABLETRGM(t)	( ISPRINTABLECHAR( ((char*)(t)) ) && ISPRINTABLECHAR( ((char*)(t))+1 ) && ISPRINTABLECHAR( ((char*)(t))+2 ) )
 
@@ -99,11 +102,16 @@ typedef char *BITVECP;
 #define GETARR(x)		( (trgm*)( (char*)x+TRGMHDRSIZE ) )
 #define ARRNELEM(x) ( ( VARSIZE(x) - TRGMHDRSIZE )/sizeof(trgm) )
 
+typedef struct PackedGraph PackedGraph;
+
 extern float4 trgm_limit;
 
 TRGM	   *generate_trgm(char *str, int slen);
 TRGM	   *generate_wildcard_trgm(const char *str, int slen);
 float4		cnt_sml(TRGM *trg1, TRGM *trg2);
 bool		trgm_contained_by(TRGM *trg1, TRGM *trg2);
+void		cnt_trigram(trgm *trgmptr, char *str, int bytelen);
+TRGM	   *createTrgmCNFA(text *text_re, MemoryContext context, PackedGraph **paths);
+bool		trigramsMatchGraph(PackedGraph *graph, bool *check);
 
 #endif   /* __TRGM_H__ */
diff --git a/contrib/pg_trgm/trgm_gin.c b/contrib/pg_trgm/trgm_gin.c
index 114fb78..b519901 100644
--- a/contrib/pg_trgm/trgm_gin.c
+++ b/contrib/pg_trgm/trgm_gin.c
@@ -80,7 +80,7 @@ gin_extract_query_trgm(PG_FUNCTION_ARGS)
 	StrategyNumber strategy = PG_GETARG_UINT16(2);
 
 	/* bool   **pmatch = (bool **) PG_GETARG_POINTER(3); */
-	/* Pointer	  *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
+	Pointer	  **extra_data = (Pointer **) PG_GETARG_POINTER(4);
 	/* bool   **nullFlags = (bool **) PG_GETARG_POINTER(5); */
 	int32	   *searchMode = (int32 *) PG_GETARG_POINTER(6);
 	Datum	   *entries = NULL;
@@ -88,6 +88,7 @@ gin_extract_query_trgm(PG_FUNCTION_ARGS)
 	int32		trglen;
 	trgm	   *ptr;
 	int32		i;
+	PackedGraph	*graph;
 
 	switch (strategy)
 	{
@@ -107,6 +108,32 @@ gin_extract_query_trgm(PG_FUNCTION_ARGS)
 			 */
 			trg = generate_wildcard_trgm(VARDATA(val), VARSIZE(val) - VARHDRSZ);
 			break;
+		case RegExpStrategyNumberICase:
+#ifndef IGNORECASE
+			elog(ERROR, "cannot handle ~* with case-sensitive trigrams");
+#endif
+			/* FALL THRU */
+		case RegExpStrategyNumber:
+			trg = createTrgmCNFA(val, fcinfo->flinfo->fn_mcxt, &graph);
+			if (trg && ARRNELEM(trg) > 0)
+			{
+				/*
+				 * Successful regex processing: store CNFA-like graph as an
+				 * extra_data.
+				 */
+				*extra_data = (Pointer *) palloc0(sizeof(Pointer) *
+																ARRNELEM(trg));
+				for (i = 0; i < ARRNELEM(trg); i++)
+					(*extra_data)[i] = (Pointer) graph;
+			}
+			else
+			{
+				/* No result: have to do full index scan. */
+				*nentries = 0;
+				*searchMode = GIN_SEARCH_MODE_ALL;
+				PG_RETURN_POINTER(entries);
+			}
+			break;
 		default:
 			elog(ERROR, "unrecognized strategy number: %d", strategy);
 			trg = NULL;			/* keep compiler quiet */
@@ -147,7 +174,7 @@ gin_trgm_consistent(PG_FUNCTION_ARGS)
 	/* text    *query = PG_GETARG_TEXT_P(2); */
 	int32		nkeys = PG_GETARG_INT32(3);
 
-	/* Pointer	  *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
+	Pointer	   *extra_data = (Pointer *) PG_GETARG_POINTER(4);
 	bool	   *recheck = (bool *) PG_GETARG_POINTER(5);
 	bool		res;
 	int32		i,
@@ -189,6 +216,17 @@ gin_trgm_consistent(PG_FUNCTION_ARGS)
 				}
 			}
 			break;
+		case RegExpStrategyNumber:
+		case RegExpStrategyNumberICase:
+			if (nkeys < 1)
+			{
+				/* Regex processing gave no result: do full index scan */
+				res = true;
+				break;
+			}
+			res = trigramsMatchGraph((PackedGraph *) extra_data[0], check);
+
+			break;
 		default:
 			elog(ERROR, "unrecognized strategy number: %d", strategy);
 			res = false;		/* keep compiler quiet */
diff --git a/contrib/pg_trgm/trgm_op.c b/contrib/pg_trgm/trgm_op.c
index 87dffd1..71aa938 100644
--- a/contrib/pg_trgm/trgm_op.c
+++ b/contrib/pg_trgm/trgm_op.c
@@ -77,12 +77,6 @@ unique_array(trgm *a, int len)
 	return curend + 1 - a;
 }
 
-#ifdef KEEPONLYALNUM
-#define iswordchr(c)	(t_isalpha(c) || t_isdigit(c))
-#else
-#define iswordchr(c)	(!t_isspace(c))
-#endif
-
 /*
  * Finds first word in string, returns pointer to the word,
  * endword points to the character after word
@@ -92,7 +86,7 @@ find_word(char *str, int lenstr, char **endword, int *charlen)
 {
 	char	   *beginword = str;
 
-	while (beginword - str < lenstr && !iswordchr(beginword))
+	while (beginword - str < lenstr && !ISWORDCHR(beginword))
 		beginword += pg_mblen(beginword);
 
 	if (beginword - str >= lenstr)
@@ -100,7 +94,7 @@ find_word(char *str, int lenstr, char **endword, int *charlen)
 
 	*endword = beginword;
 	*charlen = 0;
-	while (*endword - str < lenstr && iswordchr(*endword))
+	while (*endword - str < lenstr && ISWORDCHR(*endword))
 	{
 		*endword += pg_mblen(*endword);
 		(*charlen)++;
@@ -109,8 +103,7 @@ find_word(char *str, int lenstr, char **endword, int *charlen)
 	return beginword;
 }
 
-#ifdef USE_WIDE_UPPER_LOWER
-static void
+void
 cnt_trigram(trgm *tptr, char *str, int bytelen)
 {
 	if (bytelen == 3)
@@ -131,7 +124,6 @@ cnt_trigram(trgm *tptr, char *str, int bytelen)
 		CPTRGM(tptr, &crc);
 	}
 }
-#endif
 
 /*
  * Adds trigrams from words (already padded).
@@ -287,7 +279,7 @@ get_wildcard_part(const char *str, int lenstr,
 	{
 		if (in_escape)
 		{
-			if (iswordchr(beginword))
+			if (ISWORDCHR(beginword))
 				break;
 			in_escape = false;
 			in_leading_wildcard_meta = false;
@@ -298,7 +290,7 @@ get_wildcard_part(const char *str, int lenstr,
 				in_escape = true;
 			else if (ISWILDCARDCHAR(beginword))
 				in_leading_wildcard_meta = true;
-			else if (iswordchr(beginword))
+			else if (ISWORDCHR(beginword))
 				break;
 			else
 				in_leading_wildcard_meta = false;
@@ -341,7 +333,7 @@ get_wildcard_part(const char *str, int lenstr,
 		clen = pg_mblen(endword);
 		if (in_escape)
 		{
-			if (iswordchr(endword))
+			if (ISWORDCHR(endword))
 			{
 				memcpy(s, endword, clen);
 				(*charlen)++;
@@ -369,7 +361,7 @@ get_wildcard_part(const char *str, int lenstr,
 				in_trailing_wildcard_meta = true;
 				break;
 			}
-			else if (iswordchr(endword))
+			else if (ISWORDCHR(endword))
 			{
 				memcpy(s, endword, clen);
 				(*charlen)++;
diff --git a/contrib/pg_trgm/trgm_regexp.c b/contrib/pg_trgm/trgm_regexp.c
new file mode 100644
index 0000000..cfcabbb
--- /dev/null
+++ b/contrib/pg_trgm/trgm_regexp.c
@@ -0,0 +1,1797 @@
+/*
+ * contrib/pg_trgm/trgm_regexp.c - regular expression matching using trigrams
+ *
+ * The general idea of index support for a regular expression (regex) search
+ * is to transform the regex to a logical expression on trigrams. For example:
+ *
+ *   (ab|cd)efg => ((abe & bef) | (cde & def)) & efg
+ *
+ * If a string matches the regex, then it must match the logical expression of
+ * trigrams. The opposite is not necessary true, however: a string that matches
+ * the logical expression might not match the original regex. Such false
+ * positives are removed during recheck.
+ *
+ * The algorithm to convert a regex to a logical expression is based on
+ * analysis of an automaton that corresponds to regex. The algorithm consists
+ * of four stages:
+ *
+ * 1) Compile the regexp to CNFA form. This is handled by the PostgreSQL
+ *    regexp library, but we have peek into the data structures it produces.
+ *
+ * 2) Transform the original CNFA into an automaton-like graph, where arcs
+ *    are labeled with trigrams that must be present in order to move from
+ *    state to another via the arc. The trigrams used in this stage consist
+ *    of colors, not characters, like the original CNFA.
+ *
+ * 3) Expand the color trigrams into regular trigrams consisting of
+ *    characters. If too many distinct trigrams are produced, trigrams are
+ *    eliminated and the graph is simplified until it's simple enough.
+ *
+ * 4) Finally, the resulting graph is packed into a PackedGraph struct, and
+ *    returned to the caller.
+ *
+ *
+ * 1) Compile the regexp to CNFA form
+ * ----------------------------------
+ * The automaton returned by the regexp compiler is a graph where vertices
+ * are "states" and arcs are labeled with colors. Each color represents
+ * a group of characters, so that all characters assigned to the same color
+ * are interchangeable, as far as matching the regexp is concerned. There are
+ * two special states: "initial" and "final". There can be multiple outgoing
+ * arcs from a state labeled with the same color, which makes the automaton
+ * non-deterministic, because it can be in many states simultaneously.
+ *
+ * 2) Transform the original CNFA into an automaton-like graph
+ * -----------------------------------------------------------
+ * In the 2nd stage, the automaton is transformed into a graph that resembles
+ * the original CNFA. Each state in the transformed graph represents a state
+ * from the original CNFA, with an "enter key". The enter key consists of the
+ * last two characters (colors, to be precise) read before entering the state.
+ * There can be one or more states in the transformed graph for each state in
+ * the original CNFA, depending on what characters can precede it. Each arc
+ * is labelled with a trigram that must be present in the string to match.
+ *
+ * So the transformed graph resembles the original CNFA, but the arcs are
+ * labeled with trigrams instead of individual characters, and there are
+ * more states. It is a lossy representation of the original CNFA: any string
+ * that matches the original regexp must match the transformed graph, but the
+ * reverse is not true.
+ *
+ * When building the graph, if the number of states or arcs exceed pre-defined
+ * limits, we give up and simply mark any states not yet processed as final
+ * states. Roughly speaking, that means that we make use of some portion from
+ * the beginning of the regexp.
+ *
+ * 3) Expand the color trigrams into regular trigrams
+ * --------------------------------------------------
+ * The trigrams in the transformed graph are "color trigrams", consisting
+ * of three consecutive colors that must be present in the string. But for
+ * search, we need regular trigrams consisting of characters. In the 3rd
+ * stage, the color trigrams are expanded into regular trigrams. Since each
+ * color can represent many characters, the total number of regular trigrams
+ * after expansion could be very large. Because searching an index with
+ * thousands of trigrams would be slow, and would likely produce so many
+ * "false positives" that you would have to traverse a large fraction of the
+ * index, the graph is simplified further in a lossy fashion by removing
+ * color trigrams until the number of trigrams after expansion is below
+ * MAX_TRGM_COUNT threshold. When a color trigram is removed, the states
+ * connected by any arcs labelled with that trigram are merged.
+ *
+ * 4) Pack the graph into a compact representation
+ * -----------------------------------------------
+ * The 2nd and 3rd stages might have eliminated or merged many of the states
+ * and trigrams created earlier, so in this final stage, the graph is
+ * compacted and packed into a simpler struct that contains only the
+ * information needed to evaluate it.
+ *
+ *
+ * OLD COMMENTS:
+ * States of the graph produced in the first stage are marked with "keys". Key
+ * is a pair of a "prefix" and a state of the original automaton. "Prefix" is
+ * pair of colors of last two read characters. So, knowing the prefix is enough
+ * to know what is a color trigram when we read new character with some
+ * particular color. However, we can know single color of prefix or don't know
+ * any color of it. Each state of resulting graph have an "enter key" (with that
+ * key we've entered this state) and a set of keys which are reachable without
+ * reading any predictable color trigram. The algorithm of processing each state
+ * of resulting graph are so:
+ * 1) Add all keys which achievable without reading of any predictable color
+ *    trigram.
+ * 2) Add outgoing arcs labeled with trigrams.
+ * Step 2 leads to creation of new states. We use breadth-first algorithm for
+ * processing them.
+ *
+ * Consider this on example of regex ab[cd]. This regex are transformed into
+ * following CNFA (for simplicity of example we don't use colors):
+ *
+ *                    4#
+ *                  c/
+ *       a     b    /
+ *   1* --- 2 ---- 3
+ *                  \
+ *                  d\
+ *                    5#
+ *
+ * We use * to mark initial state and # to mark final state. It's not depicted,
+ * but states 1, 4, 5 have self-referencing arcs for all possible characters,
+ * because pattern can match to any part of string.
+ *
+ * As the result of first stage we will have following graph:
+ *
+ *     abc      abd
+ * 2# <---- 1* ----> 3#
+ *
+ * Let us consider the sequence of algorithm work for this graph producing.
+ * We will designate state key as (prefix.s, prefix.ambiguity, nstate).
+ * 1) Create state 1 with enter key ("  ", true, 1).
+ * 2) Add key (" a", true, 2) to state 1.
+ * 3) Add key ("ab", false, 3) to state 1.
+ * 4) Add arc from output state 1 to new state 2 with enter key
+ *    ("bc", false, 4).
+ * 5) Mark state 2 final because state 4 of source CNFA is marked as final.
+ * 6) Add arc from output state 1 to new state 3 with enter key
+ *    ("bd", false, 5).
+ * 7) Mark state 3 final because state 4 of source CNFA is marked as final.
+ *
+ * At the second stage we select color trigrams to expand into simple trigrams.
+ * We're removing color trigrams starting from the most wide. When removing
+ * color trigram we have to merge states connected by corresponding arcs.
+ * It's necessary to not merge initial and final states, because our graph
+ * becomes useless in this case.
+ */
+#include "postgres.h"
+
+#include "trgm.h"
+
+#include "catalog/pg_collation.h"
+#include "fmgr.h"
+#include "miscadmin.h"
+#include "mb/pg_wchar.h"
+#include "nodes/pg_list.h"
+#include "regex/regex.h"
+#undef INFINITY /* avoid conflict of INFINITY definition */
+#include "regex/regguts.h"
+#include "tsearch/ts_locale.h"
+#include "utils/hsearch.h"
+
+/*
+ * Uncomment to print intermediate stages, for exploring and debugging the
+ * algorithm implementation. This produces three graphs in Graphviz .dot
+ * format, in /tmp.
+ */
+#define TRGM_REGEXP_DEBUG
+
+/*---
+ * Following group of parameters are used in order to limit our computations.
+ * Otherwise regex processing could be too slow and memory-consuming.
+ *
+ *  MAX_RESULT_STATES - How many states we allow in result CNFA-like graph
+ *  MAX_RESULT_ARCS - How many arcs we allow in result CNFA-like graph
+ *  MAX_TRGM_COUNT - How many simple trigrams we allow to extract
+ */
+#define MAX_RESULT_STATES	128
+#define MAX_RESULT_ARCS		1024
+#define MAX_TRGM_COUNT		256
+
+/* Virtual color for representation in prefixes and color trigrams. */
+#define EMPTY_COLOR			((color) -1)
+#define UNKNOWN_COLOR		((color) -2)
+
+/*
+ * Widechar trigram datatype for holding trigram before possible conversion into
+ * CRC32
+ */
+typedef color ColorTrgm[3];
+
+/*
+ * Maximum length of multibyte encoding character is 4. So, we can hold it in
+ * 32 bit integer for handling simplicity.
+ */
+typedef uint32 mb_char;
+
+/*----
+ * Attributes of CNFA colors:
+ *
+ *  expandable               - flag indicates we potentially can expand this
+ *                             color into distinct characters.
+ *  containNonAlpha          - flag indicates if color might contain
+ *                             non-alphanumeric characters (which aren't
+ *                             extracted into trigrams)
+ *  alphaCharsCount          - count of characters in color
+ *  alphaCharsCountAllocated - allocated size of alphaChars array
+ *  alphaChars               - array of alphanumeric characters of this color
+ *                             (which are extracted into trigrams)
+ *
+ * When expandable is false, all other attributes doesn't matter we just think
+ * this color as always unknown character.
+ */
+typedef struct
+{
+	bool		expandable;
+	bool		containNonAlpha;
+	int			alphaCharsCount;
+	int			alphaCharsCountAllocated;
+	mb_char	   *alphaChars;
+} ColorInfo;
+
+/*
+ * Prefix is information about colors of last two read characters when coming
+ * into specific CNFA state. These colors could have special values
+ * UNKNOWN_COLOR and EMPTY_COLOR. UNKNOWN_COLOR means that we read some
+ * character of unexpandable color. EMPTY_COLOR means that we read
+ * non-alphanumeric character.
+ */
+typedef struct
+{
+	color	s[2];
+} TrgmPrefix;
+
+/*
+ * "Key" of resulting state: pair of prefix and source CNFA state.
+ */
+typedef struct
+{
+	TrgmPrefix	prefix;
+	int			nstate;
+} TrgmStateKey;
+
+/*---
+ * State of resulting graph.
+ *
+ *  enterKey - a key with which we can enter this state
+ *  keys     - all keys achievable without reading any predictable trigram
+ *  arcs     - outgoing arcs of this state
+ *  parent   - parent state if this state has been merged
+ *  children - children states if this state has been merged
+ *  fin      - flag indicated this state is final
+ *  init     - flag indicated this state is initial
+ *  queued   - flag indicated this state is queued in CNFA-like graph
+ *             construction
+ *  number   - number of this state (use at the package stage)
+ */
+typedef struct TrgmState
+{
+	TrgmStateKey enterKey;
+	List	   *arcs;
+	bool		fin;
+	bool		init;
+
+	/* (stage 2) */
+	List	   *keys;
+	bool		queued;
+
+	struct TrgmState *parent;
+	List	   *children;
+	int			number;
+} TrgmState;
+
+/*
+ * Arc in the transformed graph. Arc is labeled with trigram.
+ */
+typedef struct
+{
+	TrgmState  *target;
+	ColorTrgm	trgm;
+} TrgmArc;
+
+/*
+ * Information about arc of specific color trigram: contain pointers to the
+ * source and target states. (stage 3)
+ */
+typedef struct
+{
+	TrgmState  *source;
+	TrgmState  *target;
+} ArcInfo;
+
+/*---
+ * Information about color trigram: (stage 3)
+ *
+ * trgm     - trigram itself
+ * number   - number of this trigram (used in the package stage)
+ * count    - number of simple trigrams fitting into this color trigram
+ * expanded - flag indicates this color trigram is expanded into simple trigrams
+ * arcs     - list of all arcs labeled with this color trigram.
+ */
+typedef struct
+{
+	ColorTrgm	trgm;
+	int			number;
+	int			count;
+	bool		expanded;
+	List	   *arcs;
+} ColorTrgmInfo;
+
+/*---
+ * Data structure representing all the data we need during regex processing.
+ * Initially we set "cnfa" to cnfa of regex, write color information info
+ * "colorInfo" and set "overflowed" flag to false. And the stage of trigram
+ * CFNA-like graph creation "states", "initState" and "arcsCount" are filled.
+ * "owerflowed" flag could be set in case of overflow. Then we collect array
+ * of all present color trigrams to "colorTrgms" and "colorTrgmsCount" and
+ * expand them into  "trg" and "totalTrgmCount".
+ *
+ *  cnfa            - source CFNA of regex
+ *  colorInfo       - processed information of regex colors
+ *  ncolors			- number of colors in colorInfo
+ *  states          - hash of states of resulting graph
+ *  initState       - pointer to initial state of resulting graph
+ *  arcsCount       - total number of arcs of resulting graph (for resource
+ *                    limiting)
+ *  colorTrgms      - array of all color trigrams presented in graph
+ *  colorTrgmsCount - count of that color trigrams
+ *  totalTrgmCount  - total count of extracted simple trigrams
+ *  queue           - queue for CFNA-like graph construction
+ *  overflowed      - if set, we have exceeded resource limit for transformation
+ */
+typedef struct
+{
+	/*
+	 * Source CNFA of the regexp, and color information extracted from it
+	 * (stage 1)
+	 */
+	struct cnfa *cnfa;
+	ColorInfo  *colorInfo;
+	int			ncolors;
+
+	/* Transformed graph (stage 2) */
+	HTAB	   *states;
+	TrgmState  *initState;
+	int			arcsCount;
+	List	   *queue;
+	bool		overflowed;
+
+	/* Information about distinct color trigrams in the graph (stage 3) */
+	ColorTrgmInfo *colorTrgms;
+
+	int			colorTrgmsCount;
+	int			totalTrgmCount;
+} TrgmCNFA;
+
+
+/*
+ * Final, compact representation of CNFA-like graph.
+ */
+typedef struct
+{
+	int			 targetState;
+	int			 colorTrgm;
+} PackedArc;
+
+typedef struct
+{
+	int			 arcsCount;
+	PackedArc	*arcs;
+} PackedState;
+
+struct PackedGraph
+{
+	/*
+	 * colorTrigramsCount and colorTrigramsGroups contain information
+	 * about how trigrams are grouped into color trigrams. "colorTrigramsCount"
+	 * represents total count of color trigrams and "colorTrigramGroups" contain
+	 * number of simple trigrams in each color trigram.
+	 */
+	int			 colorTrigramsCount;
+	int			*colorTrigramGroups;
+
+	/*
+	 * "states" points to definition of "statesCount" states. 0 state is
+	 * always initial state and 1 state is always final state. Each state's
+	 * "arcs" points to "arcsCount" description of arcs. Each arc describe by
+	 * number of color trigram and number of target state (both are zero-based).
+	 */
+	int			 statesCount;
+	PackedState *states;
+
+	/* Temporary work space for trigramsMatchGraph() */
+	bool		*colorTrigramsActive;
+	bool		*statesActive;
+};
+
+
+/* prototypes for private functions */
+static bool activateState(PackedGraph *graph, int stateno);
+static ColorInfo *getColorInfo(regex_t *regex, int *ncolors);
+static TrgmState *getState(TrgmCNFA *trgmCNFA, TrgmStateKey *key);
+static void transformGraph(TrgmCNFA *trgmCNFA);
+static bool selectColorTrigrams(TrgmCNFA *trgmCNFA);
+static TRGM *expandColorTrigrams(TrgmCNFA *trgmCNFA);
+static PackedGraph *packGraph(TrgmCNFA *trgmCNFA, MemoryContext context);
+
+#ifdef TRGM_REGEXP_DEBUG
+static void printSourceCNFA(struct cnfa *cnfa, ColorInfo *colors, int ncolors);
+static void printTrgmCNFA(TrgmCNFA *trgmCNFA);
+static void printPackedGraph(PackedGraph *packedGraph, TRGM *trigrams);
+#endif
+
+
+/*
+ * Main entry point to process a regular expression. Returns a packed graph
+ * representation of the regular expression, or NULL if the regular expression
+ * was too complex.
+ */
+TRGM *
+createTrgmCNFA(text *text_re, MemoryContext context, PackedGraph **graph)
+{
+	struct guts   *g;
+	TrgmCNFA	   trgmCNFA;
+	regex_t		  *regex;
+	TRGM		  *trg;
+
+	/*
+	 * Stage 1: Compile the regexp into a CNFA, using the PostgreSQL regexp
+	 * library.
+	 */
+#ifdef IGNORECASE
+	regex = RE_compile_and_cache(text_re, REG_ADVANCED | REG_ICASE, DEFAULT_COLLATION_OID);
+#else
+	regex = RE_compile_and_cache(text_re, REG_ADVANCED, DEFAULT_COLLATION_OID);
+#endif
+	g = (struct guts *) regex->re_guts;
+	trgmCNFA.cnfa = &g->search;
+
+	/* Collect color information from the CNFA */
+	trgmCNFA.colorInfo = getColorInfo(regex, &trgmCNFA.ncolors);
+
+#ifdef TRGM_REGEXP_DEBUG
+	printSourceCNFA(&g->search, trgmCNFA.colorInfo, trgmCNFA.ncolors);
+#endif
+
+	/*
+	 * Stage 2: Create a transformed graph from the source CNFA.
+	 */
+	transformGraph(&trgmCNFA);
+
+#ifdef TRGM_REGEXP_DEBUG
+	printTrgmCNFA(&trgmCNFA);
+#endif
+
+	if (trgmCNFA.initState->fin)
+		return NULL;
+
+	/*
+	 * Stage 3: Select color trigrams to expand.
+	 */
+	if (!selectColorTrigrams(&trgmCNFA))
+		return NULL;
+
+	/*
+	 * Stage 4: Expand color trigrams and pack graph into final representation.
+	 */
+	trg = expandColorTrigrams(&trgmCNFA);
+
+	*graph = packGraph(&trgmCNFA, context);
+
+#ifdef TRGM_REGEXP_DEBUG
+	printPackedGraph(*graph, trg);
+#endif
+
+	return trg;
+}
+
+/*
+ * Main entry point for evaluating a graph.
+ */
+bool
+trigramsMatchGraph(PackedGraph *graph, bool *check)
+{
+	int			i,
+				j,
+				k;
+
+	/*
+	 * Reset temporary working areas.
+	 */
+	memset(graph->colorTrigramsActive, 0,
+		   sizeof(bool) * graph->colorTrigramsCount);
+	memset(graph->statesActive, 0, sizeof(bool) * graph->statesCount);
+
+	/* Check which color trigrams were matched. */
+	j = 0;
+	for (i = 0; i < graph->colorTrigramsCount; i++)
+	{
+		int cnt = graph->colorTrigramGroups[i];
+		for (k = j; k < j + cnt; k++)
+		{
+			if (check[k])
+			{
+				/*
+				 * Found one matched trigram in the group. Can skip the rest
+				 * of them and go to the next group.
+				 */
+				graph->colorTrigramsActive[i] = true;
+				break;
+			}
+		}
+		j = j + cnt;
+	}
+
+	/* Recursively evaluate graph, starting from initial state */
+	return activateState(graph, 0);
+}
+
+/*
+ * Recursive function for graph state activation. Returns true if state
+ * activation leads to activation of final state.
+ */
+static bool
+activateState(PackedGraph *graph, int stateno)
+{
+	PackedState *state = &graph->states[stateno];
+	int			cnt = state->arcsCount;
+	int			i;
+
+	graph->statesActive[stateno] = true;
+
+	/* Loop over arcs */
+	for (i = 0; i < cnt; i++)
+	{
+		PackedArc *arc = (PackedArc *) &state->arcs[i];
+		/*
+		 * If corresponding color trigram is present then activate the
+		 * corresponding state.
+		 */
+		if (graph->colorTrigramsActive[arc->colorTrgm])
+		{
+			if (arc->targetState == 1)
+				return true; /* reached final state */
+			if (!graph->statesActive[arc->targetState])
+			{
+				if (activateState(graph, arc->targetState))
+					return true;
+			}
+		}
+	}
+	return false;
+}
+
+/*---------------------
+ * Subroutines for pre-processing the color map.
+ *---------------------
+ */
+
+/*
+ * Convert pg_wchar to multibyte character.
+ */
+static mb_char
+convertPgWchar(pg_wchar c)
+{
+	/*
+	 * "s" has enough of space for a multibyte character of 4 bytes, and
+	 * a zero-byte at the end.
+	 */
+	char		s[5];
+	char	   *lowerCased;
+	mb_char		result;
+
+	if (c == 0)
+		return 0;
+
+	MemSet(s, 0, sizeof(s));
+	pg_wchar2mb_with_len(&c, s, 1);
+
+	/* Convert to lowercase if needed */
+#ifdef IGNORECASE
+	lowerCased = lowerstr(s);
+	if (strncmp(lowerCased, s, 4))
+		return 0;
+#else
+	lowerCased = s;
+#endif
+	strncpy((char *) &result, lowerCased, 4);
+	return result;
+}
+
+/*
+ * Add new character into color information
+ */
+static void
+addCharToColor(ColorInfo *colorInfo, pg_wchar c)
+{
+	if (!colorInfo->alphaChars)
+	{
+		colorInfo->alphaCharsCountAllocated = 16;
+		colorInfo->alphaChars = (pg_wchar *) palloc(sizeof(pg_wchar) *
+										colorInfo->alphaCharsCountAllocated);
+	}
+	if (colorInfo->alphaCharsCount >= colorInfo->alphaCharsCountAllocated)
+	{
+		colorInfo->alphaCharsCountAllocated *= 2;
+		colorInfo->alphaChars = (pg_wchar *) repalloc(colorInfo->alphaChars,
+						sizeof(pg_wchar) * colorInfo->alphaCharsCountAllocated);
+	}
+	colorInfo->alphaChars[colorInfo->alphaCharsCount++] = c;
+}
+
+/*
+ * Recursive function which scans colormap and updates color attributes in
+ * ColorInfo structure. Colormap is a tree which maps character to colors.
+ * The tree contains 4 levels. Each level corresponding to byte of character.
+ * Non-leaf nodes of tree contain pointers to descending tree nodes for each
+ * byte value. Leaf nodes of tree contain color numbers for each byte value.
+ * Potentially colormap could be very large, but most part of the colormap
+ * points to zero colors. That's tree nodes which corresponds to only zero
+ * color can be reused.
+ */
+static void
+scanColorMap(union tree	tree[NBYTS], union tree *t, ColorInfo *colorInfos,
+			 int level, pg_wchar p)
+{
+	int			i;
+
+	check_stack_depth();
+
+	if (level < NBYTS - 1)
+	{
+		/* non-leaf node */
+		for (i = 0; i < BYTTAB; i++)
+		{
+			/*
+			 * This condition checks if all underlying levels express zero
+			 * color. Zero color uses multiple links to same tree node. So,
+			 * avoid scanning it because it's expensive.
+			 */
+			if (t->tptr[i] == &tree[level + 1])
+				continue;
+			/* Recursive scanning of next level color table */
+			scanColorMap(tree, t->tptr[i], colorInfos, level + 1, (p << 8) | i);
+		}
+	}
+	else
+	{
+		/* leaf node */
+		p <<= 8;
+		for (i = 0; i < BYTTAB; i++)
+		{
+			ColorInfo *colorInfo = &colorInfos[t->tcolor[i]];
+			pg_wchar c;
+
+			if (!colorInfo->expandable)
+				continue;
+
+			/* Convert to multibyte character */
+			c = convertPgWchar(p | i);
+
+			if (!c)
+				continue;
+
+			/* Update color attributes according to next character */
+			if (ISWORDCHR((char *)&c))
+				addCharToColor(colorInfo, c);
+			else
+				colorInfo->containNonAlpha = true;
+		}
+	}
+}
+
+/*
+ * Fill ColorInfo structure for each color by scanning colormap.
+ */
+static ColorInfo *
+getColorInfo(regex_t *regex, int *ncolors)
+{
+	struct guts *g;
+	struct colormap *cm;
+	ColorInfo  *result;
+	int			colorsCount;
+	int			i;
+
+	g = (struct guts *) regex->re_guts;
+	cm = &g->cmap;
+	*ncolors = colorsCount = cm->max + 1;
+
+	result = (ColorInfo *) palloc0(colorsCount * sizeof(ColorInfo));
+
+	/*
+	 * Zero color is a default color which contains all characters that aren't
+	 * in explicitly expressed classes. Mark that we can expect everything
+	 * from it.
+	 */
+	result[0].expandable = false;
+	for (i = 1; i < colorsCount; i++)
+		result[i].expandable = true;
+
+	scanColorMap(cm->tree, &cm->tree[0], result, 0, 0);
+
+	return result;
+}
+
+/*---------------------
+ * Subroutines for transforming original CNFA graph into a color trigram
+ * graph.
+ *---------------------
+ */
+
+/*
+ * Check if prefix1 "contains" prefix2. "contains" mean that any exact prefix
+ * (which no ambiguity) which satisfy to prefix2 also satisfy to prefix1.
+ */
+static bool
+prefixContains(TrgmPrefix *prefix1, TrgmPrefix *prefix2)
+{
+	if (prefix1->s[1] == UNKNOWN_COLOR)
+	{
+		/* Fully ambiguous prefix contains everything */
+		return true;
+	}
+	else if (prefix1->s[0] == UNKNOWN_COLOR)
+	{
+		/*
+		 * Prefix with only first unknown color contains every prefix with same
+		 * second color.
+		 */
+		if (prefix1->s[1] == prefix2->s[1])
+			return true;
+		else
+			return false;
+	}
+	else
+	{
+		/* Exact prefix contains only exactly same prefix */
+		if (prefix1->s[0] == prefix2->s[0] && prefix1->s[1] == prefix2->s[1])
+			return true;
+		else
+			return false;
+	}
+}
+
+/*
+ * Add all keys that can be reached without reading any color trigram to
+ * state of CNFA-like graph on color trigrams.
+ */
+static void
+addKeys(TrgmCNFA *trgmCNFA, TrgmState *state, TrgmStateKey *key)
+{
+	struct carc *s;
+	TrgmStateKey destKey;
+	ListCell *cell, *prev, *next;
+	TrgmStateKey *keyCopy;
+
+	MemSet(&destKey, 0, sizeof(TrgmStateKey));
+
+	/* Adjust list of keys with new one */
+	prev = NULL;
+	cell = list_head(state->keys);
+	while (cell)
+	{
+		TrgmStateKey *existingKey = (TrgmStateKey *) lfirst(cell);
+		next = lnext(cell);
+		if (existingKey->nstate == key->nstate)
+		{
+			if (prefixContains(&existingKey->prefix, &key->prefix))
+			{
+				/* This old key already covers the new key. Nothing to do */
+				return;
+			}
+			if (prefixContains(&key->prefix, &existingKey->prefix))
+			{
+				/*
+				 * The new key covers this old key. Remove the old key, it's
+				 * no longer needed once we add this key to the list.
+				 */
+				state->keys = list_delete_cell(state->keys, cell, prev);
+			}
+			else
+				prev = cell;
+		}
+		else
+			prev = cell;
+		cell = next;
+	}
+
+	keyCopy = (TrgmStateKey *) palloc(sizeof(TrgmStateKey));
+	memcpy(keyCopy, key, sizeof(TrgmStateKey));
+	state->keys = lappend(state->keys, keyCopy);
+
+	/* Mark final state */
+	if (key->nstate == trgmCNFA->cnfa->post)
+	{
+		state->fin = true;
+		return;
+	}
+
+	/*
+	 * Loop through all outgoing arcs from the corresponding state in the
+	 * original CNFA.
+	 */
+	s = trgmCNFA->cnfa->states[key->nstate];
+	while (s->co != COLORLESS)
+	{
+		ColorInfo *colorInfo;
+
+		if (s->co == trgmCNFA->cnfa->bos[1])
+		{
+			/* Start of line (^) */
+			destKey.nstate = s->to;
+
+			/* Mark prefix as start of new color trigram */
+			destKey.prefix.s[0] = EMPTY_COLOR;
+			destKey.prefix.s[1] = EMPTY_COLOR;
+
+			/* Add key to this state */
+			addKeys(trgmCNFA, state, &destKey);
+			if (state->fin)
+				return;
+		}
+		else if (s->co == trgmCNFA->cnfa->eos[1])
+		{
+			/* End of string ($) */
+			if (key->prefix.s[0] == UNKNOWN_COLOR ||
+				key->prefix.s[1] == EMPTY_COLOR)
+			{
+				destKey.nstate = s->to;
+
+				/*
+				 * Let's think prefix to become ambiguous (in order to prevent
+				 * latter fiddling around with keys).
+				 */
+				destKey.prefix.s[1] = UNKNOWN_COLOR;
+				destKey.prefix.s[0] = UNKNOWN_COLOR;
+
+				/* Prefix is ambiguous, add key to the same state */
+				addKeys(trgmCNFA, state, &destKey);
+				if (state->fin)
+					return;
+			}
+		}
+		else
+		{
+			/* Regular color */
+			colorInfo = &trgmCNFA->colorInfo[s->co];
+
+			if (colorInfo->expandable)
+			{
+				if (colorInfo->containNonAlpha &&
+					(key->prefix.s[0] == UNKNOWN_COLOR ||
+					 key->prefix.s[1] == EMPTY_COLOR))
+				{
+					/*
+					 * When color contain non-alphanumeric character we should
+					 * add empty key with empty prefix.
+					 */
+					destKey.prefix.s[0] = EMPTY_COLOR;
+					destKey.prefix.s[1] = EMPTY_COLOR;
+					destKey.nstate = s->to;
+					addKeys(trgmCNFA, state, &destKey);
+					if (state->fin)
+						return;
+				}
+
+				if (colorInfo->alphaCharsCount > 0 &&
+					key->prefix.s[0] == UNKNOWN_COLOR)
+				{
+					/* Add corresponding key when prefix was unknown */
+					destKey.prefix.s[0] = key->prefix.s[1];
+					destKey.prefix.s[1] = s->co;
+					destKey.nstate = s->to;
+					addKeys(trgmCNFA, state, &destKey);
+					if (state->fin)
+						return;
+				}
+			}
+			else
+			{
+				/*
+				 * Unexpandable color. Add corresponding key to this state.
+				 */
+				destKey.nstate = s->to;
+				destKey.prefix.s[0] = UNKNOWN_COLOR;
+				destKey.prefix.s[1] = UNKNOWN_COLOR;
+				addKeys(trgmCNFA, state, &destKey);
+				if (state->fin)
+					return;
+			}
+		}
+		s++;
+	}
+}
+
+/*
+ * Add outgoing arc from state if needed.
+ */
+static void
+addArc(TrgmCNFA *trgmCNFA, TrgmState *state, TrgmStateKey *key,
+	   TrgmStateKey *destKey, color co)
+{
+	TrgmArc *arc;
+	ListCell *cell2;
+
+	/* Check whether we actually can add the arc */
+	if (key->prefix.s[0] == UNKNOWN_COLOR ||
+		(key->prefix.s[1] == EMPTY_COLOR && co == EMPTY_COLOR))
+		return;
+
+	/* If we have the same key here, we don't need to add new arc */
+	foreach(cell2, state->keys)
+	{
+		TrgmStateKey *key2 = (TrgmStateKey *) lfirst(cell2);
+		if (key2->nstate == destKey->nstate &&
+			prefixContains(&key2->prefix, &destKey->prefix))
+		{
+			return;
+		}
+	}
+
+	/* Not found, add new arc */
+	arc = (TrgmArc *) palloc(sizeof(TrgmArc));
+	arc->target = getState(trgmCNFA, destKey);
+	arc->trgm[0] = key->prefix.s[0];
+	arc->trgm[1] = key->prefix.s[1];
+	arc->trgm[2] = co;
+	state->arcs = lappend(state->arcs, arc);
+	trgmCNFA->arcsCount++;
+}
+
+/*
+ * Add outgoing arcs from given state.
+ */
+static void
+addArcs(TrgmCNFA *trgmCNFA, TrgmState *state)
+{
+	struct carc *s;
+	TrgmStateKey destKey;
+	ListCell *cell;
+
+	MemSet(&destKey, 0, sizeof(TrgmStateKey));
+
+	/*
+	 * Iterate over keys associated with this output state.
+	 */
+	foreach(cell, state->keys)
+	{
+		TrgmStateKey *key = (TrgmStateKey *) lfirst(cell);
+		s = trgmCNFA->cnfa->states[key->nstate];
+		while (s->co != COLORLESS)
+		{
+			ColorInfo *colorInfo;
+			if (s->co == trgmCNFA->cnfa->bos[1])
+			{
+				/* Should be already handled by addKeys. */
+			}
+			else if (s->co == trgmCNFA->cnfa->eos[1])
+			{
+				/* End of the string ($) */
+				destKey.nstate = s->to;
+
+				/* Assume prefix to become ambiguous after end of the string */
+				destKey.prefix.s[1] = UNKNOWN_COLOR;
+				destKey.prefix.s[0] = UNKNOWN_COLOR;
+
+				addArc(trgmCNFA, state, key, &destKey, EMPTY_COLOR);
+			}
+			else
+			{
+				/* Regular color: try to add outgoing arcs */
+				colorInfo = &trgmCNFA->colorInfo[s->co];
+
+				if (colorInfo->expandable)
+				{
+					if (colorInfo->containNonAlpha)
+					{
+						destKey.prefix.s[0] = EMPTY_COLOR;
+						destKey.prefix.s[1] = EMPTY_COLOR;
+						destKey.nstate = s->to;
+						addArc(trgmCNFA, state, key, &destKey, EMPTY_COLOR);
+					}
+
+					if (colorInfo->alphaCharsCount > 0)
+					{
+						destKey.prefix.s[0] = key->prefix.s[1];
+						destKey.prefix.s[1] = s->co;
+						destKey.nstate = s->to;
+						addArc(trgmCNFA, state, key, &destKey, s->co);
+					}
+				}
+			}
+			s++;
+		}
+	}
+}
+
+/*
+ * Get state of trigram CNFA-like graph of given enter key and queue it for
+ * processing if needed.
+ */
+static TrgmState *
+getState(TrgmCNFA *trgmCNFA, TrgmStateKey *key)
+{
+	bool		found;
+	TrgmState  *state;
+
+	state = hash_search(trgmCNFA->states, key, HASH_ENTER, &found);
+	if (!found)
+	{
+		/* New state: initialize and queue it */
+		state->arcs = NIL;
+		state->keys = NIL;
+		state->init = false;
+		state->fin = false;
+		state->children = NIL;
+		state->parent = NULL;
+		state->number = -1;
+
+		state->queued = true;
+		trgmCNFA->queue = lappend(trgmCNFA->queue, state);
+	}
+	return state;
+}
+
+/*
+ * Process the state: add keys and then add outgoing arcs.
+ */
+static void
+processState(TrgmCNFA *trgmCNFA, TrgmState *state)
+{
+	addKeys(trgmCNFA, state, &state->enterKey);
+	/*
+	 * Add outgoing arc only if state isn't final (we have no interest in arc
+	 * if we already match)
+	 */
+	if (!state->fin)
+		addArcs(trgmCNFA, state);
+
+	state->queued = false;
+}
+
+/*
+ * Process queue of CFNA-like graph states until all the states are processed.
+ * This algorithm may be stopped due to resources limitation. In this case we
+ * assume every unprocessed branch to immediately finish with matching (this
+ * can give us more false positives but no false negatives) by marking all
+ * unprocessed states as final.
+ */
+static void
+transformGraph(TrgmCNFA *trgmCNFA)
+{
+	HASHCTL		   hashCtl;
+	TrgmStateKey   initkey;
+	TrgmState	  *initstate;
+
+	trgmCNFA->queue = NIL;
+	trgmCNFA->arcsCount = 0;
+	trgmCNFA->overflowed = false;
+
+	/* Initialize hash of states */
+	hashCtl.keysize = sizeof(TrgmStateKey);
+	hashCtl.entrysize = sizeof(TrgmState);
+	hashCtl.hcxt = CurrentMemoryContext;
+	hashCtl.hash = tag_hash;
+	hashCtl.match = memcmp;
+	trgmCNFA->states =
+		hash_create("Trigram CNFA",
+					1024,
+					&hashCtl,
+					HASH_ELEM | HASH_CONTEXT | HASH_FUNCTION | HASH_COMPARE);
+
+	/* Create initial state */
+	MemSet(&initkey, 0, sizeof(TrgmStateKey));
+	initkey.prefix.s[0] = UNKNOWN_COLOR;
+	initkey.prefix.s[1] = UNKNOWN_COLOR;
+	initkey.nstate = trgmCNFA->cnfa->pre;
+
+	initstate = getState(trgmCNFA, &initkey);
+	initstate->init = true;
+	trgmCNFA->initState = initstate;
+
+	/*
+	 * Recursively build the transformed graph by processing queue of
+	 * states (Breadth-first search).
+	 */
+	while (trgmCNFA->queue != NIL)
+	{
+		TrgmState *state = (TrgmState *) linitial(trgmCNFA->queue);
+
+		state->queued = false;
+		trgmCNFA->queue = list_delete_first(trgmCNFA->queue);
+
+		/*
+		 * If we overflow then just mark state as final. Otherwise do actual
+		 * processing.
+		 */
+		if (trgmCNFA->overflowed)
+			state->fin = true;
+		else
+			processState(trgmCNFA, state);
+
+		/* Did we overflow? */
+		if (trgmCNFA->arcsCount > MAX_RESULT_ARCS ||
+			hash_get_num_entries(trgmCNFA->states) > MAX_RESULT_STATES)
+		{
+			trgmCNFA->overflowed = true;
+		}
+	}
+}
+
+
+/*---------------------
+ * Subroutines for expanding color trigrams into regular trigrams.
+ *---------------------
+ */
+
+/*
+ * Compare function for sorting of color trigrams by their colors.
+ */
+static int
+colorTrgmInfoCmp(const void *p1, const void *p2)
+{
+	const ColorTrgmInfo *c1 = (const ColorTrgmInfo *)p1;
+	const ColorTrgmInfo *c2 = (const ColorTrgmInfo *)p2;
+	return memcmp(c1->trgm, c2->trgm, sizeof(ColorTrgm));
+}
+
+/*
+ * Compare function for sorting color trigrams by descending of their simple
+ * trigrams counts.
+ */
+static int
+colorTrgmInfoCountCmp(const void *p1, const void *p2)
+{
+	const ColorTrgmInfo *c1 = (const ColorTrgmInfo *)p1;
+	const ColorTrgmInfo *c2 = (const ColorTrgmInfo *)p2;
+	if (c1->count < c2->count)
+		return 1;
+	else if (c1->count == c2->count)
+		return 0;
+	else
+		return -1;
+}
+
+/*
+ * Convert trigram into trgm datatype.
+ */
+static void
+fillTrgm(trgm *ptrgm, mb_char s[3])
+{
+	char		text[14],
+			   *p;
+	int			i;
+
+	/* Write multibyte string into "text". */
+	p = text;
+	for (i = 0; i < 3; i++)
+	{
+		int len;
+		if (s[i] != 0)
+		{
+			len = strnlen((char *) &s[i], 4);
+			memcpy(p, &s[i], len);
+			p += len;
+		}
+		else
+		{
+			*p++ = ' ';
+		}
+	}
+	*p = 0;
+
+	/* Extract trigrams from "text" */
+	cnt_trigram(ptrgm, text, p - text);
+}
+
+/*
+ * Merge states of graph.
+ */
+static void
+mergeStates(TrgmState *state1, TrgmState *state2)
+{
+	ListCell *cell;
+
+	Assert(!state1->parent);
+	Assert(!state2->parent);
+	Assert(state1 != state2);
+
+	foreach(cell, state2->children)
+	{
+		TrgmState *state = (TrgmState *) lfirst(cell);
+		state->parent = state1;
+	}
+	state1->init = state1->init || state2->init;
+	state1->fin = state1->fin || state2->fin;
+	state2->parent = state1;
+	state1->children = list_concat(state1->children, state2->children);
+	state1->children = lappend(state1->children, state2);
+	state2->children = NIL;
+}
+
+/*
+ * Get vector of all color trigrams in graph and select which of them to expand
+ * into simple trigrams.
+ */
+static bool
+selectColorTrigrams(TrgmCNFA *trgmCNFA)
+{
+	HASH_SEQ_STATUS scan_status;
+	int			arcsCount = trgmCNFA->arcsCount,
+				i;
+	TrgmState  *state;
+	ColorTrgmInfo *p1, *p2, *colorTrgms;
+	int			totalTrgmCount, number;
+
+	/* Collect color trigrams from all arcs */
+	colorTrgms = (ColorTrgmInfo *) palloc(sizeof(ColorTrgmInfo) * arcsCount);
+	i = 0;
+	hash_seq_init(&scan_status, trgmCNFA->states);
+	while ((state = (TrgmState *) hash_seq_search(&scan_status)) != NULL)
+	{
+		ListCell *cell;
+		foreach(cell, state->arcs)
+		{
+			TrgmArc *arc = (TrgmArc *) lfirst(cell);
+			ArcInfo *arcInfo = (ArcInfo *) palloc(sizeof(ArcInfo));
+			arcInfo->source = state;
+			arcInfo->target = arc->target;
+			colorTrgms[i].arcs = list_make1(arcInfo);
+			colorTrgms[i].expanded = true;
+			memcpy(&colorTrgms[i].trgm, &arc->trgm, sizeof(ColorTrgm));
+			i++;
+		}
+	}
+	Assert(i == arcsCount);
+
+	/* Remove duplicates and merge arcs lists */
+	if (arcsCount >= 2)
+	{
+		qsort(colorTrgms, arcsCount, sizeof(ColorTrgmInfo), colorTrgmInfoCmp);
+		p1 = colorTrgms + 1;
+		p2 = colorTrgms;
+		while (p1 - colorTrgms < arcsCount)
+		{
+			if (memcmp(p1->trgm, p2->trgm, sizeof(ColorTrgm)) != 0)
+			{
+				p2++;
+				*p2 = *p1;
+			}
+			else
+			{
+				p2->arcs = list_concat(p2->arcs, p1->arcs);
+			}
+			p1++;
+		}
+		trgmCNFA->colorTrgmsCount = p2 + 1 - colorTrgms;
+	}
+	else
+	{
+		trgmCNFA->colorTrgmsCount = arcsCount;
+	}
+
+	/* Count number of simple trigrams in each color trigram */
+	totalTrgmCount = 0;
+	for (i = 0; i < trgmCNFA->colorTrgmsCount; i++)
+	{
+		int j, count = 1;
+		ColorTrgmInfo *trgmInfo = &colorTrgms[i];
+		for (j = 0; j < 3; j++)
+		{
+			/* FIXME: count could overflow */
+			if (trgmInfo->trgm[j] != EMPTY_COLOR)
+				count *= trgmCNFA->colorInfo[trgmInfo->trgm[j]].alphaCharsCount;
+		}
+		trgmInfo->count = count;
+		totalTrgmCount += count;
+	}
+
+	/* Sort color trigrams by descending of their simple trigram counts */
+	qsort(colorTrgms, trgmCNFA->colorTrgmsCount, sizeof(ColorTrgmInfo),
+														colorTrgmInfoCountCmp);
+	/*
+	 * Remove color trigrams from the graph until total number of simple
+	 * trigrams is below MAX_TRGM_COUNT. We start removing from largest color
+	 * trigrams which are most promising for reduce total number of simple
+	 * trigrams. When removing color trigram we have to merge states connected
+	 * by corresponding arcs. It's necessary to not merge initial and final
+	 * states, because our graph becomes useless in this case.
+	 */
+	for (i = 0;
+		 (i < trgmCNFA->colorTrgmsCount) && (totalTrgmCount > MAX_TRGM_COUNT);
+		 i++)
+	{
+		ColorTrgmInfo *trgmInfo = &colorTrgms[i];
+		bool canRemove = true;
+		ListCell *cell;
+
+		/*
+		 * Does any arc of with this color trigram connect initial and final
+		 * states?
+		 */
+		foreach(cell, trgmInfo->arcs)
+		{
+			ArcInfo *arcInfo = (ArcInfo *) lfirst(cell);
+			TrgmState *source = arcInfo->source, *target = arcInfo->target;
+			while (source->parent)
+				source = source->parent;
+			while (target->parent)
+				target = target->parent;
+			if ((source->init || target->init) && (source->fin || target->fin))
+			{
+				canRemove = false;
+				break;
+			}
+		}
+		if (!canRemove)
+			continue;
+
+		/* Merge states */
+		foreach(cell, trgmInfo->arcs)
+		{
+			ArcInfo *arcInfo = (ArcInfo *) lfirst(cell);
+			TrgmState *source = arcInfo->source, *target = arcInfo->target;
+			while (source->parent)
+				source = source->parent;
+			while (target->parent)
+				target = target->parent;
+			if (source != target)
+				mergeStates(source, target);
+		}
+
+		trgmInfo->expanded = false;
+		totalTrgmCount -= trgmInfo->count;
+	}
+	trgmCNFA->totalTrgmCount = totalTrgmCount;
+
+	/* Did we succeed in fitting into MAX_TRGM_COUNT? */
+	if (totalTrgmCount > MAX_TRGM_COUNT)
+		return false;
+
+	/*
+	 * Sort color trigrams by colors (will be useful for bsearch) and enumerate
+	 * expanded color trigrams.
+	 */
+	number = 0;
+	qsort(colorTrgms, trgmCNFA->colorTrgmsCount, sizeof(ColorTrgmInfo),
+															colorTrgmInfoCmp);
+	for (i = 0; i < trgmCNFA->colorTrgmsCount; i++)
+	{
+		if (colorTrgms[i].expanded)
+		{
+			colorTrgms[i].number = number;
+			number++;
+		}
+	}
+
+	trgmCNFA->colorTrgms = colorTrgms;
+	return true;
+}
+
+/*
+ * Expand selected color trigrams into regular trigrams.
+ */
+static TRGM *
+expandColorTrigrams(TrgmCNFA *trgmCNFA)
+{
+	TRGM	   *trg;
+	trgm	   *p;
+	int			i;
+	ColorInfo	emptyColor;
+	mb_char		emptyChar = 0;
+
+	/* Virtual "empty" color structure for representing zero character */
+	emptyColor.alphaCharsCount = 1;
+	emptyColor.alphaChars = &emptyChar;
+
+	trg = (TRGM *) palloc0(TRGMHDRSIZE +
+									trgmCNFA->totalTrgmCount * sizeof(trgm));
+	trg->flag = ARRKEY;
+	SET_VARSIZE(trg, CALCGTSIZE(ARRKEY, trgmCNFA->totalTrgmCount));
+	p = GETARR(trg);
+	for (i = 0; i < trgmCNFA->colorTrgmsCount; i++)
+	{
+		mb_char s[3];
+		ColorTrgmInfo *colorTrgm = &trgmCNFA->colorTrgms[i];
+		ColorInfo *c[3];
+		int j, i1, i2, i3;
+
+		if (!colorTrgm->expanded)
+			continue;
+
+		/* Get colors */
+		for (j = 0; j < 3; j++)
+		{
+			if (colorTrgm->trgm[j] != EMPTY_COLOR)
+				c[j] = &trgmCNFA->colorInfo[colorTrgm->trgm[j]];
+			else
+				c[j] = &emptyColor;
+		}
+
+		/* Iterate over all possible combinations of color characters */
+		for (i1 = 0; i1 < c[0]->alphaCharsCount; i1++)
+		{
+			s[0] = c[0]->alphaChars[i1];
+			for (i2 = 0; i2 < c[1]->alphaCharsCount; i2++)
+			{
+				s[1] = c[1]->alphaChars[i2];
+				for (i3 = 0; i3 < c[2]->alphaCharsCount; i3++)
+				{
+					s[2] = c[2]->alphaChars[i3];
+					fillTrgm(p, s);
+					p++;
+				}
+			}
+		}
+	}
+	return trg;
+}
+
+/*---------------------
+ * Subroutines for packing the graph into final representation
+ *---------------------
+ */
+
+/*
+ * Temporary structure for representing arc during packaging.
+ */
+typedef struct
+{
+	int		sourceState;
+	int		targetState;
+	int		colorTrgm;
+} PackArcInfo;
+
+/*
+ * Comparison function for arcs during comparison. Compares arcs in following
+ * order: sourceState, colorTrgm, targetState.
+ */
+static int
+packArcInfoCmp(const void *a1, const void *a2)
+{
+	const PackArcInfo *p1 = (const PackArcInfo *) a1;
+	const PackArcInfo *p2 = (const PackArcInfo *) a2;
+
+	if (p1->sourceState < p2->sourceState)
+		return -1;
+	if (p1->sourceState > p2->sourceState)
+		return 1;
+	if (p1->colorTrgm < p2->colorTrgm)
+		return -1;
+	if (p1->colorTrgm > p2->colorTrgm)
+		return 1;
+	if (p1->targetState < p2->targetState)
+		return -1;
+	if (p1->targetState > p2->targetState)
+		return 1;
+	return 0;
+}
+
+/*
+ * Pack resulting graph into final representation.
+ */
+static PackedGraph *
+packGraph(TrgmCNFA *trgmCNFA, MemoryContext context)
+{
+	int			number = 2,
+				arcIndex,
+				arcsCount;
+	HASH_SEQ_STATUS scan_status;
+	TrgmState  *state;
+	PackArcInfo *arcs, *p1, *p2;
+	PackedArc  *packedArcs;
+	PackedGraph *result;
+	int			i,
+				j;
+
+	/* Enumerate states */
+	hash_seq_init(&scan_status, trgmCNFA->states);
+	while ((state = (TrgmState *) hash_seq_search(&scan_status)) != NULL)
+	{
+		while (state->parent)
+			state = state->parent;
+
+		if (state->number < 0)
+		{
+			if (state->init)
+				state->number = 0;
+			else if (state->fin)
+				state->number = 1;
+			else
+			{
+				state->number = number;
+				number++;
+			}
+		}
+	}
+
+	/* Collect array of all arcs */
+	arcs = (PackArcInfo *) palloc(sizeof(PackArcInfo) * trgmCNFA->arcsCount);
+	arcIndex = 0;
+	hash_seq_init(&scan_status, trgmCNFA->states);
+	while ((state = (TrgmState *) hash_seq_search(&scan_status)) != NULL)
+	{
+		TrgmState *source = state;
+		ListCell *cell;
+
+		while (source->parent)
+			source = source->parent;
+
+		foreach(cell, state->arcs)
+		{
+			TrgmArc *arc = (TrgmArc *) lfirst(cell);
+			TrgmState *target = arc->target;
+
+			while (target->parent)
+				target = target->parent;
+
+			if (source->number != target->number)
+			{
+				arcs[arcIndex].sourceState = source->number;
+				arcs[arcIndex].targetState = target->number;
+				arcs[arcIndex].colorTrgm = ((ColorTrgmInfo *)bsearch(&arc->trgm,
+								trgmCNFA->colorTrgms, trgmCNFA->colorTrgmsCount,
+							sizeof(ColorTrgmInfo), colorTrgmInfoCmp))->number;
+
+				arcIndex++;
+			}
+		}
+	}
+	qsort(arcs, arcIndex, sizeof(PackArcInfo), packArcInfoCmp);
+
+	/* We could have duplicates because states were merged. Remove them. */
+	p1 = p2 = arcs;
+	while (p1 < arcs + arcIndex)
+	{
+		if (packArcInfoCmp(p1, p2) > 0)
+		{
+			p2++;
+			*p2 = *p1;
+		}
+		p1++;
+	}
+	arcsCount = p2 - arcs + 1;
+
+	/* Write packed representation */
+	result = (PackedGraph *) MemoryContextAlloc(context, sizeof(PackedGraph));
+
+	/* Pack color trigrams information */
+	result->colorTrigramsCount = 0;
+	for (i = 0; i < trgmCNFA->colorTrgmsCount; i++)
+		if (trgmCNFA->colorTrgms[i].expanded)
+			result->colorTrigramsCount++;
+	result->colorTrigramGroups = (int *) MemoryContextAlloc(context,
+									sizeof(int) * result->colorTrigramsCount);
+	j = 0;
+	for (i = 0; i < trgmCNFA->colorTrgmsCount; i++)
+	{
+		if (trgmCNFA->colorTrgms[i].expanded)
+		{
+			result->colorTrigramGroups[j] = trgmCNFA->colorTrgms[i].count;
+			j++;
+		}
+	}
+
+	/* Pack states and arcs information */
+	result->states = (PackedState *) MemoryContextAlloc(context,
+												number * sizeof(PackedState));
+	result->statesCount = number;
+	packedArcs = (PackedArc *) MemoryContextAlloc(context,
+												arcsCount * sizeof(PackedArc));
+	j = 0;
+	for (i = 0; i < number; i++)
+	{
+		int cnt = 0;
+		result->states[i].arcs = &packedArcs[j];
+		while (j < arcsCount && arcs[j].sourceState == i)
+		{
+			packedArcs[j].targetState = arcs[j].targetState;
+			packedArcs[j].colorTrgm = arcs[j].colorTrgm;
+			cnt++;
+			j++;
+		}
+		result->states[i].arcsCount = cnt;
+	}
+
+	/* Allocate memory for evaluation */
+	result->colorTrigramsActive = (bool *) MemoryContextAlloc(context,
+									sizeof(bool) * result->colorTrigramsCount);
+	result->statesActive = (bool *) MemoryContextAlloc(context,
+									sizeof(bool) * result->statesCount);
+
+	return result;
+}
+
+
+/*---------------------
+ * Debugging functions
+ *---------------------
+ */
+
+#ifdef TRGM_REGEXP_DEBUG
+/*
+ * Print initial CNFA, in regexp library's representation
+ */
+static void
+printSourceCNFA(struct cnfa *cnfa, ColorInfo *colors, int ncolors)
+{
+	int state;
+	StringInfoData buf;
+	int i;
+
+	initStringInfo(&buf);
+
+	appendStringInfo(&buf, "\ndigraph sourceCNFA {\n");
+
+	for (state = 0; state < cnfa->nstates; state++)
+	{
+		struct carc *s = cnfa->states[state];
+
+		appendStringInfo(&buf, "s%d", state);
+		if (cnfa->post == state)
+			appendStringInfo(&buf, " [shape = doublecircle]");
+		appendStringInfo(&buf, ";\n");
+
+		while (s->co != COLORLESS)
+		{
+			appendStringInfo(&buf, "  s%d -> s%d [label = \"%d\"];\n",
+							 state, s->to, s->co);
+			s++;
+		}
+	}
+
+	appendStringInfo(&buf, " node [shape = point ]; initial;\n");
+	appendStringInfo(&buf, " initial -> s%d;\n", cnfa->pre);
+
+	/* Print colors */
+	appendStringInfo(&buf, " { rank = sink;\n");
+	appendStringInfo(&buf, "  Colors [shape = none, margin=0, label=<\n");
+
+	for (i = 0; i < ncolors; i++)
+	{
+		ColorInfo *color = &colors[i];
+		int		j;
+
+		appendStringInfo(&buf, "<br/>Color %d: ", i);
+
+		if (!color->expandable)
+			appendStringInfo(&buf, "not expandable");
+		else
+		{
+			for (j = 0; j < color->alphaCharsCount; j++)
+			{
+				char s[5];
+				memcpy(s, (char *) &color->alphaChars[j], 4);
+				s[4] = '\0';
+				appendStringInfo(&buf, "%s", s);
+			}
+		}
+		appendStringInfo(&buf, "\n");
+	}
+
+	appendStringInfo(&buf, "  >];\n");
+	appendStringInfo(&buf, " }\n");
+
+
+	appendStringInfo(&buf, "}\n");
+
+	{
+		/* dot -Tpng -o /tmp/source.png < /tmp/source.dot */
+		FILE *fp = fopen("/tmp/source.dot", "w");
+		fprintf(fp, "%s", buf.data);
+		fclose(fp);
+	}
+
+	pfree(buf.data);
+}
+
+/*
+ * Print trigram-based CNFA-like graph.
+ */
+static void
+printTrgmCNFA(TrgmCNFA *trgmCNFA)
+{
+	StringInfoData buf;
+	HASH_SEQ_STATUS scan_status;
+	TrgmState *state;
+	TrgmState *initstate = NULL;
+
+	initStringInfo(&buf);
+
+	appendStringInfo(&buf, "\ndigraph transformedCNFA {\n");
+
+	hash_seq_init(&scan_status, trgmCNFA->states);
+	while ((state = (TrgmState *) hash_seq_search(&scan_status)) != NULL)
+	{
+		ListCell *cell;
+
+		appendStringInfo(&buf, "s%p", state);
+		if (state->fin)
+			appendStringInfo(&buf, " [shape = doublecircle]");
+		if (state->init)
+			initstate = state;
+		appendStringInfo(&buf, " [label = \"%d\"]", state->enterKey.nstate);
+		appendStringInfo(&buf, ";\n");
+
+		foreach(cell, state->arcs)
+		{
+			TrgmArc *arc = (TrgmArc *) lfirst(cell);
+
+			appendStringInfo(&buf, "  s%p -> s%p [label = \"%d %d %d\"];\n",
+							 (void *) state, (void *) arc->target,
+							 (uint32) arc->trgm[0], (uint32) arc->trgm[1], (uint32) arc->trgm[2]);
+		}
+	}
+
+	if (initstate)
+	{
+		appendStringInfo(&buf, " node [shape = point ]; initial;\n");
+		appendStringInfo(&buf, " initial -> s%p;\n", (void *) initstate);
+	}
+	appendStringInfo(&buf, "}\n");
+
+	{
+		/* dot -Tpng -o /tmp/transformed.png < /tmp/transformed.dot */
+		FILE *fp = fopen("/tmp/transformed.dot", "w");
+		fprintf(fp, "%s", buf.data);
+		fclose(fp);
+	}
+
+	pfree(buf.data);
+}
+
+/*
+ * Print final packed representation of resulting trigram-based CNFA-like graph.
+ */
+static void
+printPackedGraph(PackedGraph *packedGraph, TRGM *trigrams)
+{
+	int			i;
+	trgm	   *p;
+	StringInfoData buf;
+	initStringInfo(&buf);
+
+	appendStringInfo(&buf, "\ndigraph packedGraph {\n");
+
+	for (i = 0; i < packedGraph->statesCount; i++)
+	{
+		PackedState *state = &packedGraph->states[i];
+		int		j;
+
+		appendStringInfo(&buf, " s%d", i);
+		if (i == 1)
+			appendStringInfo(&buf, " [shape = doublecircle]");
+
+		appendStringInfo(&buf, " [label = <s%d>];\n", i);
+
+		for (j = 0; j < state->arcsCount; j++)
+		{
+			PackedArc *arc = &state->arcs[j];
+			appendStringInfo(&buf, "  s%d -> s%d [label = \"trigram %d\"];\n",
+							 i, arc->targetState, arc->colorTrgm);
+		}
+	}
+
+	appendStringInfo(&buf, " node [shape = point ]; initial;\n");
+	appendStringInfo(&buf, " initial -> s%d;\n", 0);
+
+	/* Print trigrams */
+	appendStringInfo(&buf, " { rank = sink;\n");
+	appendStringInfo(&buf, "  Trigrams [shape = none, margin=0, label=<\n");
+
+	p = GETARR(trigrams);
+	for (i = 0; i < packedGraph->colorTrigramsCount; i++)
+	{
+		int count = packedGraph->colorTrigramGroups[i];
+		int j;
+
+		appendStringInfo(&buf, "<br/>Trigram %d: ", i);
+
+		for (j = 0; j < count; j++)
+		{
+			if (j > 0)
+				appendStringInfo(&buf, ", ");
+			appendStringInfo(&buf, "\"%c%c%c\"", (*p)[0], (*p)[1], (*p)[2]);
+			p++;
+		}
+	}
+	appendStringInfo(&buf, "  >];\n");
+	appendStringInfo(&buf, " }\n");
+
+	appendStringInfo(&buf, "}\n");
+
+	{
+		/* dot -Tpng -o /tmp/packed.png < /tmp/packed.dot */
+		FILE *fp = fopen("/tmp/packed.dot", "w");
+		fprintf(fp, "%s", buf.data);
+		fclose(fp);
+	}
+
+	pfree(buf.data);
+}
+#endif
diff --git a/doc/src/sgml/pgtrgm.sgml b/doc/src/sgml/pgtrgm.sgml
index 30e5355..c4105e1 100644
--- a/doc/src/sgml/pgtrgm.sgml
+++ b/doc/src/sgml/pgtrgm.sgml
@@ -145,9 +145,10 @@
    operator classes that allow you to create an index over a text column for
    the purpose of very fast similarity searches.  These index types support
    the above-described similarity operators, and additionally support
-   trigram-based index searches for <literal>LIKE</> and <literal>ILIKE</>
-   queries.  (These indexes do not support equality nor simple comparison
-   operators, so you may need a regular B-tree index too.)
+   trigram-based index searches for <literal>LIKE</>, <literal>ILIKE</>,
+   <literal>~</> and <literal>~*</> queries.  (These indexes do not
+   support equality nor simple comparison operators, so you may need a
+   regular B-tree index too.)
   </para>
 
   <para>
@@ -203,6 +204,23 @@ SELECT * FROM test_trgm WHERE t LIKE '%foo%bar';
   </para>
 
   <para>
+   Beginning in <productname>PostgreSQL</> 9.3, these index types also support
+   index searches for <literal>~</> and <literal>~*</> (regular expression
+   matching), for example
+<programlisting>
+SELECT * FROM test_trgm WHERE t ~ '(foo|bar)';
+</programlisting>
+   The index search works by extracting trigrams from the regular expression
+   and then looking these up in the index.  The more trigrams could be
+   extracted from regular expression, the more effective the index search is. 
+   Unlike B-tree based searches, the search string need not be left-anchored.
+   However, sometimes regular expression is too complex for analysis, then
+   it performs the same as when no trigrams can be extracted from regular
+   expression. In this situation full index scan or sequential scan will
+   be performed depending on query plan.   
+  </para>
+  
+  <para>
    The choice between GiST and GIN indexing depends on the relative
    performance characteristics of GiST and GIN, which are discussed elsewhere.
    As a rule of thumb, a GIN index is faster to search than a GiST index, but
diff --git a/src/backend/utils/adt/regexp.c b/src/backend/utils/adt/regexp.c
index 6a89fab..e29e734 100644
--- a/src/backend/utils/adt/regexp.c
+++ b/src/backend/utils/adt/regexp.c
@@ -128,7 +128,7 @@ static Datum build_regexp_split_result(regexp_matches_ctx *splitctx);
  * Pattern is given in the database encoding.  We internally convert to
  * an array of pg_wchar, which is what Spencer's regex package wants.
  */
-static regex_t *
+regex_t *
 RE_compile_and_cache(text *text_re, int cflags, Oid collation)
 {
 	int			text_re_len = VARSIZE_ANY_EXHDR(text_re);
diff --git a/src/include/regex/regex.h b/src/include/regex/regex.h
index 616c2c6..7e19e8a 100644
--- a/src/include/regex/regex.h
+++ b/src/include/regex/regex.h
@@ -171,5 +171,6 @@ extern int	pg_regprefix(regex_t *, pg_wchar **, size_t *);
 extern void pg_regfree(regex_t *);
 extern size_t pg_regerror(int, const regex_t *, char *, size_t);
 extern void pg_set_regex_collation(Oid collation);
+regex_t *RE_compile_and_cache(text *text_re, int cflags, Oid collation);
 
 #endif   /* _REGEX_H_ */
trgm-regexp-lcov-report.tar.gzapplication/x-gzip; name=trgm-regexp-lcov-report.tar.gzDownload
����P�=Mo�Hv�$�Iz�H�� @��-�m��H}t��zlw��n��v�`�Xh)�$C��j���=����r�9A�B�S��K� ���v��"E�����t��0�%���W��{�>���}�������w��:�A�U;���7n[��t:F[i��-E��-e�
�t[���!�5���_[��+��#mvj�'�����3��:�m]_;���Y�]7�-�T�Ga����?��x��{y�|�����+��'��O~����?��������G[[���?���r��/��O���������~Eo�.^n����{L/?}z���?��g���������~�g��O~����
�����������������?~��O�W��N���������m}��_���������|���{�t�������~����{vc������U5:��������>��g'���_�8E�������8?;F��f���q�yr}��7]{��[��:��l�^�������l����~����=��g80�4�{������v�:v����9��axuP���I�<F����88xu�d�[cP+������k���
�����{z�m9_#�5?���?�8���t��~
M=<>�M�7�����f�����;�%��������5
�5UQ�����F�;P���?7�kx57G#vE��O{���
�"%]Sk1�Cw���7�3'�K�btH�x��{{��}k6A�7$��
�a�B�-'��|0mB��a
b�}�G����'�N�H]�������aP"c�,����������7�y�p]�e�Bxm�B���#��6�q��!�������7��R��U���l�����A�9d!G��
d�Q��*��k����J�L��b��5�-���r��7��x��CU�����&��sL��m7t�*Z�������=E���q����R	.C�NG��n[����!G�bR�|[D�/��N���h	���_��>t����FF66zI���K{OL����N������D�������2��Qgi��Tn\-��TE���~��h����fAl�,U����a�z�h�P�����X/�YUl�����]�G����\U�gW�������9�����dZ�2����I�����1��|;-�_P�+��Y���1�)����
a���X��-E�������FS3��]?��;6�4-��cl4��v�Hs�������Cgp�Xt����n�<k��O��7�5�kk����B�2�_�^����8�&+�V?`{��H���"���&�9`/M�n;����R�����{��}�#�&X�z�Dx���~��3�����n�X������QsQA'��N����F�#����w�Aw���x�L������C6�~�s�~�|�gd�����WV��|�c=�(�(P�b�S����R,�C�����R5%�A)��7S�����y�����H�uF6�����!����P���Y�����y�w��]o����oR�ic>�G��,R�d�i������������/����K�}���t�s�{/�h�c���>����h����7�U��J�?��ng�_SU�.w����>��On'$j4����9(��.4����4IoYRQ#��~�}�bI��X�.KRE���%����cI2��7�P�x��%�(���#Jr������+Q?#��lV
'�#.����X�I|�>�@���?�p5���_��E�����R:k�tW��nC��r5��i��$�Da���N5Q��@`R6
i=X�@�t)`U��	�Bt>&�����hXP]��FAO=d���,zbnpL)�L���p�����O�+F����y��/?�����d������7b=CDB)�$�
���hOmt�W����Q�A|&���DJ���������������23�$D�g�06��$���!P�3���������~����{l��_�^�����]1����N�����������1�f�d�����BcA�-���������AmL�������PW���v���"��`�A�XQ/�C��Pn��r��F~���d/$��xl(1�����5������H(��~e[}(��OC�y��jf,c�+��h�	3�sOKg��x�����t@t�����F&��hc����e�����$���R��d�7����!�^ [��CE���G��������4 ,�������������>�*0���Y�������ix���v���F���M��������9���H��MU�CsH���N��d-�X�.�U������f��mwh����%����
]��+Z��7>���-�QJiY��/���_��:?�??zzv�8�������K�
]�c�5}�
m�5�t��Fk������Ju��,������������������k��� ��r�J]���]�R�$���(]=}�]NJ
���P��fiRN�����J��]�9Z&�J�y�m,��IZ-�ZBeE!-i�R���>���B���9l����"ZvKh	5r�Lz�"f%�Ak����������V������)���!k*e�P��
����AAj�s������U�i��!-��(�^���H�%`j\�+���.8:4�P��\0��(F�Vm@'������^�q���_]�u��:T��$�g������-&���BA7��7@����3}��Q�`~�G��������1�}��~��x���
������b7L6��������h�y���1�v�
��Gh���
�b:#����S���"��*���!�^��!@��������xy.1�*��]J|����:TN�J|]�<��Z/q����P��n��"����[�1��V�u��u����u���f`
��|xK6�����N�Z�Cw6�^C�����Fh��E�����K���:<�J�P�X�k"t{=��*���	��uVIMA24���*�P�R��X�b�KX�_&9n�������z��Nfy[R	����d���RrN��V�K()?)�,��Q��HuR��V[/@�Zzv�0/�������Jf��^�P���KNk��;'��^�j�]�O@@�4 Ei�3��^/��L�UUV����I����S���6�T����7Z��8�����M�3o���'�����6�T���68�5�l�v�;�]~P���v�����iW�m�7C ���,d�D�&M��l�v6��ik�
&S^�������"����1�S2�!3�����+(�3t���"/
����l ��������V���2��	9#����$���D�F��
�$�$�6���hK����h����1��/X;R�����a8;�dJGJI��prK$����m:�U�&�����Uvq��VV�a��|�2;��k=n�$D������h���DN��kG�6���$������>h<��'�3��������������,g���Gs��us(pQ0��6�i�H6$3��e��q���N�1�KoY��%���@*b��+�\����	�Z�H7Z�Mb"s����}��J��s��ND����%���V�v��-�x�qc�	��O,�1��S�"�B9Jo#����w
d�{E�! NkQ�U�gGV��(�a]+�,'w�Nn�/`�M��c�gg/���:9~v�|���mq�:�:G��t�A7����~x����l@���&h]�*�{�r�Bn}qau�KH`��S��'�����A����I#k����9�7��j6>9e����X[��������l��~�y��~7�)iF�(r�K1l�@ �(��v�g��R����������B�\��T	���Q#�����O'3�N�����b�	d�w�-C���d��Z&� �2�o,��zb�6���LE��ST�*�6UE.msUOE�BH��
Tk��9����&�W�Q����!�!I�^�3����N�'��g��@N0_n��=��6��m��@;w��Jn��E�8�-a�c	��7fl�DD��$��,n|�r
�D������A\Z7�������i�rj��/J����h��7li�5���*���E@���G�.����W�-�N�d������%�q|����l��&�F�M�&W�������"N�T���`��XV��m���>F�c���b>���=w���M�9&*1x�����v��d���?��	/��rI)�*R
���dg;8k��;�x���AT�� ��(�U�uke��������:��1)5�}T7m��[D�����F��m)|#�S���@iXB��Ea�����
�RO�Fy}F�����&ox!�P9�j����)7��3n��&< �
T����V���T� �X����Z����x`v<�Ln�E[_��|��S='2WP���5�1z�������i����W���/O������i��1�V%3#��30}�����'��g��>��I0�oG�[ 6W���/@���j�b�����������wAC�s��q]#8�����+H����[�P�K���4�m�1�0��e/�P*��U�y���4�^QzQ���S-����k~fD����w\���J��I-��V� ���>U�YE6�����d��$�
H�P$��������P�dr�8Rz"����d.�D'D�C��$5����"\����{rCT����
�zp�e7�cgd�����7q���e��������O����c/H�Z��;h�����Pr�C�mI�F&Rb!�����{�5�;�Y�7� w�tM1�C|�N�,%����%X�I�-�5�C�a"E[B����|�VE(�.mQ-7�r�����T�d/�P��/��z����S���H�Dt�I�*�&��U.C����G,Wx��*��6��^��������/�8�'��>a�!�;��%q���/�%�E�_�<���	.E�����Q��*%-�FJz��`��H3�PQ4.�a��:\��i;�e~������)*����F&VO=�U�hn��;d��N�^���)�����c��F;�N%}��
#_�`�d�J�{�W=�M�����OO��! wH�*/O����m(IvQ�X@JT�QZ�0H����I�J�d��L(�s���]������������������U�1����h�:�N�v���t*����)��
r��K��0|���K�**��P��'�c �p��0�T�,��C�oVI�[O�����01��)��*M~W���s3��pJ��k�D��k��r��qR�e����N�4���+MZ�8���>�Xd�@X�NU�'�����+�*N�.��
"R,K�qX������2
F�q�a�\�j�F���6����q���S����8��^\^��<������lq�Im�7�#���X����;C�����p�|��f(�>��yY@����h�~
�z�3��Z<8=�<v�U��M��/�fu�g��m�b���"�I��^��;��z���m>�0Z�:�����,�
�����'�:���"�T���t�<?�Y� �
��$�$~7��&~���Il���h3����BG�vS<P�a���i���H�8�G�k-4p�}��58�����U$+c��'����V�����*dFi��b=4^�0��r{l�=D��3�
�!����|(9��N'��$y�ov�X�|�M�h��y���@����zA�����D�	��q��.�.y�}�������0/Q�_B�k�PD^�#k8>:?~z����GH(�*y���I�/���(N�}��?���w�QBWz�9	~K
1O���>vd���D�9{7�=��H?�h������&Zx�|���b��0� 
���C�;����zp����^r����G�]~I�
�g6���Wn	�J	n�P�������aL|NXL[w01E3 ����=2�����]���P/����{������b�>[�	�ed���%�Y����H�Cl�!#���$��q�1��%N�����I��<�r�gV����i;�*�'=CX]�?=��s�������������""��N:��ZD�Mg�r��~�����V�8>�t�&hx���>*��r��hz������;:�����K�k�6�_x=t=�s��uw����K�	�nq�4�/r���A����5��6�/*?�U�|{b����mA?V}�����W�i�X@����"�;6S�������l���r2�m%������(�0:��o J�7"7�TZM�����J��8���u��������
rf�������=�8i��FLR��99w9��9B����8sX���q���|(�2�dG"~:x�y�r�G�'��m>����*5b��=4��Ss��|���;�������B.�b��n���B�FsbX~��8��k�b��0[�v�y|;����N��{7��[��Z"�+4�c%�1�	�`�K2�-M�d���D>[�shTr�����@�=9�<�� o�p�9��g����y�#Y���4���ccc�R2��������@6y

�l�A^�����`U	 �U���Y$q��o!���"3meZi'-G;�F;m��J�1�������
�D��CT�#������?w�!��U��V�On�7V�dI�j��\E>i=E���59R3��k����U0XMz��L�F�w������������0�����g���.`���8�E�x�J?$r~�jQ0a^�V��h'�`"�j����><�i_{�!��!�R��|�X�u�z�)q���oJG��,����)�8zz���`jli<.B����==�&����.^\.fg(�*�3Ai��R�d����vzj�6����TCG���k\����v�Cp����p�IG`���?yS��C��v����	�����/L���K�-]�;U��U�u������C�J���r����E�^>�q�ju������~gZ9����U-Z�vZ�N2KL�)�xt�#u�`����i��:��e�*i�j�R@/v�<
���,;�)06��
�����W����B7�P���XVt��Ak�^C��-A���f�a���6O��\
5F�(���9��l�:�@���
����A8�f�:��a�i�����|Y���:dF������6c'���������!'�I�i��q�Ae����";V��r��X�Qoi~D�l����y?����ZZ�R��n�:�;V�V��~S^G��6/v� ���x��y���:IM;�Y1�So��#IT	�<�dY�![�A�0�E�3��P��@�)��H��k��q6����w���e_�d ��(�L2TGY6����=[�2q(��J��58|Gq8�����8����7"���&�B������?��~��'qUW q�G14�8��G�K��������L"_�TC����@_���y�������n\x���T�B�N��H�iI������d�0"G�I���}�,���������T�GS~�<P�9�Idr���p��{��Qs��L�3R,%C���S��xB���7��k�v�51��8����V}Z0x�zXS�F:d������B�y����w����6�'�m�U�|��2����N�J�ps��6�K�9��D��%\;qF���A-V-J��S����E1H�Bs#�#�{�,m���GVj�8-����%�w���U������:�������C�sG��P��Q�}{��~e����Yp#���)��4�]y��@c�Qt@@������@�>���}��~�R�Z��1(-�)�uU.L)��-Uai��&WF��g�qE�VC�w�����eG�BhnkM4�1�a�*����rZ��2u�+&����Z�{V!6��	�y�Q-�sB^�����z
�a��(�]:�!�$�)�2[
��#��9�����_�����W��+����c 6
'G��g|8�O�d6�7�e�����s�p����"�y��G����|D�����&6�v�'�n&�������b<�xk����
����.������R���%#���&����d���)�6�d��������6���j�*���s]}�B�@+.�	��Z)��|i1Mq��v�_V()����j��8�j#J1�����x-�
��ttk��&@�`���]��UVN=�E��E���A�F��UH��`�)t���#����dh^����Y����DN���b��.{���+V�7���!�������������u��Zs��i��9Q���[�Ddu�,�|w�:�� ��9�[�W�`�i��t��`��w���%F��+�e�b����)�I�������k���UvAa���4|���4�h��b)e��{�T"%��c
3r���b���nmq�����������k� �8����u2�u�����o���`n=n<m��������n��,EqG���)��j@�.9)^��F/�X�����R��_��U��h!�X����zI$�����u���sM�e���3�_Bd�*�b����`�V������z���S�K���)��M��E<�M���z������PH"��^���j��.�_��5]�Ee��Ko����!������]s�VP��"����l�;.g
���[;�m�hq!�d�[�kz����ES������K���k1�����{�6Z��b��+�I|jh����%�����l����uEw���F�����X����x��;
g��ZVc8iIX9��v*�)r�������J�N�����*����y]��'���g����xu|����	���=eq����R:��<�e�@��}������>={�j���:�h;��U���pq������z���=E����(]h�=a����v�n�]dY�	$�-���O�O�[��_FR�?��&���bsG��`�j�%���$:����:�`�������RC$�����rk��J�g�_�h���V�&���Y }"Jc��}�@|���&;���uc�+q�U3�
��N���x�����x/��f����>�wB�A��s/����0!~'��3���;�C�=+�{m]_���")K�tm/����Z�~��[���yq��������Abh�Ka1@���~q���|m��kDbv��i��=d"��cp.4��-��9%��J����
�iy��d7�a���mM������y�S�;���vE��1��' I
*���L�g:��h:��{�E.�sY��� ,H�M��w������W����Y���	��d�'q�)u�J�i,�|�#���sQO;IZ��<�Q�P�t�h���Y����B���X�$���B��1Ok������WP=�|���~,�����nZ����!�;��%@;��0N���1���RF(��GF����]A�����:�W/�*Z�z�R�E����V��@��M�	�������M���J���b�Af�TP��[��!*5���g��i<?�o�84���#-8U���TO�������=���&���|>Op$�%]�7X����xvv���_[�t��^=24	��<K�oO��9>{��������G�=*?�����Z}{��&*�o�����^���2c:N�#��p�E�q�>�[��d�k�������e�*FE��r���<�@�0�E:iYf���
��RO�#P/�*�)�[A�����D��+�h�E=\���[j����#�n�Z��*���%�dRu
=�����h_���2�j������JRS�}gl�q+D�����}�i�*
���^�8�	�V����N�����sbOm��T�E����X�O��d�sh������^��gg}hPe5�D�.,�KN��q�p��uj�u�������\�R������z����v���LeA��������kZLv�s��vm���1y��������k�^�6�{��9���(@���Y2-��W���+q����6{"����b#�����5��@r�vG7��r{�Z�O�aJB����X~�>N��CCM&��o[I��l�`��Lb��3�2���Y�I��N�K��3��Cb�����r���c3K.���!�Un����p#��{���Y1��Q�I`��/~~{���1^���i�"U��r����j���y=�J�Au.!#M�1ez�p��w���������^��A^D��u���TU����h-dp*���y`�Z�;���C����<���+?�����v��!�E=�a�Ev��	=z.�
vzD|��~���b�h;b��Hz��a�{�n� ��!�q��3���!���g����lg�������U �,0�����E�BFq"�`�N�bns0N�����WV�d�+
�6-�6s�h�y#�"�����O�����j`hs �F�Z�VQ*w�d-mR,����X�^�-^fo���
��O�ukb�j��(7,��h�X_����_�]�5V
��
v
���-�)i���H[� 4��Vw5s������t�K&���e$��D�84��Z�#�1L�p+
i]��rF�o@�,}(�DO#��q������lp��q���MzwS�?��LA+�d���.�5�b
P���@�C�0]��G������I�#6Q}a����V�
��
�y��|"4v����1D��Z��pM�&�#0M�z�+�|���A�~"�'�^S�`�d��2�X�0���5(
&�����Q��>�3gI�EZ�1���c}C�%N��DM���]V���z��
l�����F>)���'\NR�@��x-������	)��b�9�A��4R�L!�-���i���G`�:��Z�s#�Md�o�J���!J���[G�!��Y�����V��t]�j��#�*��_U~x�����p7��}��tnx-v�t�q|v�j���qZ7�	��rf���L2rR)g���j9�K���n�%9�lD���I�6��X����4�&�`I������������a��o<v[�XP����A��VrY�K
o_r�2m�?o�T{������|ix-��}*K�����6?�l��-������1�J6F���fc��OP��l,��112�gb���������9���]&F���z�gb�qx-6rAu+-��UQkS����W��2��c��8�+?��Ur�;�Wwfs�����v��|�_�������~8���_������k�D�n�����?�fC<�
��e�4�F#��T���!���c��y0�d�|�xm{{��w	�n���kI;v��W1����k�'@kJf���<�<���"\{�<Q0@jd��=v5�/�]������8�mG�b>�/����=���a�+�.��1�=��������eH��O��'G�~fI;������DTm�~�9G�|�v������_��?c�5�5�g��4��;�K���;�2�n�/���N�[�mXZmp���G:��W�/�t\��q��A��/��Wm��E��X���\*��o���[���`��T�����7O_����!����{����lmkg������������v�a��(��o�������	Xl�q��x��g�a���q�����><^;�+���-H��&0���X�y$2�D�u�=}���&j���`[,��x;��Rm��W��E"�E���
�*~������(�������[rj"�Q��p���O�w'���m/������p����3�C�c����U�����b���������o�M�����%�����/b��	�9�b�C�|��
5tz�~��>��9*�$���O���=����1���/L�Z�Re�%_��p��z�v����F���w�����*-�T��d��H���+7�*�]�=�����Qw.�����������+��4����F���dT+����V�)�"KVR����N�O�nC�G\��(���?���z�I�������o^�|�w��}���q�wd_c�����j;[���@��p������Pz�m��n�w�M^������nW�7G�z��m��M�}��ZR{z7JK��*f-����U�����`��c�(z��rIjx����~���{���t��co���
?��	Z
�o�B�~�AZ�F��iq��v:LNW�T�/��Y)����c���8��o�l-��m�3?	���hU���?Wi��>)������l�\B�|6m��L.������7�RjD �g�e?kO:m����%��')�B���g�D�d5:�`4�qb�2��/������'���=�B�H?g6�s�$���l<�7O�^���6����������9���1m/YV���M��e����^���L��+@VkC���v����:�{��m�;���i�����Z^����|�U��*V��j�����=�L��7���Y������U[7+{o��'Q�����)@[A-T�}�)��F��KW�"Gl��E�~mP�VN�/���2E��8�S���\�����U�5b��S;}��
K�H��[H�gflA�
^s��X�a�S��{yw���kw���Riw��j�S����s=�^���[���R�NI��}���e��CEcV��Go��;\N��}�o�K�������_-bX��q�&���8���l��r����]���4�X���?����S}@^�������y4{�����D|��g;�l�_V3�uj���MM��j�����h�]a��+@��������VW�`w�%,?�]��U����H��g�7 -��^�=^u�U`�����t�]�����Y��7���k�����.��-��J�����H�.Lf���P7�����j��+*������i,�n*n�-,���jZ�����v�aw0����8�e����bva���w���U�`��N�2,Z�����k���Q��!���*�_�u�����9����(w�������qo�-���h�?�W�{���e��otHU�H�N�I��v�%����6���?�Y�_�Mv�_��,	��{��]F�dW�{�)�&��: �LfF8�n�g�P��i�8�Sp�Y���t��nt�*��|/�4y��O���^g��O��v�kO&�{?�Hs��k�������,����L$
�&��q���R|X]"�{MR��-��
M��;r��4y���Tx��.��q������������0�"�\)�����i��i�h�_L�B�<����>��������j���1�n��d���7�4E�ZFS������:�
?������{��<�x����[�#����nt���yR�"�f�}<�q<�0*��7����s���"48��]�)��@7N�^ua~�Tv	��$�f������`z����X���B�������N�b�w������[(���{�������o�������������{�>����qS����}�����4��P�
[���t��m�w�G�������(��������N���[=���{��5*������7o��e����
�_���p:�]w�5�Kw��>\7�-|�p���)����U��}o����������w�U�����.7�p��Qs���?�}��{����_���_��L��;���.$��S�*�P
�����Vr�"�������:�{���,����������v���������(B�/��{�����"A������^|��4l[%��GY���o%�I�E}%h�D�O�vmM86�H)������/E����\���������VgQp9=��I8������Bi��i���0�vG����\�it�j�����:m�n�5
�@��(�&��i�[����*w�9����X�Ng7%t���h��l5J;nN)������}n�
�<�2��A7�/�7�Ve�����u=����)?x4���{��`��^Fe0|�����[ ��e�=�v����n?�p1
t��[!���{����aGni���{q�u��!���N��L��tn�+$bV�@go�>��~F����>� ��N�f���i5jM����n�Z#I�h����#�r�>�n�J-�����tjd�G�0��~�T3!�6�m����nc�jt�L�@h�Du�o�y�5��������f8}��"D=�����������X):�?����?n����q�{���(��?��?��?��?��?K�}����H������������ >3�����D�w��t7�tw�	�n����/��y\�nL�l����1��{��{���x�w��e�;��;��rW��w����81�;�����V����=X�l���?����?��?��f���d[��
�����z������p��s�O����������g����7�a��R��Y�U������������
���������|�>?�s�*k��{��<����<b��}��l�����pb�?��"�y\��.{:���2?����*���8���.��pq�?^L�����R�v6�����%��60�o�Cnc��K���`:/�����a�hF�������3�H��^K��TS�+d����
�~�D�����t��)���M��u�6��Y��j?�����^���g����xu|��������V��\��\��.>:uCryb1)����*����	�H��kY�=W�p7�dO1����<��Q���n|����[5�.:����i<w�I�����l4�T����.g�
jn�nVWq�����yX��M��r����c���=���X���l��m
�)�]�LV\��7A���J<����e�A�r ����d�A�$
#
A��<��Y���P9^�r��p�I�hv�I�e�GZ5L*��kY�6V����i<����
4���4l4�V�8��Lc�!M���A�a��c�Z�H��v�\��T^������������7m}������Z��7�_��u���~�:�S��Y���e����������m~�\_���"�t�,cg�����s^�p�o�q��)�U/���+b_���R�?,�`��(f>\�l*(8/�8�;����=f���GG���d���M���u�������&�8���eI#���_�_O�8���H�T�%-K)����������&z��r���y���n�q�F5)K)�����������X�s*S��a��pV��pV�\��Y��.���s]g���.�[�H��������Mep��a�.>��������r �������Ui\����-���X�\���}*{�����R��i���e����Wo6{�4�Y0���	�����{M_��!|sx���������/[m��O����t�P���W�JZ�[�*
M
�J
��P�.�Lf��[�]�@w�����L���hW/S�.M.��`�Wh�E�>o&��~|q����k�Lj<�r���a|���^�%��>y��	����d�Te�O����������-��v
-6���$/7f�������B&��b\!�:#�d�Ii�H�b��54�T:�����q��erS�78���fY'��
�B���)o�%I9y�����?�?J?��`�3^W��E� f;$kl�]�����
�KC�$�Vm���X��������.�|�G��i����BE���z~E���
���p]�s�z/�{��2����<�q5�;
����l�rH����5p�V��X��&�G|��o2`�{���3s�YF�O�'?%K��������n5��G�0���o�Q�GJ�`O�S������I��=H�J�;��n��$-�_�HC?"}�����������85���~�����
������`�)���o�I�R�p�6�KN��N�k�p���1P�����
����.��EO]�����?���������J9-B������=9mSI���6������Nm��������i��s���6��������v����[v���7��������2:y�/���m��OO������"�2j�Rf�3o<��D��>���N��O7�x)}����4�[	C�d���/ ��Z|��7I���s��/���I�g���^F���	5���	l�g�G'����A���P���{M��#��~C5Ri�x~��JT�& ���C�[�zE�8>^�����?��U��(s�D�PV$��{i�����������*�P�
qo~@%6���]-U�A��D��>U�"����/-Zg0�������j���3�!�u�Z9��l�/����)!z��y�v�c�����zzHD�z�����Zn"�����%�`�B��.�U�_��tq���y,_�F~eN���V�^!���8������V|��w����)?�?:x~*D��xec�4�R'?�6��� ^�f�II>s�LdbN3�
�M�����,�;p�6�
�uh��p1�.�5L�.��=^��������8����}-"{���
�"���	5:�"����������2k��B�j��Z0���h�T{�J������U!���p�����Q������o�g=�/i�9��C��o�E.`|3����R�:�K��v+R�[�3M�Z:R��=^�(�x�j/�H��� i^�#]~/h�����\}I#m�L�h���eg�M}���K,Q����{_�,gc�� ��v�iE�j5Q
���QQ
�I����W\�j�m��.��!P�����m�.ti�@������Slv]�������gC^1��|*6�<��h+��[��R�_��b�i{���Jw�/��}<��C��W��d����S(�����t��5d/I��sAw�=?Ig��_~��?��O�VZ�F����v� ���z^������e��u
J���3�]KO�� �U�����C����P����S!2w
��^q<W��t� ����B�P�����l�O:���.���m�{��W���G-��H�����d�^�^��<b�h�a\��J����@>�_�H2�.Q��4��o�IH���T|!�
������0�����O�^�"I�2U�����.��e��(y��+T��|��~�%Rj���qKjI�:�
F�'�������������#�-
A���y���sx���m��Wg�6����*yE���\>�@Q���������<����E��c�6�n������E���+�#��)��d�E6V��Tb�B��� ����qv6�H3��CfC����)a������?���S���03����,���i�����V&mp6�}���+�A���T�}o:bb2��*��so"�,���d���[(tf8b)]ISi��,*� O���5��n��f>T>���g��l��b�H��r�X�Q��I:�D�����"N�_m��h�~�����.���^�r^G@�b��l_���i��>6�M�{��E,�N���|�� RL/�3/��|�.�#�s��t��X�G!K�S��u����4k;��"���T
�v�
J���+����F�c��s�r���09����GG�o#�
n�q�Sb�{U�[?P�
��c����� ��Z���bNnd�Je���!\Os��86�w�F�&�d8����$m��IY����F��7{Ws���<:�?�����K����R>�L6�
F��c�k���)X�� ���RA[G��}��d�7I���r�I0	��<���|�!��yd���W���By!���\c��q�9`��i!�2��s�{O���d8��"������������o�����`\�|���`������VK=���S��W������`�/\��oE����!�"Ei�(�Z*�������.[.9;�6|�Nz�V%��9�"V���1�X��k�ReD��h��G�	���Fi�b��t�&�LgQ��
��b+�mI��9�b:�����O���qx��Kb�mf�tv.s�*�>�������{��1p���V��"�c� g|P�`���uAIAM�.8��b���I*M/|�^��p~-�:�����R��d�)&1-mX��E��fp���S.��H?
��17g�MK��dvpm"�s�����Q#[�v�.���b��Y��F�S��u>
�9@�"��1!�,�k���F�y�a�E��������&�~�Zj�����t�F#���I
{��|5���~Bm:��M�����F���]��@�Z��$e�T����	%#��Z����a����kY�Y�,#��v"\�i3ZA���Q�Z�5)o�E�7��D���
��%�2�`<��mu��#+"���Z2�v�;J�HH>{�
E�OG��=�[8������p�YR"-e����+��m����z�_X����A,����c(�(�	��%%��� ������.��w��x2�&AM�P���/�0%#��Zli}v�7���g����y4b�mw��[��!�l����"G��"�J���$������+2$�"�3$��L�m��i\����	^���������o�"A������O��M?���e���E���Y��1�\)�L#/RC�d��������txs��I�	�>?�e��K�&����`V�b1�z$�`�.91��r;k�D�DZ��p���R��F�$��t��Mt�]�"��x-5.�ga���sN*�����@�>�E2)yr�-�2�(�	���1�����qyw]n�u���� � D6�B��U�2�tY�=9���B0�����b�D�jzi����[�B�����=����eE�����y��3g!]�%q�)��x#��)�B���sB���+�RWRZN���l�14����S�iAx�s�A�/���e�63J�m����h�>����ro��*��/O������n���[]ev�����i��������_���%��� @�?:;�N�sT��KNs���r`����?���N>�t�*��[t�5U���4l?-��*J(m�q����B���P�P�0�JA�dGp\)�[cGB\)�2�}d������ �W�����!���vt��Y%�T��A�v(^=�\G'����;�s��dy+?����@Q-�J�U��������1�c-'�?�A��v���{ZR�?�
J�v�,�H[M��Q+V����P���Q���Z-�����&��y��*�+�_U�&LR[-x\��z��X\���]V�����,��2\��"t����X����&z����OkHf���Tr��������HGE[�9�:.���C���B�v<l�A��� R��v�N�uD1�?�(Pk��B��~�g
=I��j� XU
-j��_+$�|������+!���1E�V��F#�v�����QFB����i� �'�H�S�guE[���1E|V�Z!*�Lc�Ll�����x
L�bt�&��
)����<�"6��u0C���8��""�$?������9e[N�!���Qt�mc����%*Y[1�"��a+�0�b���L9��Q9�G��I)H�Ix��X5!�p������:����v�,w��s����
J��%Q�(�EF�����li��
�l���Gyi��i^L�t������(r�<��0*M#�D�HW�a���)��F���+�N�������d4�Z�::H������::��d�����',l$.=�h��L�CF�����D4�Y!ZH���k!������r��c�Pb���������"pO����3X�q���:m�<]YF�������h|a�
��i�IG��l���4�E�Y��tu���X��}�������Z�v����m\�b��L����eE�6�2�v��M{����� �����K3���R��6��?����?�-8�&��VN��U=�fU�N�82��|�t��~�>h+cN�������|�V��V�vzR|1�Q�x-v<Sr�gG��Ow�>`dx`�l������v*}��:~����<��M�{�^���������������t��F#��K��*��6��zn����anx-$D��t������Q)��gc&.5 ����_[0��)�jg�TL���F��Gk�*���
zIa']r�M��b���-�5p�*L_5��Ls��x�p���64�]�L)��\+��[�q��������?����2c�mZt{�<�c�]�+��c�9�K���N��J=]r����t]m��h���]��%sD)e�G*'x�x��b��������.w!zY�Y ����R�i4�t��.�c�k��B�Z��������*�����@��%���1\��t�_r����.v���.��W���_
��L���a��^R���f���%<H���A]2�	��(��Q�<��C����c�%@��?����H�.����Y�-|k�4zL��5z���H0i������L]r"����]�	�Q�y `��M�qZe�/��%Y�H�?s?Zp�o��+f�8�]y�^��?n�>��V�<J��,I`'�����c�L�?P�|&u����x
R�$B��$V����*��:&�k9�SES��}dzS��8�H�V��7��IS���[���U}f�t���<8��G{U�����Gn%��u�����JS�N�U�I��c��wI������J):�<?.�0���
�H�y�]ng���P��]o�C����Y��/��$����h���H|���?4
ld4�2�����������cU��-�d�Tj!IH�d)�D�2FQ�IN/ �����D@H:�������0�+T\��������T~P�.�� ��IsFW]�Ls�`t���e�)/��-�+ �*
cp�r��q���q�C�y�S��sW��H-�I�
��[�����4@;���iQ�c�eg"BL�9��Q�2Bn[�����7^���*���J�*;h5V����������N22-���gP#�v�0�/i��U������e�&��1�K��v�g��en*:����*r��H�3�f\�[��iS@�8&�&-u���O�:%$F��B���H<�Ikd�^��K�1u�����z=&�>���*mu��qG[9������v�����s����f���!��w�<�{�� �"+g�#��i�y:�19���M��5�D�-�&n�X9�^�1�GQ�]oQm��R^��
����c�t���\v|��p����D����$J �g5Q�Z8}�E���-��B�ex��V$i�=8y`�I�����/���T��g��=O{�i�����{r�^�!��������B�n�i���E���C�P���������
�t9YZ�]�<��U/GE}i#�������A/%N@��,��s��S���];���_s��
����"T��A�����D�:����-+�M���{#V�{X*��rZB�����#c�
=g�zp����T=2������j�[��s��a� ���Tr�.�yYK�U�O&Rb���y�2*p����k!iP�������!3�E,���89g��Y8��w����?�����x�J�P����	xh�5l�����������GF��<���6�
:0�W�2t��f���lx$�I�N���$k~h�����D�=m8��2
..M�y����& ������,Y�:��L�������Wr���W{�]0�1_2F--�5od�O���@`E�/b�s����f�G[,Fx�.�P�'�K;N�c��o�s��/��	zG�����n?��,��D�W�&JE���)q����a�S����w(5���5M|�zR��A1�$�����������J����GN(U-J��lKK��t������c.�����=���j��Ri��:H��/bc������h�Q'�������\i�w��$�^������������m�Lq[\�5����So_A�zv�[=S�V���RC~���2��G�:*!WHc`�B�������^=S�W�H
\��H�(�^��C�^:�1r�>xc,�s�H�2?�L�B!��W���	MR
��+�V��Ez��G<j"ITV���GB:VX��:�B?9�^�
�r���L�b"#	��\�49I;�~����t'-7�B�� rL�-�A���2G�'����_�cBv5}�\?�������g��!u�$�_!��{�ZL]�d�=�\<���0
l��)��(4|�<��<��]%_��_NRx25���/�����{u����ocb��NDH=Ma~�RJ�V�b/�0�0�\u���@�fB�f�Bz���1	?�WN��K�GN"��r3�����[Ud^�	�J��	��Ka��K��z�k���Z&�
�Z�����\�:����E=��E�^6�M����^����``8��hE�K�@�����3k���=�,O��jf��A��@�V�����j���M�����#���^��wZ�5�����k�
��~��y"�4����=��/�rR�G��Z>�z`���]*��!��0(|��E"��70���o�?Je(�#x��j��Q���kb�ue�m �����!��5V�t�k��}��3�u�GB�
����7+������?�/ '�b�:������'#Z�R�(�7������:MU�N(�}S~����t��G�@�m�n}2�E��'�J�!"0^���s�6^�x,D�V60l#��I�e&G��##Z�E���t'-�!�fkT���cKLUI��JW���Nd�'������xZ2MD61�T���u<�����>9�#t4nj��>�S�;Z�����j���2��d��0
��7ML�l�?HmX���@�r����������g-o�|s���pq>��[l+{�jy�[��������?[�i�
]����L�y�^]\D~|,�lF������\�a�'��#(����������W'�E)��;K��L�A)%�q.4F����]�oNf���n
�i3�/�MV|$2�d���x�?��J�q�U�c�8
[��f�X2���a��
�����;�90��D����')�:��������w{
.
z�]N������`��m�!����Q����	*p������AK�TrR2���I
�#�w�aeP����s����"p���Hi��n^�-�Hsc�����^Y����.CT�)�(pgnk��=7�U�]h����Q@�f5�q:�.i�������A;w�7d���9�m�4��H�k1��V����
�k�
��~��K0����0�������)����-��f� 6�������A�P�������7��T�-�<&��P�(�S�;���d��2�/NN����JRt]�=s�]I���P��h���6PfY�
�M�Ct2�}}6V��B6�����/��V�!�M+��j��rk�>��P����y������-'a���{x���*���R��3�0S�%����3����eF������Wh���-�,=����C
��780��j\j���6������+���<�u��+�"��cHK���b���t�4��]~�k��#^�6� �-���.#\�R4b��Nx�������z!���3�����0v*0t}��_g�fx��6/����S����k%B��
�uQ^�X���QE����i�AB���G�Y0��"�y������9��X���)n������@�V�6$�������*�����T��d��k�����������G���H���c�.s�2����7����;��2M|���V2����D����e����[���B01�����Ih�L��n�{6��o�#���V��_��4%c��bj���d,��r�?w^.0&��y���������_iLiP�k���+{����6���O$'��P�Y�K�Z1���E�fL�w0��K[���0��H�*�b��X��5j�����U3�����64�V�6DCQ����@;md~[D\Z�5z��>�l�������y|.��6�S����gu��1}�K2�|%.�S�9m�[���d(HZp���$��� e$������>0	�^�
<Ql7�xdIZ�v�Axc�7�$+�T��S����&����4�X'���H�xt� t}�V����f�O�?��R-S�~I4
���D�s����iG��9MF����i�7��}y����J~U��[��:*��Nt�v#��_��\<��.i�O9bv�$v�b��d[�<?���c�GG/NW��Oy���;99<=KcE�fRf�Z�.9	�IH"}6H�MWx��x�\5*�h�|�#C��R�X0��F"��[�����b�r�Qc���*-E�%T�@he&.���h2'-�&��r���{P"h���w ��U���J$����rn��D�>+
���R*��������$�d��X�v���R�X0v�7�B\�t�P�
�hzPB��Q���%���AIF����;x-v.��7c!j*q����`�x9�� �����Cr�6*?!cGLmt��t4�Q$4�����l�(������>�B�`m�\�2/+��%lg�o(���:FC�(1��h.7�1��Jf�
�6��O�~�#���y��L�{�,��fJ��CK����1'��BW�D����`�o���$��$�:�Q�\`�y�*��V�9"��R3~��cJ����s9(�}zd�N�7��*���b>����<�}/l5o�H�T5?����d+��P�N��$-+	�,��5������TB��C�d��6g)f�f0�����4�R� �b�|��F�]�uZ��4��(gc�~X��]�o?���.������ri�����T�l�M%l����`hU+=q[!0�[�VJm��(��B�g����	��/�v�O���]���Y�?��#��)��K��6c���o��9���q�����Y1��!�������GrZJ�|<�`�\KJ�L���-�D��/�CYH���J�a���i�9E�[�DL�`�<T��5 �����GJ�����1\���KK��P�*M�fm�i�+��z���<Ve��*2��j��(���c2��#��@��[�yv�d\������yv�a�iQ���:��K[�6E�d��%�]�Lc�K�!	;������A���;�jovv�)^�zc��(�N����u�4Yg�4�k1�Ze�^ShN}�k����\�(���~����4�CE�YS#n���C�������Evs(�
N�YTa�\�����]m���H��
Z�\DP��`b���ml�;/+/���c��������K�.9o�����z���P�9W�b'�Rk�b��+���xSJ������E��V<q��Q��z�����RV�)�[}�%����_�����W��D�:��������N�.���k�#��]��A�P��E%���Z�gT�*��F���Ip+������J�]m��r �V	nN������\���$�!�����3Bm�y�(�6��Z����@_V�%�:X�H����K�1hv:�	�/�AW���Kp��!�E��La�������@�W���?n����Z�����+����fW���n�Q�6�hEu�i�mG/�#���:��?��"�rAk��5����#w��o�;��������}s�eR�@�9=��?�������?��#�����+��;�/�p������1�W���v��5v�G��q�
���7<�������SR1���x�>_�������%����k��;��K�t{6�\K���+�����k�'@kJf���<�����E����?���N���C����������8�=�����(\�������~�3y���3���gW3~�z�C��`�������W?���l�Az�Q���a�<]�����'�'_U+������s�a������dc�)�����i�=��XL�[k�nCm����6/�n�:�^��^��n�+�m�~��q�j��^�����M��E������l�,����;Z~��������>d?��<b���x����m����9��yz�T~��n;����QQH������,1Xl��
��cx�����a&+X�[����������R�:���k���?=^��O�X������������g[�k�!����b?�����kt���a������3��l���E�����|?^)�:�Q�����5���w�>}����l3'A�Z��a8�Y����8�����S��/v/}?�{�_N������nh�_�j�"��)s��d�����h�������7^�A����`:�?	F��$gl����QA��~����jK�ZZs��������\����w��I���-sV��d#�Xu���7U<��������Q}.+���������+��4����F���d7T+�w����)g'K�S���O�O�nC�G\z�(������t��:���^�^mwo{�}gk��h�k���v:[mg�uW�g�&2n�k����o~
������fc�<:�6��T��Q.�����i������g��
����2R{*d'���
�9������;����<�t"���|.	O��� [�E����s��n3v�M|V�*f�:��K��_/�C�:N��(�8-��NG����:�o��3S���t�K>��B��jgl��ns����%��L�.�&~y��j})|R�G���������l�tv2�[���kO �i"�7nS���:NC�N�(�����H�@����{kOf�+�'�y�T�N���
:w��@�������D�z}!�����/����{M��
l�t��9�PLfz������>�����/=M"{��{z��bU��>
�zdvo�������K?>����I��,�n����7|������%:���2�Qd0��[��{�n�+u�[������L��Iwne�8��@.��sov�I���h���g8����=8~��%���=�>�4���t�	������/v���)�	��~
.��DW���}��� ���\}yD:�g��]o:��G�iw�����j��e���K6���*�;��pN��{��I
�w�I�i����u����W3������~��~)GSc�N�I����,�C���m��o����5
�IQ��;�������{��m�{�������o����������:����{���������1���s����EW��\t]\�^�6_��K7�S���qw<�����x��S����|��hw��������=�"�w����w��+��w�a��X������pH���w����x~���B�~�����f��/��:7������w��~���e�����6��������&�{?��__>����g�:��
����gh[7���Yl�&��Mw�#C�Ob\������m�p*����v���^:�w��u���v��H
���w+�����r���O �Sr���	��	��_���
.>��Ow�����S�W�^5��9�����^V>]��n����za3����6|c�.�����Zd���]�}�����	�~U�tp����Zx��8�V��7_�]
.��
�9��}�yR��i��1��� {��8���l��r����w�_F��c���������h��k.��/��h��;�������;�c;��P���V�=^������^o��U�v�]����\aN���.-��^u%�v���%�,��*K��X&�>���.iq���:5��U�
����G_~.��������_v��3Kp�][I{���%���+-A^��B�|N+N�
u�n�������a�_��"�s-�0/��i	��������va�(��X~��@c��������8��������&�����:�����N��3���j��{=������};����T��{���A�K��������������{o�����
�=��d��1�_�Y�~�V��:�7?�+&�e*
.���~�
y|#�
�F�$���2aK�����f�|O�JA�����kO��R�Q���l�����b��|rCa��\����?��H�''�o���-"�7u��I"g����!���`�W>���1F���&D-f u2~�f^S[b�Y�{��N9��"�,s�f���%x�c��2rb������f�B �����C�&r�d�h��:n�?-��o���q�C9�����/��G���Xgc��(}g��YO^�������*:�<�c�C/.��D|��K���	���S�l����s�i�^�49�4����;���_V}XW�0x�\��_3�������\��?��_yq��(r��e���T�@W>:!�?�Wk9���d�?���n�������dys��	��Gl���������xk�x������%��j� A�J��0>��^�{Nqb4���g�:�5s��+�q��X,�a�/��,��7Kf��N=�}�Xct.�\�#��c~M�p����^��0g���Y����G�`x�����)������B�+��:�����OG85�����qp>�a��/b���m����������D����x�'x�l�������3.�
^��K]v|fE��Tq�n���\
p�&�x�s��Ot|]���`3c~���~��?c�	������cA��$XX����<��������'������C������4#p�#�}����Z���	�`l���+�-D��4��7�}x�S�F���s2�
��Yg�"f� V�&E��R!2{7H8u��%e�od�8����^��hm�$��L��h��6N��c��>����U:@b���.��l1�.���'�������+�d��ZOGC����g����	3�c1�Y�f��VG'�t�'H��1`��9Oy�	��R�|�c���1�K�PG�m��S�)
igKY��4���2i*��DH:9����:��%'O.��Br�hp`�}������b�)Y?�$�f��0y�<�di0�u�����pXD�<Q��/��xk�eakD�{-h�	���`Dt����������O�)�b N��,N]!y����s��h�~f��{�Le0��o\�K��x�|�4��p�d�
8r��/C��J
�%V8�

rIYR*Mh_W�}r���
N���6�"���3��,8/�\2���@�M�#��U�+W|���.��5�s��xeW�W� �4Xe�f����]_LE�]���,�Y^CB���S~xK+��	��8'�j0��h+Y���$�H��&�����)���b3������� ���b����`����84�'N���
b��
�����l�k�0��u>F����<�,e�b��]��`�%NNa���m���a�$�r�/N6N����2}#�OG��1�l�+^��0n��\�9k�	���|g	��1v/�m,������T1g�8kO����K7h�)��T-�}[}��i0�f-C0�b���|Fo\��kA�i���&��X���0��s���R^��L��s����b��z�A�<�*�k�MN����>�T���W�sK7����l��`<J�h2����<�a�v3X��������6�����������B��GNL��g�>�X��������c{��%�@@�O�z� 
&�.�7���$p��{��k3Yv>_K�%'dXP��1���F�Jm__C�ss��>�j��_d}:����^�:4�i
VeY(�k����u���_���"��,(q�4�X-s_j|��lf���pho��~���!�IS���S�)�B����u�8�hp����Ra�d���Q�t����/�?� 
v(�I.;\�%�x����������������H��c��AMu�e�'�����]�;��t�)'F����&IX��\}LI���G)����Yx���%N����(\��������[��"�D��S�<9t�����	�M�s���b1F#��Si�������kiNWq��g�l.i$(����,80}�|bqb4x���>;}����������=FW�x�-$�L-���l�O���`���M��	QGH\�{�XL)=��D�~�,I��z6����T����/���oW�m�<�w5��i�������o!��{�`6���7��9���v58����Tj�#j>�����v`!5��M��h��d��a��&m�����z�� �,�����pW��&o� uH+���/��&�w��%?�]K+�����Sv���������fWC�;I�������S	�"�s�R����r)C���{�:J5�������*���s�K������DcWU[d��������T��=
��R�H��U�Z���{n����czq����J�:N�G�����E1����#�}I����S)gn�81�l��%T����m���u������<N%x>�����Q8�>_�i��jBO[����R�z�C`�������O���������D]�.q����t��1�
�/1�I'J�����&
�o.�������P\ZU�B1�B�?�U�8Ur`�l�0D!�'����G#a�.6�"���0��	W��A�)��L���ik�[W�25+$��[���<��s�����O�Nr�����~���s��jKJ�"S�6���Kr�Z9�V��;���`]�Z>���X%(�D�/���������5yk����8E��"���&l�-0��[�0��������d�0���\G����#�9m=��j�~�����W.��n=���@��?x�:h�uqC��._�����1W.��W���[.#E�z�����W���Gco&�sCn��J.<�Y$�o����d����{i���.��8Q���[������'%��_lq��<�av	�?{g!g��,���8I{>u,�y1�x*�������K���&T�x�vP��`?<�,$ ���G�Q��Q����p�k	7����x�C��@
�����e?�Kr�-�}���V���G��?����vy����}�����L����
y�x�W�S
�|`$b	�|���!9�T����um;�L.n���<�\p`�M��EA��c�K�p���;=���K�rd��h����\l�+�����GB��a
�Sk�;Of�M�
�e
�M.B��tM�w�Y����&3���	�)A�����%�������bzu��{��%��io��������r���
���AA���k~Gk����t�G����_��
J�������Mrt@�q��9c����8V5��v[:a}{�����u������[�
*T@@2�\��Q'!,>�c)��Q�������3������c���]S�Q1>:�r!	�x�P�-�8
�T���U��J�mGN�k'�@�9M�1h�E�����o�d7�o��p��33������3��1��P�N�T�A#��G�Z�\�B����qx	1A����l*��4x1������J� z�I@�u#W[aT>�]���
���4�345�������������H�?��^LG�{q���������
�}�p��q0���S�[*�2���K|YG/1������<@�B����8zc���!TZ[��8���m�Z�2
�*'��!W��S~�M�1��"���M�Q���.���O3.H��������e�����A
f�i!eMR��D��YH�0�y.^$���������������N<���
Gm|?������L�_�9|~��������9^�����
����rt���f	�u�q��������g�F�x!���B�'�X��(�
|�>Q��`���;!��S��3�r��ztJ��R9��8���c��7�'o�N�NN�OO�x� ���}
����D�����\�g��A���^�/���cq`�7��*q��AY��a���]�SR�oYwo�,:��H���D
-�)+n��7d�A���B���<�3q��(��V�`�(s!@�tT�l+W����������v��M���$�t�m9�x���G����<~��q���EW�"������t�����/���[P�o�S�\�p�.�LA��-N�>�.�*����7������)�.Br�����������Nvr�k��l�'{�S0YL���^�W �����18�
C�4r�A.(w��c���b5�xjG�����@^.}��D�6�$w:�E
'Y|���Y����t�L��`��eC�B�k�n:!/�����~�j���P�K���������!�'Zv��W.[�b�]
��0�=g!d� ��X�~�����WK�H�#,Y���1N��T��N���+� ��2���d��B�1�7]L�y0,E���b����������)B"��P���q�d����� \L��c��o��� �)=O]��*�cP�A����C����K!�2�����!]/�b���%[�ZoX+ b>)Gf5���+�p������W�0�8#������d�J/g������s"��Q��d>���8M|1�6��z���5�0�g����'(z��d�����0)�N*#�w��cgR��p\�$�wTFq�~�K�2���")A�CJ��)Z%3�V3��h�������r#oR��1�!�=��NQ�
��Kv��/=�Nx��*��8����FyIl�0�("\�N��/�Q&���K����\���t�M�
:��.�=	����v��r�1N*`���'�_<�|,���*���Iubp:4�6��I��W��Dd�R������Dt�����������U\����4r[+���	���V0-�Hi,���X��	^�0��&�J���?����j8P�+�����b�~�����)&%_\�yFXht���,�)�k��1��E���JRTJ�}x-�
����:}'K�����������o^>p���`�����D�*�|s�0���-[�]�l��W�Z�&�[��+���Jz�8��JO��N>��'R~B{��$>h�9.pAp.��� x�:zI>��o�;��4��9:z��`��/���xt���:�x�W-����oXG����_�V�
'����a�wu��xl��Om�����Fm��N�Ny7[���I�u���]&nY��J#8..#���2B~������j�R<a3������I9
�TZ����^WD��p��W�@��KZ�}�h���N�L��kI���Z�t����^|�n�I���i�F�{�EW�V��lC�
bu�fq��W��59^p`Ecr��F+B<��Oq�������Fh���6G/�E|
�<|��]�4.�d�:�����LJ���F�.��}3)�+M��Et}5�����>+�j���b#�D�|Q�QB��������0���Y(��$N�Nl`�R>b�dQ|�������*�-Hv����d6|�}��R��r���L����e��}��f�6����Z�P�N��I�����#�|;�^]�(�q�u��P�1�a�[��`-�f�
����Z7M�����[�HE�o�"��.0I���P�X:�qYH��'U�Q���B5N�NL�\�XE�A3n�W#�4|�p�Nv����d�8�������/�������]�CwJS46T:Xt��gIi�VQ�];t���h�Q:d_�?��W����^u*�������R��]"���q��:�#�e~/��P���	��B*���2�F����^�?d��ES�d�A�gn��I�q�4D�BBX��9��~1?�I�yxp��_��&�Z���G������u�y��z^��B�K!W�R\��~P�'s�6
�����	Z�����q�0�0��'��@�(�%�*@x�kG'�ar���A��_
KxET����8���;:�3�v"e�<6F����)��I;q�:q�������@����z�=-^������WEn�Eo��\8:&�i��T��p���c�����DWL�����������f���1�e<(����]V���K��A/cx��?�)���%��r�����5Y������V,��I��.����l/���:�/=Va�E�D���H
����B�1�����C4�v�h���Sxw+yV�T'Z�;:�#Y.��p�nf��d~B�M,a�2���m����g:q$��f��_H�mv���m�C��\���{�������l���x������$�#Ew5�IJ�l88�C����/z��$�L!�l���P�#� �96�$w��=�D)G(Z�����c&eg#O���s���;��I��t�����s�����J�L�����0&e)�%�f��n���E�Q��u7sUw��K��lD/������d]�q�����LN��A���.�I)��#�*�Z��t?��,WL��A��{Y�eaP�(�H#7��x�d�@�q	:d�>����j�=/��%i�0QW_h$��7 ��OC�$;��������u��N(zAU��W4H�f�E�C�7I�����b��C��������9"���|�L%���/]��Lv��k����b!�{�T������m������t�KAH*Z�[h��s��eP��)N��MT�iW����\��L���hj%�~�#�8�z*���������j���A�/3�"�t��s��W
>"� �
�����:������:�
���o]��e-o��T��
����1)*����2�`�f)���Vb�_��ES[�����A(�t����$�I=k��������w��L�We��rnm��m�#?��Y:�"=�$�U���>;������9��V��a�����Z�a,c���?������M:���*�������V-������R�h�-+>�z���������9$������~bW�<�%�zSK�/�{�&��r*1�hb$�3tY�r~(m��G�P�cEM@���k������C�J%3���X�����E��Av��)	�r�<����M����6�&bSlp1��p]1�����[68��Z��s���
(�H��*�;=!��J��T��6���f<	�8����Cd��l����P5J�� 3@�A�T6����/��t�Y��.�_4i�����{�`o��"l��b��dpI�WE�
��%{�~\�F+B��0Z\�"U�4����j����~��Un]�����MkD�Sg�v4V�fa�j+*y�L�yiQA9�?(L�K�L�k�m���<��VW���%�Y�i��.qC��^����[`1�Dz�9��B��7~��O�S9�j����e]���-T�d��?~{t$�l4}�I�/���4`����E�cSo�?^�:��'h3�~����4Sw��Nx]�wt�g����k��������������_rl�O)5�'D��Z��t���II87���O�8[�;<&%��y�)F�.��1)���)1���=���+8_�X�^�IQ�P��`�S�X�M��>��	����6�cRZZDIj,�Z�Z<�����8Q��Q6��R��F�t/��b���%;�%R����������.���������9<��:�����^����q!�l������O�����p�==|�Yj^���xu|�����GNFv.��G�qW��P��K��F�T$�g�����_�n���|c]�H.?���M�"��:�|~[�
��x���KA��-H#���SW�wqg.0�t�E�,��_�|qi4��^���%�r��og�-�X���v���F�U��Qg8�����l��{z�JN��d�I�]s�B����d	��B���C-�N��
b�s��1��������-��J�����$x�j$x6���[����.^&cE�A�;�FN�n���]��\���`LX�c~��Q����j����0Hq0�#^�����Z���zQ��u�*��*~������2>��{�yLI�]zp�J���������E��(��v���Mv�� ��Rs��E���*�X��$�g��zvm��o�e�C[�������5�A�I�>������>d�������D��[RV���^;�j�#����<���l^�����]��U�gR��;���J]��mg��Y�z��FR��-�mI���q�,�=dwZ�m'��*u�dw�?�j��	d�R���6X��M��D;��l��G2C���r���C�9���������<[�������'�d�Q�`��3���.�D����\R~S�c*�W�{|���0�Z,���|#��!�O\�
�%|O���v�TI7�o$e��e�Ox�Zbg��a���&koR��h�CR�@Z���~���*��*��E\1W���$�r���D������I�:p�$sLE����}�����h[�T�N�A��K�m���}@M48��Wqo�+Q�y�v�� +��u����G�6�_z��t*���&?/V�d�i��pv��/�����~�-��5X\�� *Q.�A�a���x���G��\��:���S��.,��j���slw���x���J(!{�{�+m�u=q4[����SO;������qV5b�4;C���iD
�����&z����*����"JO?	�����l
d�6�m#�RJ��������Ch9���'�/|
�!��6H=�2�{!��x��z�=��^���������� 
�.S���P���Z�w��b��;�Nu0I��Mp����7V�P*6"�T�#�&:�2�'��M�/������]��Z��l���A5���%d%��N��r|K���D�AU&��N4��%6�������L��k{���4��*5�=��p��W�|S�����+������C��u�:6���(
�%�$�sz���yK#`�Y�9��XH�������1����8��*�lVu(�3^��(g"��8�8
�^�7w���?��~
���������3���D��#A�#�I.��.�Qy��-=�P�IQH��X���^@@�9�C����=]K����!�z�2���c�h*��Xc�F��1|��]����m\������|E?����9=��u�(6�
��I�T���"�BT?��1shC��--��?r�`�CH(�/�����R��76O�7
k�#g��%�J���6�v��j�7M�9�i2t��6�.>��MFqR�
3B�{����+JqO�-��I�������j�������M���J�

m������"�X���������|.b^A�����	���'�B�Ow�7�=~>���Z,���������+f�f�g�W�H�3��6���N��� �E%Y��+��A�)J2��x�$����x���({pQ�!{}����FnH:
����!��Q�X3��i��$z�?��i���	���m^�z��t�m�r������yIX@h��KN�i�KV��x�bJ���+~��������
����hD��Lva�,Se)���Ww�6�)���N�_��z0����6��h�w��F�:m|v���x-�������''~���N�:�R�x����r}�/uH�|6���1�$m�;6�+��v��������`"�&_sS��K�����Z�=z�S����|�=�Q<o�����;����oC)�T�>�}�'�V>*b�viWW� �i!�:�_
����_Z&xT��o_
�!�����"oN�����Gmj<�G�&+�v���o�5�L|r����/�Mv��k�
;
��y���F��~,������-lw����nadw�B�G�B�3�������i(���j,M�D�bF���_����w�x=7����G���t6��$9�]y0�mT�:����;M����&�+���p���tp�$F�u�I�������R[�$�~��6H4���V-���#�������!u�q�m���mce���u�f��c�,�V�U��>��^�YX����w��c�Rv{q}�K`u���d�/�9���/_)u>de�����������o|i�-��;��������OA��6l������q��Ow|o�<���h�M#9=o&@%����`���<8_�xV�>�s^XTRaTF�\��m�&P��X<���H�^T�S�6�u�{�^���$�W��l����$��x��Eq:��2�l@I�������.�i9�����2^�?OR<EC?�	�#!b9p�q�4�{��0����r������D9�_�idA}�����|
��x��yc�����
a���&as1p�������h����G�a%]�|uy��QqnR�r���o�)���G�p)��oq�����Q�H�wp#e_N���������@�8��8/�Yk1�(&�yw��_OO~�d��7�z>
xI�#�C��
��.T�����F�@����ER���.���x-�
�^Ib �_����?��Z$�`������o�_�|
�^��%�O��.����<,�dlAZk�4���g��Ya�����=+����I�M�-���|>O�$���������/+
y�;��3��w$r
&��"?lF�||
b��=�-j����&N�m�/�����I�HX��|/���K�0��NB4�S�����LIpfOa|��K4Co�X��@�S�����9J!���v�
���|�]�S����{�,����4Z<�$���v,(�t�4C��`J�������"�;_��������;+���]lKR/��&+��&+�,��M��	f/��:�h�9n}��z)m�}Eu��]eh�k{������:_�d��R����+�1�%-��K��]L��G���m�Fd&m���(��a�1���L�=9�����]�y�;��� �}2
`Y�M��u�J�������.��R���jQ.it���2 5�q����p��{�A�-!�J���v��j){6y�+9��qR��%Xc*��tI����k1��%zV��M�mcu�d�[:�Z��0���O�Z��y+lWu��7���h#r�^�A$�	�����I9���Uu3Z|�)���[�a���Z���E���q���7O~z�yjJa���G�966C����>7��>}pN�(�,g��=-�>����}0�k���k�}�����>���]�{dg+P�>9[�B�IG�l�g�x�d��m����_�z���Z4?�������`~$�zH���+^�j�\����$��%��f	��)2R�jCeJ)C��}z��r��}c8Q��{W���^���#�$���-S+��-�^z
M�d�	Z2��#Y�F�G�):
'��C�i��I������r�i"��x�@YK#�����Rt:&7Lw���.��V����d�M��o��'_��8w���l-t�Sn�_x0|����(�c�bv��w�+/�� �����}:2&�r	}���!�9\��K$[��m�����|��W������S+��rN��q#���fA��;�y^��m����v�S��DF\��y+8�>���n�y��1�'Y���m�����O&)�L�F��u�x-v2������"���:���W�&Kq�mj�>H��b'Y�6�O����/� ��9��A$�=eA=�Q��ZX����b'�qz�@�85n�i�:�:��������Sd@N��b�; �X��)���V�''���
%I0�����������2i�0�/p25P-)+M�Z���� �^Oq^D��.N���T��w
�A{�h4 J����o �Fg
p\8�x$�������[l#�MV����2LUl���,+�#�1��$:-�7OFV�|�����x������WG����WW��f�<&;���r?��(YU�}&�+��'�P)���z����R��h0��m,��J��v���W4������
��q��8"��Y�`	W�0It���-�����i��)��to���S.N�
!�#|�a�����n��*6��m�'�5�����`��#m$+�b��B�z���������_��[
TKK�)��x�@iCp~�BVvX�s�$8����_�H����9��`w[q��{[,��X���s;|���g�{B�#�a�����2_2w����r�,�/��/i'x�����������P�`t`��(����ub���2�HV�"�g�<��rv��e
����$�Cx!e[��}�����r�QQ��uq��@P9�QD��q���g���N��zq#N^IUC1�Y����'����a��3V��?u{�Hx��9�~ZJC1����U4�+Q|����1��n
}���/M��K��=g������8��+m�uD;�2������T�Jh�:
a���,�b��T��+N�m��8_~[�;��������uc	9�������i������GG�3w�3	�B���]����l�� N�
ww��������+"U?^c��`dHg9�CZ�3�8�`]�-�]��h.$��c�*���B�%�N�y�D���
�����F����vP���<p%,L����(�}���i����H
�b�����/�tL�]�^��p��8��#���`�/�I�G�sv�M��Q�����#X��n/�r}��k�89�G��8�F �Rmx��"���h���Z��v7`�%�Ue��
*��iC�o�����!V�+6�������u��"# &�+�o�^�l������{�"�
N��1sr
���cz�����t��'�7IZ�v��D�:qK��%
g>(C�Y(��T�
�#���:�{���8�
h2�6�Zp��
���V��$7)@��F��E1T�|K=D��,���C�F�br�Z%�b&�(I>#�����b�T�8&�����U�~o�E1Gz�H��H��P�)���2v{.QU���l�O�*��t�����uh#D�-�����:����k%����<� E���iS��nM/<)4�QL���'��h���1�R�L��k��|.�B���'��qVK�������O[z�`Ga8�R�\�d��/Ca`�#�Y�������R�)?����l���q�Y;���� �
�f�-*W#�l������L�mjPGj���];�)n���B���(���L8a��P��.r��
��A&��`eF�d	^�
r��6������MWJ�1]K�������K��T�b��zS��0e�����uw�E�3
��b������J(LN@R��.�����,5�>�6�txE�����j�M�=�q�$nK�7v����_�:i���U�#��\�eU}��t���pAD�|�"	?V��7(�J�������nss\�z�lt�d���������=�B�E��x���n���<�������n���O?��D+�����)Q��|:��&�g�!������E��Y�n+�Z_�{�*xe�R����b�e�!`*f�����p����9�*)��IfC��X-���V����]J���5.��;�EF��`�I������^mS�G2i�H�)wg�8?M�c/����h4���p1�N��q���j���������J��,f��i�#��"�mH����Ie����[!^U�96���`�81�������:,��7O��R�^����73����Z����BHU-���8��������'i���$-�"r�\.���A��|�[��S�_Z-�E�J�~�.�u�L�dd^���&=+������z�v����l�C�(Vx��������8G5q��];Lg����	����!�����AB��	��������
Z�h�=��l�f���oZwZ2��\6�/W�������l��b���a!}�G.�_A�m�Nk��9�p}�'��Z\"��V>&k'���oF.� B�[���K{h�\#�f�
�f
�:�����x�������E��I�P.�+�NJ~��!�4���
j��XI��R�f,�ml,c\�L�fq�C>�$�>���XOzF2)���lE��J��+C ������iI�*���B�!-
��Q(P!� HH���)V��4� 
�<m���`�H��DR��R�vf��	!��&�E�:��(��
�������a	Z)���>Vl*�_��Pj�W�Q�g��8��(T����
�vZH�!��.9�J.����|Y'?L8��E�{����&q����s���ih�7� F"��YYG��x����c�cF/�S����Z(�#��5�[��f�������4����k5��.9����zv�Y��/�)��Ep��&H��$�F!���Nt���T��%#:��Dwp�BFwA�����|hMt�������8kYP��B��7H��p�R�	D�C�R��pI����rdQWQ������{�I� }���+i&������&eX���������*�R;��F��I����,u��X��W��~9�#g�������`�g�k���ga����G������k��_\�f���`Y��n���c�4
������[-0KR��`�v�y��R4��PDY�8��J���uA�*�Pc^��|�*������^'���C*���N�i�p1�B��,U��$�V�]-K��9t�1�GZ��It���=���G�W��V�S�?�)�A/�{�y���H���
��g�1�.
��s� ��K��ZJX��!4E'��B��!�TM��v��_�)��+uA'����C��Ftq*�XQ�$+����� g���9�s9A.D3��!�M��s�EDoj
l������Dn9%�� �=h��=2�gqdl'^���{tte]u����>p�#�B�z�=w������j��9�Qo��l���\oFK�C=��E\��0j����Nl��sgO;�YY3�������t&*��V��:*�B���x�XO�G#���*i�Xq��^��\�H���e2^s8�{	�]F,_��ELp���'*�:��$I��,�&K������1���S�%��H�9E����5��d��3Nh�L�M����g�3�^f������A�j���{����X��z#i����c�L�%V0�Ma����|@lG��[��/k=�^)�v��4��s�MGc~��_�ND��Sje,~��#�>[d��I�����k{���E�-&hJ"�	�5���qFAZ,��%�L^�����) >�h��Lo�+�]�����j�u�Z������q�?C2�\W�������y6:��4�KE���5�h��
��z�����Ry���������s�88��s�:���
`�PV��D��CPU��;IN���
�b��1g�Z�:|o�K�)�N��*���UVOI%r
i^�������ql�/I��bO'����m�b���,�f"35�roR���gK
.���ix-V3;yiLT��r�� 4Fj;D�H��6�jQ���=c��%���{HB�������}4#V���cNc�+c��g���7�fn4J��u[E=N�����q�����xu���g��� ��Z���e��c������0��$���������
>�NK�4��s��������Y~�s� ���`�y8���M�����&E��������M�����k����9���R�U�$��!t��B����<��O�K1f�t��H�|V2E�63���5�[<�S������"���Z%����''�O�'?���INc1���l#t�
8���8j �#�N�����m^��pn��G9�Y0
������-����g�4�Ej���/�h����)�Hl��0�X)����t\x���*�Sbl�RP"S6�	1)^����jL�Z����	�	:~{D$��e+H�.&�\nz��!�T�Z����hDO�I1��7�R:%_�1��[*���Ba�^�j�^Z$bM���
qKx5b8m7T~@/6���%��="qmj�,(�i�/k���M�7�F2���]5xev#��
W���=�p���28QT���4�?�cf�O\{��=N���j�k�Y�����5��I���p���Vj`r��w��b�~��e���������WX������5�K�u\���N�vc�kNi��k�n3>���&���U�E��B�@���uD�P���(4���
���*�R0&:�'?���^��g�%��c��4��C������s?=��2����6�)`}��e8��	gG���!$Gl���C.yE�b��f�`��N����D

���,
%���8�m���5���Lr (�L� �8C�;>��$rIpS�M��i�Qi
��l�I�'B�6� �oG�|��!�����x{��'���8��c�� U�tyD�(+	o�.�!X�j�j���#�*��6Y
f����j�.���9����tN��,���
_-���Q�CP�(�7�+(�T�L(����Z����S�>'e"(����c��4@z��*y�TI�4d�8m����T��b~��x
���b�V6�	UH�:����Kv�6\������d� �V)����2����	�~��}���&�����k���i���������_^.��%��`B��q8
2$����K6�cR�vX_q$����������G���|�F��e;�5h�6�&m��5M�6M��--�G�/�����W����|�>>{{|p���q�����o���V��Z�P�@,���H�����������A$E��H��.�����+E��3d�H�Y����3+�c���9Rr2�f0/��F�����;�nvSigW\���S��U�����:��L4�$#���H�Xa��)k�=$3��@�(����E0���3e�#I]��u��/U	��X1��#���-��I'�u\����/k?+�n����������I����7B'@�.!n�������
��>�u��G��ID��Q�qB��;^�]���, �_t�<�(>�c?��dd%����������+���|V����fJz:�������h����+H.�1� �|�`�������������������.��3����l�i��$�
#`���t��U�D�tFGT�"X��.�LK�U��
N������������4�A��
|��$��?�
w���Yu/7
����8:���?��9<y{tz������[�O�]���M$��M�3��~�MX��~r�zH���8�X������@<V���!*�s��a����N���n�[<���!�(�ZlpV��'fgc����k���,���"�D��c22��e.���'����?����� ��*��D �����!��k����h@-�	`��b:/"1�Q8�a�����_��$��J����E�[z��s�C�1�8�����g|M��!�����`2k
�)���K
��9��������K���+��Dv�zE���b?���D�G�3��1�'B �E�sI��g)��@%���5t��|e������K3�8d~���x-T��`c�T*6V�a#?�����&9G���l�^�2P�S�57Q��)�>�)�yA(����O�����J���8%��%vIv����y��R��b�H
���[�]���M��vB�\�Kc$�39I�q��+c���;�u��P%-�����Ne���R�hJY�� ��Q��`�M=k�1o+�\��R:�Ag�V�AC�:d�.=�Qh-d`�Bz�����<�B��{*dl��C�z����.�t4����	 z�;��<:BMr��p.�?���:9?^�K}��C	
�����t��[*�V�9�_QO=g�d�l�p��
�����@���m���ag��2b�M�88�����b�I'Q�
�J���`*uJ�23��}�+)  ����c�1�/0�T����t���< �`���N6N��`���sy�6rAV��#��u��"�|��_���#��M����J/0����X�l�\b�_�Z�uo�'8x��M���G�!8}���]�f�E�8�D�L_8Q3��������x^�RN6N��/`w��6��
��}O�
S��
����:SMy����Q!r��<	��T���S<��q���r���JT1vx/��p�%���h��[~K���c��LJ���b����W6�K~�A�!�(��n��q&�����!N�������yVM`��WQ����:�<4�-�Og��������r+����������?\����O�?��}��5U���4b��+r����������"'�g�B�=W�]����������~^nr^�v�d��i�b#@�S|is�9�
���RR�a��?u$_j5
E/�4'QC@"�!��\�4rt�����&���}�YX��O���w����.��H`�^H������������K��&�5�H��a*�(�a8z��]�F��C#��f	�Id�h"����5�=p����i$��C��q������#I�����4(6���`�!�q���w�;�J��&RPz��Di�UVF��Wt=��:n���u\:�C��q��<�d$�+\-������K�a�>���@�VW;���hsr�O����ECoz���P���`:(C��e��bH�f%4�K���
���Q%i�Kd���%I�x"�w�����d�����E-/��8�=��"g�ME�q2��E������`��+,���i�y�v���3w��k)�qr�a����C��t���A�hmg�y�5OiQ'w����5E�[*����`o�1�}Pa�i���ZE�h5k�1L�RUGq}]y{D��j����42��Z4�n�c�l%����dPoP�eG(m&M#W�3j�r1�.�����m@��d��g}���@�V!��#�����df�UYz�
��"(�U(N��SDOOo�4���2U�7��AL�o���g|���'�����$��PDL�wZ	���5�5h��F-|�k��%,��P�H��!>��z���`�V�@@���������Z�9w��ju����7�H+I���0x����@��x-���;
p~��h1C��a:�-�:�My)�����d=
@9�i�r<������"�m�pI�<Q
k�H�;`[9���i���l���'�f�����@D���d{p�d�d�%2h$��y��=^5W��t&�M>+[�YX����F�fn u����[A�4T�����S1aV��0�#&��.#��(��\{�����K��
:6����]rV�e����eEAp�!���X4����h�i��&��'|�9�~�6��W��(��N���h8�-�
w�u�R���c�g�Uj}��������y]Q[�i]��rKjc�-�d0R�J�3�bV21�6V3A�r����b����&4���l�P���W����k~(����m��3��[�����w�*�[�dh�������y�"�1�)���6Y]�x�2G6�P��������-��g#�����iy�&�l4���or������BSQP�W��8�{���_>L� �w<�#�+X\i2�V.|&���9	5�[D������������<:��7S6���r�6�yu`��������7�]yW�\��G��KD�O~��G��������4�z�LM�X�E�]i�>�k��p9�9	�5�4�a&e���*Nd)aQ]U�	!�������Bg�4�D�����S+�f���=���r,I_�<]�����Sd�])�>����q
!�O�<�����������;c��.����%�%� SN��r�H����6�M"��:s��&CUO�D��	�b���|��y?����"4~N��0�QmW;�����a8���,�\
.���E�}�x�~y�k�l���4A$X�D�(���i��M����"�Y���i��a�� ��H�[!�=z���6w���r:p�\8��b�Fl�z�����������@gu�zVZ�y
I����������M�k�IVh�.������#�/�H�*3
&�9�49�5\���[���"��^�i@]�d����OC�Lr
�����*9J�irlj�X�LI�<����X0V�Hu����5�he�������L��U
��t2+i�NS���z&w@�j����u��M���/\ZH�S���NK��"���4:����%�����7�:��9=r�jO���i�vQ���d���6-w<�B��Z�������������������w�	�L�9�����9���g���o��9�hc~����C�h��]�i(-�\{�h�8wqRP5��JN��?��<��l��,0����8��.�rr=���w����uh��;�~,\�:��������~Y0���_�����,���tC��K����=�sN����mQUL/`uH��lzD��v�IG�65��-+�(�)7L�#1>z&�J��Mr�I��`�x/���4^�����m�q��2� ��
�+�v�����$]~��M+���	��i0/�h1�|�Sv�q�x�l"��@m�{S`rm�/�fL�\��L����* gt�k���q�aA�.yX��'����`<f�>��\,���\F3Z�B���?8p���2�Z&ub���Z������)�IA�~���z���T�hz�?�|U�<���r��[�t��������94�����������f4B����N�������4�g�@	����r>�j�am���:+�+��5��K�5���m(n"�	�2�f*�R����U�{d�,��q�<�uM��w���{%Q+�G������;t��:u��M�Q���������u��mD�����8��=)I �0���A��Nj�SKw�K����h#.R�\��Of��xS��q��M���E6�P�
VRSvLRS����7N�Q
��l���D�G9��h�l�G�T�=����"��9�\u!3�^Y�|j�(H*�cYTS�:qgK�F��AjJ"X�`�i��x������r��:e�_mZ0e�FzG�e4L�r;��yS��i�����y�����;����������A�7������S�,����4���
!��>?<�t���m����a4:��L\~��S&%=&�w�_�
�`#M���M6�)�^2�D�MG5Y�+�I=&���$NI������E;V�h9��J��lq�L��]��c�E�3$�����:z���N��B!1�q|��h:x�����`0�mk
���"�$���Pa�B;����eE@������0=p���������q�"Q��bj.���E,��"����4�(8C8��y0�� �F�%������d�4���)�B���e�%`���$R�#��]�W��[����Ad�7����0+��0�!�-�����L�u��Q�h+gF�"S��(C���M���.g�2qi��K�������k��&����@,��8�\���������q���M�C9����$����w���P��-��b���:h��j�����T�wA���L�Oz�^c�k�6-�u���lF3�w�a�P��{���������y1��Q�gF�K��e
��,��*�ll5�r����N��p�
"��g��=���r��.����-!5�4�m�����Q�#Z��=t���n�S~���
�@B���b/a^�K�
�3���2��E������?�/�n�uR�~zk�:�fz�$9Q&a��q�Z�XJK��jK��D�u���^���&uZ��"�����d�����7�p�.�!0E�	E��d�
��l'��V��H��q��
'��)Y8����%Z���Y\PE/�n��zAu�x��$(���dC���*^��9���Y�P&��0�F1�#��90z�gR��.��3*�dc��uUv��!��04|��<��HA>�J���6�F��b%�W���(ai�A��$*�y�N2�'-r��^������Bzab"�|������
�o�?���j��X����
F�]2��sCq�g��F�L]��8�*��������Ci<���u����[�6��a����^��J���>m�MuW�e_����������|�����o��)	Ic$��.���� ��J�GC��-�h1����tc�
���F}c#�`���=�Q��jn�pw�4�V6�K���i���#�K�l������H���{N$�"�0sWY���0R#��&��-�<u#����������N����t���	����V�"R��+����F���i�>+��ejY~��\EK������-�C��U��k[+��-��&K�W��F�1K�ox�^��)�v6��4�{A�|�EP,:�����"��3���l��X�aH�hf�:V� �A��.�r��~��"��� @Hy��|e��(����o��HG �i~���:��$�i�K�.���6
������V�Z�%Pm]�W����R��L�������L�*qWn��S?YYR�=SG�|��k����y�Edt�P�qYVj��Q��qA�m����.6:��^�0�MO;`Q�����������-�h4��N���RBg6������S��x�N5"�t�AAi��OHv1�zE�v}����j��'�1�f����w
@@a�����p���+�d��o%�����"ig����h7��I���� %�E����2_�M���n�&�
��4��A��x�jmVI@������GF����|��%�$�}��F!�\Z#���8�+q����&���W���Ki�t=�$G(W��9`��� �9�m�v�g��~"���X���-mh&����!h-u���`M�F}��y�$=m��b���`^tf��������
Qj��C"�s~Sg�&m�W�����2i^�.���]�,��y���E���)�Q|3���A�Z�JD���� ��v��'��\B�����M�����;o��hYi�^������@.�c���k��������+��8/�ju���:;:�w@�Wd>0�A��Y���S+i�z�P��
��CY�G������b6�����E�9|���L�4�fI
����l+ty=��@XD���LmPm+�\�b 6��fI`��|�-E�dD������p9����ke�^#���eTxS��u��K2
���(G���M��\�����Vi_��6f$�]����Z�s�����CS]����n�>$��J�
q���3�<E�p��~����j�9e)A��YL�N�+�z�#y_X�������a�GNR��b`������|Bm;�D�v�#II�.�~���,=w6Xr�
6��\�<��Vb��
e B8��1�AD�k���b&���Y�3:�v�!�Z���^�4�X5�.I�_���Z5v��FIWT�E�:���IF�T7�ts����O�E������W!�7��@�V
~�g��Ug�NA��%�t-$K"��E]KH��jL�������G�5���%�n�/F0�g��!���F;�Qh�T���3���3��A�:��:B�*���2����	���H�����;��� W%+�,Aic<���<Z3��/���.�<Zc�5>�A��,L�������<1-�V�"5B����V�+����$F��r��Jb��?�y���g�c���6,7-��1G��f����8vx�wi���L� ����U���y3^>C���<uJ�N`R��x�j������x�N��w��	�k�u\�w!���P��o� �T,,�)���q�A@&��plA~E�}U!t����r��?�����������8�V<qV@h6��O����'Gi����m!�#�Z�|� `~���k�=���H=��u�#'NV�*���D]=r��o���9���>?���gO|���*���zt8�{=��#@!o�dT�����i���9���>�eF�������8m=:O��O��%q� �5^�jj����$���d�.�]xl��,%yi/7�m}*(�>�����^���h7�S��k'%:�!r<��S/����B��IB�@Q���o
����|P�>�Y�'g��k�c��f3:j��&����0~���Q �@F��a���S�)���,@x-6<;w�-��j8�v�r�������I2�gC( ���C���O�u��AH�"�2�mRe������'�M���I������o��j��r?E����+K�AV"p[	���6X��l+��7��Y���������x,����A�.��f�oG��|���p�����5Nf���&��q����K&N'=+��&��Z�4~A�ID�HG}txrBZ���Z��3jV�w�E�w��������s�7�����%/~�!E��7�q�K$�������0�M�}
��HG4%x_;[XZP�J_;5��:����n@��������,�����{�&�D����:Ud�/�b�`5�e2���> ����P�����w�����o��5W�%H���A���4�r�6�����q{�	n���=�"\�QQ&`�������)�[M^)r���R��Lli�O}��l0��#���J�Ad/�����Z� J5:��o��G]&C����n��;���p��FY����$�:�k���l��!���.����*N?���ki{"���S�g|N��F kKDQ���g�Y��V�
�i�*W]�hqDH�M��k�k�����+o��A~#�I��3b+�����E�z��|�K����������m�� hc�p�U&��o�n�.m��C�HdG������_����1����Q����L�I�
��'�������o(����a��Z1�!��������m������4K����)�Hs��H �]F����Y�����F\��:�M/�V�v��lGY��-!=��o+�#v�D~}����m\���t��l�������G���I�����h]���_v�#/����5.]�a�s���[E)�����Z�1(e�����[z����4��
+�=�p��>�H�<���$�����#��5��2�g1Sg�C=���D[02P~�z�! �X���!I'�BFN[�����X�i�L3P��a���j�5K�B�`;I�o ��!����;~�+9���
���9�5����7����L<�x�n��B�Tf�~�O�c�o3�I_;w���s&�E#�H�J&�>P�V���nf�W��	���[J��=q�����?�,R�G��*�Xo"*�� Qn�	 �b%� My������=�av�6X����1x-Vb����

�(�jA����Qt���

�d� (�U:J�(�e>m���F~�G�J����
����4{.gf������]	��Z���h���]���%�8K?q%�dS�4��S[����o���"�A����� $^m�40G-5
U��?<@�M7C}��xV�#��T>��NX�L��E��Er�`��x-Vc�
���ji�H4n�d��mr�$3�m��Pfn���N�Y���c�@9�F�����]	���F��@9@�3��+���)?��r�<���`����,�EN���-��N�d�������B�dV��VRH�QN�1�6E\0q��O$��������#IK���*���w�����)���lh�i�({����r�Q)
�\�8 ���k���K1�5@�
\�]F�=
����ss�F�V��<����V;OB
��z@����b,�*��0h��A�'1���m%;������o�?�h-�8�U�T�a������l�����X���7e�����=����;�X�vPH� �?���4�0�����l����$wc�
�b\���)�Dj�7�P�xx���$��M\3��6 h���]��m�[��m"�6�������W�*,��RV�
�1���!0�4����1�� �h@����t���V�\������\Y���z�u�����I.���x����=INf��I~:���,}��Q���}+d71
�Wr��R��CdX^���>�{��`��~������
Z�2��Z;�������h�qO���$�6m�M 0��r'��;�T#���ZC�������!�����K�-x��/�NY�l�.�h�P���7"b������B�AX����0�K�,M�sV��\*i�rN�jit�`�O(y��"���l��D�����>�w�	�� z�������T���y!ih�y���|�yZp��;����k��;�H��������Ht��9��w��`_=^s�����y8���m�������i��F�)����C<J��/��|�����E��������%|
�c-i������*�/�q�x��hM������GA8v����?��^�����C����������8�=����$_&��/����C^�w�����������B�x�l���i�������,i�9�{�8T"�6v?����k>;W�d�����`�����p�4��������hv����`�=���q�^��������_0���W�6�x~������t���.$����mw��,"����������S}~G��<}up��������G����^�����_:;;OO����m����m�}�xg��x
6�
6�8KXp��{���0�c�9����_����x��z����|z��z$b
F|_�=}���&j�V�=�X�G�v�l����������3��l���E�����|?���S�4<�����$�
;�+�����?��n�_
2���
���*&w%�����������������/'�|�oJU74��/��?���;X��-����a~�5���Uk��/��f��`:�?	��$gl������~�����J�ZXd��������d�|�v��=��wKBl'���P!�_�N��ZHU%h�y��/8�o���K(�0�?���'?�J�?
co���� ��J������u�9�����z2F���%������"J�i����^{����f�����>���v�}gk��r�Lc�����j;[���@?K���`���l�����P7���M�&U�F����M����#.��{�{�A}_�����
��c�&u�w���\�(�#=}s� ?���=�~	�}����1��<��������nd��-{��7���A���@��<0�/�<�
�/iw���x�������R��`:/��(5I�g�r�G�W�o��:�z��0�42-(Vy�*V+dz��E;0�$b�
��f���u�N�IP �$T��r��Q�&c����?�:1�������=>8}�������Wg?;->g��6������\6N�8Q�'^��;��[E��<?bTCkA��k1�sr��� �-��bx�����A��+�8����?�^:�hoN��`��S`2��[c����� ����Q�V�����PE��A���0�x���2F�X��_�bH�N����j6�u���5;���7�#p�������L�^���g�_�p
�p�SDv���5��!|syc������hw��qx��l�s���y'&���b:���pr������r�o3[�tk6����6���������x2�[
s��i��*~M;���*e�������WCB�����a�'����1\����Vs5ZM�V���<����@��������kJ@Z�~��O��C����tn����m�4�@�9*�Zs�a
GI�9�n�y��M�.����f�,�����������	����G�{{p�u�=|����}s|�[�c����#?:
Y��"Qy,����c�^��uN[�T��(SJ���G�)=�QZ������=�0����uXJh������O�^�H�!N���_�2�/�l������<�~����^��i9D
��b�FN1��H����ED��=��������0�����T����Cw��tI�4�[�|��x��8���_&�C���������~�o��M��N^���xb[����7'�B[�H&<M*������ys|xt����!R`�JY�C��ch�;[�YY�p\�J��E�#�v?G�Q��hF����*[Bc2�v�p$��3�i)r���R&������*O.~����8��7$��o����H��F��#�`�M���c&J�Pu��	o�+ �F&�s��vzM��u�h���P>8���p�c����� ��l#�'r�M\�Y�/����}���a�U�L�������.?�c��[�ab��
*����U�S8���:n~PTg��!@`>�����O�hSN�X�������U^�����~�0�t��~�:Es���Kc$��QZn��o�:-Svs�~ci���.h���R�%�������0��r��Ya-�`��
v�c���������Y���8���G*!sji�_C�>�@���g�����~�La�8���Lq�����������#������-#s��g}|���C�M���22�5-Z�2mx���L��u��N"�y���*X-� B�*�%��R`A�7;~h�%���T%Ug��*��}�dh��I�!�g��=�v��(C/��I0	��<���G�C�Mc�������������P������F�i�$1U/�����,�=[/�#���x~�������!V�CN����
�Co
������>���q���u%����������Fb�J*WN�X]�����e�g�GG���7o���$���Ds�86r��ZL�P>@x�+��������|��(�>�,��2o<�fY���������lq�L���f!�!���-q����t�&�\����6N�){�)Q�L�lM���T�~:G����8��B>��;d_�j;��y�iV��/�'�'�r�<�������p�]�	��v�j�9�����t�(V���=�[{�wH�C�fH�w�I5�a{����M���Mr[\��{;�}_P�F")_��FfRL������a�w�����
9d���(��?�OJv����b�yo���W�s��tK8�OqWY�ZF\��B��M�;"��U�y���j��N��O��e������6�����=�
�gW
�!��n�(;yQ]�� ��t��*��ui�W�T7��]�J���z��%�G(���g\R���eQ.�I���\A7d���Sa�Dtq�x[�u������J�X���H*v��8>;9�s����WO��ivG;5���8 ��z>��M;mb���.���2�_<=X�x��}����\����r���Qn�� ��,O��i�iKlU~'�S�4��9g#�}���d�����"�a^���*�$�d���/f2P���E����1��T(0��ul$*��X?��y�Y��������2�yB����6;���%T9%;u�����������Sk����C�C�mX-��4��1�y�d�
��1N+����C�c�O�����Cb��\�����!'�K�Bi��V�<l��`K���$K.��W��|���"\3;�������%�d���_�������K%����r����zb�^K����q�\�9�!#N�(����@)?���.R~Pz�;��N�I���a�(#NF�����t'-��1����?|��7�����S�I�8
�w�W�C����xt��
�(u!A>�Jn���kU<�����I|P;.����j�A +:}������/�c
�Av��'���<]��@�(s?��N����v����������W�����4?pf��EJ�+�X��?��-\�,���� p����N�LS�U�da!����7��x-�a�n�YQ6��m^����mR�I'zG���'�(���;�;�����w�H],�{�m�W�g�6�Z��)��c4�	�WX����/���h�@4h��`BW��!=�
���Y�L\�n�
��;��P�b���n��4x�Jz�CH��Cl�b���\#�@v�������o��M�4��&������,QIiQ��N��Z���C��]�si�I�<���Zg� ����(�������;,+��V�/��%��gc~r���.�q���w2��[���D�6tI��2D�g������qQjgsA/����X��d�Us��'=��K�7-+��Us��)��Y��G����L�j��'�������Km������&� �G*o;AD�(�'.���[�.����������?�� �����
�nAucco����K��������_���������a��o�}��.r�1��Z���K��bX��L�2R�l����Vn�u���������`�����g�9�5�1�T@\��3��{��_%g����
U���U"�fz��%gH��|�#)����~}Z�bx���z�]��M&�Y��%�o�Z�=5������
(�E 8f^7i�%P�� v��IKQ�)�op��������;���k!�����Z�)B��M-w���������_���;|Bd�X�F=Wm!/$�-$�-f��s������>�����z��g/�����IL�x?���_������8�m����
{�oO�xg�$?��W����i��[>�ys�=9:x�s�\������L�����s�����@��'_��WP�����sh���V�[�h�B������y�w�������������r��`���;��6��w_��a{Ze��e�+>�����������y�������O�/����?�8`k[;;�tvv��>�t��;�\&���������)Xl���,��=����1_�|�o�����x���0�v�N�g����������X���X��#����>��]�'W���(��8��������3���4?^����]�~��o3ijEk�L�;�2xW�
A��?��b��2���@�l�nv&�!�X�0��$������3�;y�����>�2��3�T��9�5�!�?.IG����Uk��E�z�Y������������������Y�o�	�G��Z��,��h}��OA���O��+i�j8Ha��|!"S�0��|�.������u�O�nC�G\�(���?���z���v��r��_�������6���X?����XCV������+���o�d������{o�g6��C��n��Ia�h�����P������K���v�6l��+K�I����<��7(�g-��!������W���YX<���=b�]8.�D^�������K�h�L��<�1�,���a��c��.����	^���l~�g�i�S�t�Cu�e-fw���������lWz]�`���;��a����+y�[���3������u��Y>�U�f\��<���5|��+���X{��-����,�k�s|������z`z$��.���p[\�y9{7S+,��Go��;\N��o�����������_-bX��q�@_Z��^6�m9�����w�_F��ci~��0;!�L�y���������<�=����b"����6���<�m�uj���~o{�V-|����v�V���V�}w��`�����.a���������E�`>;�ii�������=������p�;��aa���%o���������]
�[�����Cg��]���������'{���V5|�w	�o�l�4�_��������������,��`�'��q(��O=��2��jQ-�d��8�;�^;��eX��.���4;��?I)��R+��6p���q�����3�v���w%�e��%z��i�C��7|9����E~c���[���{C���}+��'��V��3Q}���_����>Aa��v���v�!<��ww���w�~ dk�C���}�xK��%e[��(�!�b����Jw~��Wn������x�/���Y�m����R]Ph m��D�:!<d��C#	�:�8�<dN{�	������7	���F�4���yp�}Q�rig�o�y����72���(��C~��G
tKm��V"<W����C�E����>��2Ex�qZ}����W��-8�x��l2�f
�?�A����R������/l��������Oi���A����s��}����5������JW!2�ucG��c�b��i�����+��|���>�?<;4��\��.�C-�����������������3�G�bB��~}�|�������6��#up���86��ec3��q.e|?}��c�	p�_*���b�S~�%��uE
r��
�������'.o	��� �a��������Z��T�n�t&�p�sE��O��"�z��a�	�v@�"^��7���g�D���h8f������(�fe��p4V�^t���F���
��w1�!m��]��K�����"��f\#�L�t_Tvp��v�f�g4r`VF|NC1r���{�-�8���B�~����C����<��d�RI���
�%
�e;eC�&g�V=���	;���rF�AS����
Kv���G�}2�3���B#x�_�V�?a�9�����!H����T ���1�m
�������&�_��n�����mt�l�k�]����;W�d����ZQm'T[���������m)�B�bukT���6i�,����K�nT����iYo\�YAnJ�N��1��#�:�L^m��D�N.
+�hvS����J��0�����i_r3)��L�I!]����Rxb��xT���JR���U�E�V��nU�\�U$>V>	����+�8���1�����?�r-���=4�=���%��Ia�2!+w**�����������0����
��x��`ZP|,k[�(^h[\���������n�*Y�Pi	F��^����s�O�pG���3�������{����y���T��vJ,�#�^���r��w�*���6>�n#�.��x^6N����N�������+�V����8E�)�����',3�n\�����8�����k���b��N��,�2�{�o?�"����]�4��@f������3�L����
}�6�m^�����������E��*�P`k�7�P�n�f���P�EF��K.����'��&���$h<��Q�XJ�V~��cR��JRl�e��Y�XGI�(X4�}��Y_���7��f[���
���W����t�]U�\�]�w�����JD��"/.jP�%�D6:��f&�%P��RHU�7��F;�N��St ��o���������������-�����������g�������rg���|���^�����H.�1[��c�D�p����'�1[�c��H�������Mc�tLb�|�h-�qZ��8-�-��F�Z0������`i���J�\52�Qg-Fg�cqY��&��E/������,����S%Tx
�]�����d���:d;��A�#� 6/�H������dD
r���d
�i��n8^���)��F�UX��\���o�����kq�[+-,���:��XT�j�u�y]m������*"��U�>���R�����6p�o��:5��������F���>~�_~�?��_������?�����������������/����?���Wk�����������~�k��W���������?�������������?��������������������_���z����|�������������_������/��W/���~�o�7�c��Kq�����6��u���m�����_.�����_�������������_���/���?��o�
���^o������;]g���1��w�������l��?��v�����(��_�����?�}�w?��R���)���P���{����3���n��Y����*��I���@5��R��jZI��E��E����d���R������(�A��\����j�Wj*2O����O����Ku'�@��}G���dd4Yw�����_�����l�w���(�7�@�l��]=�d�+��>������A���q��j������R����Iq�S8������@e`������9_nB\���Z%���J��;�A�16i'�hE��
�k�����{m��6�^y��djmd��������~���4���\�����'��V���\2l�q��P~�O��Z?����*���7��y����$�a����s�U�����������(Q.�(����!���x�]z�I	�R�
e���a_���:b�pO�"h��� ��7|�Ob��������rzD)q,����������_o%]�
'!�
"�Aw�m�������;�"f�'�\���������i
Q��8��\b�^�W������hS��pJ����3_FQ���i���U��d���d!x�7��Y�1d#>�\D�@ip�t�x���9?��:�\B1S}c�?v��>��VH����a�Hl����C�{�������L#�I�y�c�i'N�[T�'Co���
�"�#P)��X-�����>���#����5	��1�y��3��+�$:���h`���6�,1J�
$�$�f0����*
�U#�*��E��b�S9��>���)N����XF@�`��
KgDh=�3���H,*A#��7����?n�
6�C~~�.��7_���1�6�X����w=��1eR#�W8���%L�C���|
�L�V���Cx�6�7���\���u�&]�tz�bW�F�R9����U0����Q�bI�q5Ak_r�I��&G$8P������`9��\4��k6� �z�SBg�*d�����5��sXs�b1+�s��K��������b��^�%�����9���pv-BZ��p�����h/6����qx�����Zg0���<\�pj4��rj���
���K���4����9����.�u,]r:����m��^}�[�m����^u�\LG�{��������Ox����-���j����K���&k.9���n_���v�������Z��
�5�g)�38 �F��Pt����Z����X�b���w������N����~T�-/��G��� �	�LXQ��.� M
?�a�UC1���6)�j�|	.Px�=�!�P=\��S���bEeVvi��K+����'�E�#��IYL!!Z%�K��B�m�q��ec��D�}�|����,�o�}R��[.-��.��:����^���5&[����nR��TX���;�E=����B��;����Pv�r���l@J	�.��l�G��O����o����k�"v���hC~o���h\m?���� �o"k�r��=~��G��;�}��2~��9JU[_�^G����}�X�:���wU���S�r*$���VK���S�
|@��x-t�^��.�/��g��$M�YD�Ej�����z|��~
?��\(����87�th\R����
m�
�!_��=�����`��sf.����L7�o�78%�-o~�v�m�9x����Y�%���C�8��-s��n85�&�H���Vh��d�aB�p��l�_.��<o]2��A�����9�}vr���������G/���
����y	���kq~�~{r���WMe&���������{,�%��L���:~��R�Es{�m[���<%i)��DC������|�OG|u�{[i�T�`��V�:`���Z�����V�D(O^�}zx�������/^��L��Tj�&�N�*�X����\�w������,i^��I<\���GI~;���������jq
�8
��J���BMGE���B-��w�0�s?^��8f���[ �	s�C!�<Jj�=���t��B�dNdv�jU}QU1)!��[���jh5��0�����!{'�N���C����@6�����������Y����-*[��z�1����b,`�8��hX��"[������=���q�*=��Wc���G��LE�=��W�'�z��.4��o�I��B���xST)
��=�,��B��nZ�]{�z�Z.���S��b�u5���O4YY�w)[�w�M�H����V�B�o�-Cq�q�6�#N���p����P���P�P@+�k\L/�y��B����
���<�0/��L��|��vpJ4�(�6�|�����!�Fl|����.���7��)M���'�SN��u���:��p|��Ho`��^y�KP-�����������	�bA$��F	�Q�z�������,�f��G;���8��G	_� ;���JnQ��h�@�cgN������YyB|&(�n��y���p���c�"��7�o�Z�f�����������'�@b��?�D����>��q������f���]�|y	�9Q��dc�������l(_�����p��� �U����R���b��p���Ji�w�?@OS��]�!']IENL�vf�U�Ce\er��P�LR���<� ��NU&�sM��VA�W������}>��8]
��o������]�D�o������ RU*��.�B|J���,Ev�����f��fs+YN�W�ni35I��.M�61��-!f�D�fZ�*k�k��L\X����2�
�S�N�ST��t��]�&m�'iZ6�
��M�#�E��]��9�g�m��}Tt�ly+����I�f�	it�`L�
�[����u�W�d6t����T'���D�r�P;�iTh3LA�RP;�iTX���~�
�	�s����)��>8�H�$?_c�������V�,�i�%�����s)�O��{�;�O���p��_�?-|V���5\h�������"��b����k�t$9��:%�������OA�6J�f�l~���4��IH������"{���%'���e':�|����e�l��F�K��~�j����_�3��S\zK�I��,?2����J$�%���N��$��Z���8�KP~�����%�4�����T�� ��3r�K�FNB<i	�s�I�%X#�S ���pA2<C!��� q��(����*2�����|�>^��q�@q=�WY��}:�B!�����I��:p�>�e��x3d}xR@�k�F��cV��<b����}��8�Z�'|yZAb8�������������TW��"�$�"������S�a�KJ4���E����������X�f$�����R�1� ���7F+k��� c1�Z�{]�-t�|T��X��uIi�0���7��y9����wS4DR�`����9�,1��������H89��<�69g3��W���@0$k�/��q��$��6{*"��L����u(���	�I��$f����2
bNn�'�8QH,��Z��5E��e���Xd���"�g�3N��0&��*�FF`x�&�;i���'W>-U+���d�FZr��T� x}S�B������@��������%��x��#�OFQ�������a����Q��}�5���k��I�QB�}��DF!���]}�]��*�P�d^��7l����O��Y���J�
N�
�=��S�����N]��:�}�i`
2WfV��_��}������B�- !������p�Q�F^���?��
���P���!�U*�jl46�V!��U*k�k�2�:�3�_\������Z�g�u-S��*A�yu�~�89�	��C�p�����Be=��*�-���dy�TtS�I�E1��t��i�|2�j6':m��a�dO�2�pNr��^q�;E�]�T~Ro8��H��_��S����T5m���}����,:0�"N�(H'�K7������a���,TP�6,u��mx+�d����a8N�����7/�!�9.��z		g��
��K�������&��5����G����@�I�����1wbK�]����&{P/m�P�u�^�K[6�|]��������d';U/m��-�,�����q����^������l�.t�}�����}M�0~$M���s&�h��&t����d��zod�|_���!��4^�h��2���P�����p�"����R�%<0?*4�.�a����$XZpq��3�V&�����bde�K�����c�!X�Wv����.%��~_�
jd7gE�+�kdwg	�b�MZE���F���k1�_RMR_IZ��?����R��aUUQ�Z����I�i(/'=��&��rQ}$:r�7�e������P�3����=d'��I�]�����-hNp������L������7���X����"�M�K��/O�Q����~a���u���<�5N��=���l~Ft�l��h1�Y���0.&<�d�5��:n�^�.<�vFQp>����i���������"s��<�c_��P��su��s�><����P�9x����)��'��B��S��^�
Wc&���?)��K��������
. Jn}����Hd�r����C�r�
��`�.-I�
�`��_��`
�� �
��A.�� @zA��4d_�����I��$��IS��/�4�=��4tM�I���p:�*d��jo4[])p�C
���Xb�
��g�UFv��k��Di�B��&x4�]yF}dSX�rd�X����S�m�J��<�������U�m�&�Ri��%�Bv��k��!�AK^�F�����X�+8�(M�J��"
:@���|D�N�2��~K������@�m�+�6d���;�Uk���bw��r~���X�%d7��;J7
��
r��z��&�x�#�@����)!�/����M�D���SJ�'S��
�>�x-vb��doa���~��	�#6������Z�W���O��Y`v ���Ksp�4h����dD!g���E%MK�Q�z�H��Z����#�4�d�bN�{�����s����2'R��	��G��yV.@]EJZ4�?���-��������������p�>�������,��S���Wh�:d��� .��� 4�L��X$G%X6,���"�m�HR��!��Q��w�G�K}gq�Bt+�.E��X�G�����E~���|�G�/�t�*�2:B����^(���Y@�o���]�����ea�������2��Jl����M"v�Yf����E+u�uOm&�����	$�UU�Ry�����������J<���=�:v���d��s�;v��{�9������Ab���%Q��F��9|���-���+� +����+�}�~1�*w0���z�@���rS����{���4�T3��H����h�3zl�*��[��?M��w:?�P�z�gB"b*�|�y���7
+-+ah%"�-���xAc���.i1r��}�@�^��*F4�%r�w�sH+�E���4��n�+sz�8�3���Qi�i�r��#������n�x~�e�����t�1��|�c�k�����$c����M~������r�����V���8�_�$��vR��t�^������+,<E�k�������a�������@�c���LYa�`,U����.r\_���C�E����:��SS:*�����;b]��P�o�T:[��]��L�a���2�8+�_�k��U8v��~u=srD���T�k+��_��
�mu������<e�@r�@�BQ��Gr�����|�(��(
>�)��i1F��kH��fs�N/8���+J����k��{��V���������f9�U��q�F��Q��������GI�>�m����������,�u�\Q:@�T���,���Q��
:��l�x��t��Uau�iS�D">4��*�4�fK,����f��,��c=����i���hB��w�'v���qWUu��P����x�Nz�t,!]������^6:b��)k�D�N���1:c�����h�m�P��C�����5a���3��}
	N�!�V�m]�9�f��3G=����\���(�s�A�����dlU�`�?R�d �����B��jhav
���Q��w~����>������g�1,���1�3�6�����N�k�����:��#��)v��q�rM�7�v�V�<����x>�3iI��K)�,+fy!���)���f�	D�/�"�l!�� �U?q��&k�	Zf>��v@���-����f>)�T�'?���V�����P�3���������tR�]2I��o���~�5�,��`u��x����X��3��Y�/���u
��>���B��`�1${kS^�E��LLb7{���fF���"���1�����U<�c���O��G���A4��qoi�&]wm�*�9�O���������������ks���t3�����Y��g�iFxe@�!����	��f���u��02��h,����H��D�I���z3���:i���V@(��S�SQ������a��/{{�f�o����������49�1B�l���!/~F^�4��$�@�h��*�63�v�o���(��MG2�&��?^���������"he�??�f�^��� 0��`2`���M���4�T7�:#m^v�x�|��"��%���W��9���M���>J��kD&�Dd�ID&�S�L���I��L2&p �^8��_vO��p_p�uw�7a)��Ls�v��	rZI�J	��5�0l�
�q[�.S����+��6E���C�����#�n�_�y��A+k�c�����VvX�he�I�l��������������4��E%��� �J
��'�0��Yc�OE������[!������!���_R1#������!������|%��p����!���_ �Y�g�l�S�������D�(#��ZY���!0x�� ��Cd�ID&O�D&�<E�����sy` ����������p�.��Kv�_!���w�r3�>/���#
�<������v_|r�W��>��U	�k�����w�_7��3����3_�9���G���?��K���n�3�'~N��}���?��G:��]�d>y������G�v�?~������pX��_n���u���}��7�����n��+��X<�����_;l�@�O��E��������[��X�_������g��/��:���4#�W��EW�����.�V�O���2����@�?�`8��� ��a����� ��|�!�b1�3%9��/��d�^:h\c���KI�qY��I�����c��R��{������<Q�hp����FZ���-�_��a�p����x���\��M?7N"���k�p8]�8������
e����n:D��?3�:�[!��������J���ip��Ym�Ryc�^,B�N�:��R(Go�R^������
��g4��y�����N���1��#���,!��������>�(������+��ks���������?��u��g��;����_�_���c7�sOo�������
����Z5?|�����e��
�����Ia��Y:
�����/%��H�����������<���?��A���|���:�������>�U���}��{D�O�G$� W�k@��ABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB���Nq��x
packed.pngimage/png; name=packed.pngDownload
�PNG


IHDR�})�A0bKGD������� IDATx���w@SW��2�";��"(�U���`8P���J��+��Vk[m�����Z[�8� �8����%.���aBH�?��P�2�M	��_���s��!�����K�D��)���_��/�������|>�H�_�Suu�����������E��\.�DH�-^�8""���!D�������=�;R�`�����������DYY���^A>��A��6"�����%�1���6�|�A��`0|||�T*�TH

w0����/� **
!4o����`���������!����p@�`����x@�<��P����_��/�����x@�<��P����_��/�����x@�<��P����_��/�����x@�<��P����_��/�����x@�<("�w0������~�mkk+�'��G1�O*��c���>�[>��/���������^
�����a��I3��KK���{OA��?
���{�A���_��������T*u�����������������B���r*����k}}},��&�<�L�����Tj��T*u���P|� �`�l�21 �`�`S[[���O|F`0S 50��hhhxxx�h4�O�����PNK�.m�Fkk���?�<H�?�������BjjjJJJ�C %0�8)))-\��N�����B��
�_���E�ZZZZZZ-Z�;RE�F<������������NUU!T[[G��


MMM���q�@�`�H\EEEFFFvvvnnnnnnQQQUU�;����e�X666������'N����BZ��/��������[�n%%%={�LAA��b�9�����b�X,ccc����iwB|>��f���������'O�����D"kkkWW�i����5K]]�C����2�x���������o�B'''wwwwww���"�	)Jw+466���&&&������*((L�6���w��E0Md�_@����c���:u���~��Y,������&}G���+7n�PWW_�z�������I������G�v��}���Q�Fm��q��E���R�/���p����G�>}������_���Ka���?}��p'N�XXXx���������_����f@@@ff��3g���'L��~����j������/������� %%�~�a��]�L]j�BaXXXPPPKK���'Q2�������,X����X����'���x�/BHAA��>x����e�V�^���[SS�7��_�;�������R����wpp������/�P(/^?~<�8t�������L�2n��G�
���rtt|����1c����^��;����u��I�5k�DDDH�K��������\�b����CBBp��kp� ��/|���{����E,T*���c���k������7o�Dt�������;}���k����O�����u�����;w��	0hA����r���lll�\���8�>hmm���x����G���F`@������7655�:uJ�/B�J�����uuu�7o�����W������g�3�L�Y�������c�O��w��,��@O����Tjbb��u���C�=~�!doo��'�����H$rvv���			d�	@��Frr2B����R���C�:�s>|��]��s!t��=��?`�t������wvv������?��3����{9����w/Bh���d�e���vvv'N� �A�	�/�Zkk��K��s"��'O��|��;wjkkkkk����������<y�����GDD�B�������eff�����9��App���#��d0FFF.���C3��/o�>�g||<YB3g��p8���$�	@����@����555����j���>j?�}��uDDDDD�H$z��9B������c��Aw����F]]===�������k������$����g�����UUUW�\�1cB���"�ttt������"�4�T*��������6�3���UUU�,fff��=KII������uww������"q���������N��A�x<^W,��?�����<66���#~�����g�����[�q65��~���*�����B��������	@�@�]����P����������X�p������M�&���
!����~������H��p:Lt��_�5]]]�?��h4''������p�����"��L���p�^����'�������y��/����m^^^]]Y
����={��f�����/"����B�W�f0������o���������w��9��j�*� ��\����G�Mb��������!t��m����/  �����:t���n���*--%�Y����k&&&VVVQQQd5����f�:�������t�����`�����?�����������������������;!**��������f�8���w�}��������{ .


FFF�v���m�, ������


g�����O���x�������`�z�i������/_���{�\�����e���h�����������o��������������w���d��!?�����/�K`H����:t��!}}}�Y��?�w���KKKKOO744�����l����������qg�_���w�r����
%!!��2HTuu���+�NOLLTWW�����n���111555�����B����f�����p��u(�`���bll������Z\\�;��:;;WVV��yS�M�`���������FFF***'N$~�;`��qc��I���)))������5����?������������{zz��5���>knn�������O?�t���s���s��������=��N�8���1z������_��_iiiYZZFGG���YTT���C���.\��;��t�������F���������
�_�^�x1Bh������O�^jj��i�B����_��1�������������������K��y�������UWW;88��;7--M�QSRR������o��}��Y����������7o����1c���������M�w����W��}���8n��'N���J:gmm�����������pbbb�����h +���o������w���C�{����O�8q��������������c��!$&,//�~�zddd\\�J5j��'���I�R�������***FFF�3���466^�~=,,���k���C�urr�4i��1cF�������8NvvvVVVzzzJJJAA����������H$���;{���%K����������>�������<yRMM��6SRR������222���B&&&,���������2��g��l6���8??���!���6q�DWWWWWWGG����o����?�����#H��4A���|��
����]�v���[AA"_	�D������������"��������p�\�P�RPP������������&&&,����������B�tn���e��)uuuiii����H��@�����|||222��;����;N_����7�����Rr�
�������g������Z[[���G����O����vvv�k���
R������4---Mv�/���c���6l(,,���^����(##�����b]�vM>��������������@�Rq�@,0�t����O�ngg'O�����aaa����w���qA�\����M�6e������u��aaa��O?��������� �D<==�M���)����bb����uuuqg������S�N�x���_������7n\DD�,��?
��?�?��I�BCC���"�455��9s����'O���;��W�q8

���UUU�q���O?�������MMMqg�[P�\SS��i���}�������;���I�&iii���u��e��g"�h��O�<���<�!D��N�<���t��	�Y��_y��?DDD�;wN���vvv��o

*..��������JNNvww?x�����qg�������{L&����0 ������������%44w�=z4i������Z�
w:��+�,Xp�����L---�Y0��cGpp0 ��r����k���s�����,��x<����,��_ySXXhgg�r���w��"))������k�g����@��7^^^�^�z������,�����{�rrrqg����gr������_?q��<XQQq��A�A���Gss���#�����;�;�@t���]�v=y����w��+O>�s��/^��2	����[ZZ�����r���|��W�|�	���h�c��]�t������������~{�����|mmm�Y4??����G�)(��`������9rd��
P|����yyy�O����r���3uuu7n�D�����������;��2O(<xp��ers1cI��kWmmmpp0� `���+��?�i���mN�Pd��`��=��������B����goo���������y����{����l��o����j���3I������y�W�~��IZZ�'�Z�[{�>^*E���l�������:,o�r]]������k�������3��{�������#�X�����������>� �d�d �F���_���t�Bkk�������~��e.�[__����~5uu�O?����#�_�&+��=��N&O��Z�|��R�;���.,]����L__�X"[��>��a��������������BSS��#����;��]�1fQQ������ryy����T��?��������'w(����w���x��72�F��_����W��������������a����{���e�LLL�t�����3bcc�G%6���_�j������!q�6��t�Rmmm==��;w�������aC��!����c�����������Lv"������L�?eY���544�=����.&n/X��������
CC������t�?����(JTTT�
����~���/O�8���u�N���'YOMM=|����C�����M�***�|��]�����`�������[�6��������$�P^^^������������]����r�m��!�������������Y,V�U�s;�g����������l6�����	&t����>33����_�!����a����8����I�^r���J�����7o:��������B�w1H������B����@�6�������?�|����\5"##{X���+W����e���N\\������A��h����R�
SSS�?����\�d2�y��=L:��b�X�.]�p8'22���!��8������o��A�]�g�������m��i���sppX�vm��=W
�����������^��e���Nhhhw�+u������S(v��B�����{��/�����~��[�B���]6u��1%%���R1w1H��6MMM�U����i����jll���g���������r��F�FF��
�����x"���������;��9v�X�P���"����!D���l������8((H�]�g���B�����z��U���---&L���=	�>�I������mK���wz��Bh���VVV��7�!��O�����/���@u�B�������[���+**�/��d�\Ep��D�~}t��Qmmm�P�a9q������6�uw���|�	B���"11���>11������]�cii���cGUUUuuuXX��!C���8K�����w�fffQQQ����K����-[�t�ZCC����kW�����$����h4�V^^.Nk�W����e��M�>����+Wv�+N�x��M��f������h]�����v�6\�a�>T
����l����
����g:��o���f�u���D��<<<zh
��_Yeoo����555���c�X����"��������***:::O�<A���w�>A |�����WTT:t��_~�����j���8;;���1++�;v������H$������8p�@�x&E"��1cB���=4���LjmmUVV����%���~�	!4y�dI�h 

255����h|P=�@L���Lb��<�8��\���KJJ���}����'v�����-9�e��7o�_���`~&����;2)..������m�������������0rw40���?{�����oj�?�@0��I�^����$��"��]�6s�LCCC�1l�������o���u���&&&���A�Lq��W&������K������!}}�K�.���eRyy�;���f��-����� �(��2�����_s�~�?������Gq���L����P������:u���w �������*]]]�)������B!q�$��L��������Bnikk/]���_~�o��DA��Iuuujjj�S����7?����� �_��������2�emm�����/����_�C��[UUw9�n���W����_�����jq0 	,�������qr���!����}'Yc������;�����'x
���R�T�A�_```EEEdd$�gUU�O?��7��V����o���p�\.�[ZZ���y����������l����s�����l��Y������'O��|�rKK�G}�;�Pe�����_���H���i�Px��U��T
�2u�T(�����Kee���X�&�Tjss3�\@N���l��y3B���������������4���k:ySYY��w��9r�������B�"��/ �e���s���KKK;����2k�,�G�c������������B!�_@��*����wy�����$.D4�9rd����a���$�<@^A��k���|I���SRR���122�� �'�H@.A��zzz�/n�:&$DGG���������`���W�l����t$�F�:u*�<�m�������/���@��%���7n\��b'''8���������[��0�d��+c�l�B��
!D�R������{k����qc���`���?�1|>������fgg�����$�Z[[�������C�MLLJJJp����2��`�[��������P����0KKK��?8 �_��v����V
�����;�`�������:�"�>��������mnn��r��H���I��


MMM���q'�+�����z������@ x��MQQQcc#��k�RNCC�J�2�Lccc�F*��������������������������wn����b�llllmmmmm'N����'��r����������aaa			���������{���ljjjmmmcc3z�h{{��#GJ'0�	P�������[�n%%%={�LAA��b�9�����b�X�s��=z��i��|>��f�����EEEO�<���+,,�D��������M�5k\>���BaJJJLLLRRRFFFSS������#���?��SSSSSS33����H$*//'z���(�x<��tqq�<y������9������


�}��P(trrrwwwwwwpp &�����	���������������T�i�����.Z��):���?w�\tt���oG�9e�www777CCC�PkkkN~/
srr�������������j�*SSS	< D``������Ottt��9sN�>��p$�����?�������`���HbG2�����_~!);v��}��>}*������ys��uL&�J������uK;�_�>|������`kk{��`Ux IDAT������������666


^^^�=��~ ��}�vuuu����?{�L:�mmm�y����/�J���=}�tkk�tv
��8UUU}��G4�������������5j�F[�n���Vkk�o���������{����*,1>|8�|
�������C,��A������L&���,,,���������2112dHHH�0R�������`0v��!��=��>}:�J��iSmm-�8@���b��p|||�tzPPP}}=�8������m�F[�p!qYOy%
�9���8u�T��6�����222��������H�_iKOO733���HMM���k))),���������HDMM�����8t��P(�����s��a0?��#�,@���J����UTT���7>�����z��9���W�\���d%%%�G�f�X��E(>|�J�n��Q ��$��������	�l�8����i4����qg!����������KKKqg���`����@�@�����p*���_��;;w���h�.]��%%%,���������������+V��S%�?��JCRR�����
p����@%%�;[-���z�Q�FUVV���k111t:}��������%���������\�r��K�d���/_�|������8}���#333�Y������������6m�,�4P%n������YYYL&w�>z����������S�pg������s����/\�w������w�^NN����,�$��r.%%�B�DDD��_aaa
%==w�^knn6l�|�;HUVV���|������@��,'''WWW�����~���vvv���������d5.
����jPj:���$�s����[��3FSSSQQq��a�^�"���*))gr��%''#����+�}����1B��o�����w��mJZkk�������������.����F�����&��� RZ�A���U�V���KaG�`��I����_�|��������������#;;��k����D]�~�B����Ia_�I�&%$$���r�������{!���H�^���������DV�#���"���<(�}���!�tuu_�~-�8p@GGG&~?BX�j���g����!%%%������"qf	`${�C���������3g���@ vttd2����h���qqq���P���
��]�f����p���%�%&&��1��{�cc���211!+������Ubb"Y
�p�����`MMM���W��������>|x������|��Md�� ����?Nn����[
�Cb�=�������4iRbbbmmmmmmBB��	B'N� 1��+�O�Nb���������?����������f������+W���1C��O�k���P,,,��yCb�H4v��������)!���|���D"��s�������


%1�H$��o���%�m,`�AR���tuuIl���VJJ�?���p���n���
�����K�.q8�ibbRPP��_��!���WYYIn�RUU��Z/���>{���f�_��f���D�������%K���Gb�����X>k�,bx�����s�N��o���266&1�H$�3g���?�mJHdd$B�����f�����#�&L���r���k�.3�9s��`�� ����|�����Z���%99���.$5%~�5v�X�P]]]��kkkBt:��...7n$�M	���G�>�]/�n�022"1��?�h``@b���������.�i4������B(??��a����	&<z������'On[���444$7Cee%���%GGG!TYYI��7����yeb������zzz$6p��_I���������#�A77��g���l�@PQQq��E�PSSBh��e�+V\�|������:**j��!� ��\����G�Mb��cee����������C������������B�,Y<x��[> �p��VII	B����d5�e��n���������^F����!Y�x�H$rppX�n�
��������������@(����u���_	�����iY�����Y�����N����999?~����BBB�����������;H����lmmMn��s�N���s/<{�l�����`XXX�Y���_?�����$�	p���J�w�}�������u9,�9


FFF�v���m�,�*((6lXtt����,�X�dI~~~ZZ� �0�+A���


g�����O���x���������������Gq!GII��K�V�\�; �%k��M���/_���+��\�����e�:�;K�$&&���_�z���w������w�^nn.�������d�y�f��������?�,�t���/^������k^^^<PRR����RSS]\\��9�d��YI0�?��WPPHHH���n���������G���ZZZ$~*}\.w����g������J���_ZZZzz:����6�������v��y�Y�.,,��>�x�"�DK�P(\�xqRRRff�,~����+
\.����B�$$$���k���]]]�tzbb���:�8��m��c����q���
w����e�o��G��������f���999UUU��"����I�&��������Bb�������;���B��;�T��K�pg���+=yyy�F�***����


F�1l��/^��B���f???%%����Y�����\���`�9sw P��������2d��~����d2'N�H����kmm���O�T����[ZZp����vww��������H
�_i���_�z��������Uly<^PP�BY�vmCC�8����������t8]����ggg���S�Y�A������������������QQQC�����p��,���7~�x�={�466����^�x���E�P>��c��;�,����~�z����3f����
���:m�4������/b?p���<xPMM��b�:u
�tDyy��-[mmm1&R�����	&P(�9s����J?@rr2qn�I�&�x�LRRR�|�r�fee"�I!6��}�vUUU&�y��ar/�2����k�Bc�������\�����r��W{{{�����i�E/^� 6�����}������>>>4�������r<���wy��A``������������'������������OOOEEEMM�u��=z���]��7o�8p`����{��_���E�O~n���d2f��c��	~�6�466^�~=,,���k���C�urr�4i��1cF�M\�X|';;;+++===%%���@UU���������CYYYB�B��D��������/kii9:::88�;�������W����������������>~�X 8::���-X����DB�|P������������������z���������211166�|B>��f��lvqqq~~~ii)BHMMm�������������q>x)�DYYY���III���eee!


+++33333��?��D���D/�|�R �h4kkk777wwwY< �_� �


rsssss�����Z^^�����r���*((hjj��tCCCSSS�eccckkknnN�Pp?�WUU���������������������F�G\�!���A�R�L���������������������"��`���+�������2x���-Z�^M�W��C��_��/�����x@�<��P����_��/�����x@�<��P����_��/�����x@�<��P����_����F�P(
��z���������t����~����JW��SV�pd"��E"� amm-���n�:����t������H$��J1j��/��"''��k677�[�n���RH�O����B6Y�_ 3rss�\��o�y������9#�H���]��_��6��y������6n�8d���~y[�^��3g������^```ccc��k������-311������3f�������B�����Z�JSS�����Dq8��K�jkk���������R^^�������K����+��wD@������������t���]QQahh�~[��$=���B�����������s����'�_"����_w��)���---�\�D.\��6���������`�]������O�`�W�W����Xnll|�����������mC�������������X�._����={vLLLMM
��g���FM�0���������\.w���!MM�K����y�=��O�>�������"�o{<]���������T�f���@����r���#BW�\i�7::���v������
�>#����:l���J�YVV��&�)����aVUU���/Y���k�N��+�] �������������CBB�L&B��?�����<��r8�.��B���m�r8�._��	

���655
��.�P(qows�������?���+�]�����222g���D���%��W_}%����x<�H$����rC���v�SuX"���?�N����322������L����B�6+����%$�����9B����mK��������W����[YY)))!�n�����Gz���A��%%%!��,�L��+W���B���MMM�����!�i�����������M�6�����)B������&<<<  ��{'E��w��K'� ��i��]�x��������f?~|�����q��Ii�HR�����+��������7o�t���;!D���\���:��x��N�������V���������yty����;O||�&��oMM��u�X,�N���_$=����SEEEGG'  ���'!}}���'����~������C����/[ZZ�����%����.HNN^�r%����hjjj������~����C��E4��@?���!�����m�����q�������Cn��',,l��E����������7/))�������'N���s'��O���A*0��d�;�5~���������Y�_��A�����]�9s���!��6lXPP������/M��
��������w�A
�`P��/�����x@�<��P����_��/�����x���d�O?������]����!D�R�?����a�l����;;���9m�\�P(�&M�y�&��@@��IEEE���B),,433�r������{��a��@�P~����[�J?�!0� �X,�����B��������W
V�Z����
��d�)�2���Z�lY�su#�(��e���g����r�K�R�����������*__���������B���S�L�ro�@Pe�������O����4m������R
6��-�<�R�.�����2l���m�@�B���Kq�������-p��Y�"�W���;�������sq�������������Vxb��+�TUU����v�)�N�7o���
�T����?q�5AEE���c C���6�@@����x�B����m:��������7�Pe��Y���������3g���gRTT\�p!�)�������+��t��E��N�����"�4-Y���!�������q�2���[�h��oiiY�h�,���)S�c����:@�E&q�������r�P��p���)Jeee\\���������	%Q����7EEE���<o���7n�044�q��Je2��������c�
��3�	��'O�dee���<}�4//���������������9������v��1�F���'s��������������������������=tIYY���������f������#G��N` ��D"����G��wrrrJJJMM����������X�!C��v?~L�P���B����������������466jkk;999;;��5k�����@'
SRRbbb���222������G�9r�HKKKSSSSSS33���?��;G"�����l6��.**����d2]\\&O����mnn����������t����W���l����������lmm��fE"��g����������P\\ljj����d�ggg�������s��EGG�}�v���S�Lqwwwss344�a+�H����P���������_UUeoo?��U�V���J�AY ��=z����
B���n��=�=���>|��_�=!4z�������Vr�����������-Bh������{���$v���r���u��1�L*����s��-I�pP1+))��i�����������={&��?}�t���zzzjjj�6mb��������p�o�������#�^hmm�y����/�J���=}�tkk�tv
���������SUU�����~�8�r��}��������������q%������~�M___KKk���UUUXb<|�p���
��������b 
O�:ehh���w�����&��D"����=zTGG���������HCVV�������cGMM
�8�������S��M�6���`�W����===�T����q��zPYYH�R�����y�;����#G�(**N�:U�s>���_YZZfdd��$��T���1�Lss���D�Yzoff6d����o��B���///�q��!�P�;N*++����`0~��G�Y�A���?���N����
����T]]����`0��9�;�JJJF��b�����;KO�B�����T����8@"��J����)���>0\]
��}�q)u�Y����sccc{{���R�Y�r��e��������W>L�P�?�;H_S(��~�	w��*))a�X���\.w�^HNNVUU]�b��s1A�����
�r���A������P(���������mllF�UYY�;K�������;v�H�W��<y����m�6�A�k��-jjjyyy������kutt���p��_�UAA!..w@&8�����	&(++'%%�����|����@ HOO���=w����p��,�����{�rrr���pg����K��?���������\����`�?��������,�����n����t�E�8q���}�����������o�jiiIh������~���I��n�s���r�s���o�����)�C�)))HzG<���3f�eeeEEEKK�u���;�q��A%%���B�A������JOO���N���M4..������/��������o����������n��Y
��r|�������v���dbbDV�/����.�W�VSS�D��F����/rrr��fss��u��.]J�~544V�^��/������7�l�������	&������=knn����q����=����eY�PTT���O�<���LV�'�o�)>>!$������N��{���������n��'%%��))X�j���#���|�!���Lb�������X����W"���caa���}	���`GGG&��`0���.\��F���������_�9I666fffw��!�A�JLL�1c�
��_��]�Bb++���D���~�O3f�X�tiZX�z�8��s'N�2������*���d����g���D�}��B���������RSS�������:z�(�D"��+�O�Nn��JDAAA?�t���g�����UUUW�\��P.$$���;?��3q�N�1��<���1��6��/
�B�hii���s8��'On����!++���Br�X������*==���`ff���3������Ib IDAT�����^^^^^^bn��p�m��d�ww�������~ee%������
!���Kb���������,>��`0H����'�?x7�p������KH$''w�>��Y�:���N\�z���zYY�;���?������$$22!���IlS�~!�;v,Bh���$�Dg��a0��	��������p8�i���������X�p�������y�f17?u�T]]�������o�YUU��J	���AUWW��������3c��
����$@q8��Y������O�4������	!���?l����X1�I��2T+++�L&����/|>!TWWG��B����%b��1�i�������l6[ TTT\�x!���$���?��_��`���;;�~6"VVVJJJ< ���e����/_~��-q���W,X�rqq!1B��������	���l���������t�Y=��so���---jjj�r.y�u����`���]������$
�:::p]8��_��>}z]]���7��Bjj��5k,,,�t�������������I�77n�hhh�>}:� b�6m��+WH��t�����r�J�E��TUUG��m�����Q�F��w�Pbb"���:u*�m\����2m�4UU���h�AH������z��
�A�RPP0l����h����,Y�������; �%e��5111O�>��L������k���D\...G���%%%�.]Z�r%� �0���P������~��-�YH3u����������&5������W�^����������������K�:6�'��Qy#""p!Gxx8B(!!w�^���5j����_RRR��;�; 
�%+000<<����������Kaa���c�����g�Yz���`��q��/���qg������c��1���k2�����d555999)**��ySB�b������S�R(���$EEE�q�",,��>�x�����,�&
/^����������; 
|�&YJJJ���%%%���������ECC�����7o.^�(��!����u�VY<s���[�\�r��E(�����������K��w�����vss������<$�Ejjj���;D"�P(��c�J�t��,�|P����FFF#F�x��%�,�*..���111y��1�,�hnn���SRR��/E�|���+��3gpg�WzJJJ���utt���pgy������������B����O>��J������2���f����555���pg��W������]K�P6n�����;N����7m�D�Pl�~���?���\\\


pg�BTT�������L��@�� **��d����������������S�N2$::w����?~�����={q��/^�����P(�����	�/���?�R�������
�x�����({{{��i����j�y��������jjj,���Sx�#����l����hkk����1	���8=z����7.<<��+�����������
e��9YYY���WII����i4���UHHHSS�����������2����c�7X@������~~~4������>�����~�>}����2�L:��x��AXy�{��q��������_�x!�=
���X�fhhx��Ay�m���;P��������X�����;���H�D���SSS����'���������������z������;v��_���E��PCC��7�L�����Y�"""`�;8����DDDDFF�������7n��I���5j���uoO|�������'O�<x� ==����<���������g��qz2M$������_�x���XKK������a�������j�����������?55�����������o��&&&z`���;p���{�nJJ����[[[i4��a�������X,��!Ch��WP�����������������J��1�������������#�9"�(+++111)))99���!���aeeebbbfffff����y���r6��f�_�|)h4���������������!�����������O�>���+...+++---//
�555D'R(---CCC33��#GZ[[[[[�������������/^������566�x��K�jhhP�T&�illlbbbjjjmmmcc]:��+���Baaa��^aaa�-�W�8������x@�<��P����_��/�����x@�<��P����_��/�����x@�<��P����_��/�����;�Q(
��;E/\�t���U]]]]]���5**
w����.�tw(�W��������>>>w���������{������9�;���wrA��D"�H$��B,����}�Bh���������!�}�������N������p��aP�l8y�$�������s���������;����|���'q��/������������<o���C���h��������9s�������666vX��v����l�2:����;c������(J}}��U�455


��G���Y�t���������;{L��s!�|����?�������N���Od������o�K�^�`A��������������O�s;�Q(������?��:�/_�8qb�%!!!�=F===�Pyyy���_�F1�L2��~�p�B�/19���F���������k���H|����������#�_�v�����r���m�B������uuu���,���vf��SSS����l����B&L�����}ff&��]�~=BHSS��gg��#�NG�����|>B��`��)#QEr�������qiii_�����<��FFFv���=b����+W�������������8ooo����!%%�������u�����|�_���H4g����D�W^^�d2B~�a��
��_y f��p8].'n+**"�������p8]��;���W6ljj"�
�].�P(�=F���ut���#���������
"����h�����D���yyy<O$���w�!Q_P���:,u�����B(33��������d�LwAg����{������kp���;P:�(
RT4��bA���DDT4c�&�hb/������H��P)�],TQT�����+�?�~�r����1��`ov����=;;;uR>��@��T�?!>���s-,,���k:���$��o��l�������dn����:t(�������z{{^\�Q�*hMbb"���������oA4�?��qg���AM�W����\�`ii���PUU���`ii���6�����[��������������(����}���`~�����/���o�������
�
v���O�>544���:t��fBCC�����&��3gN��WI~��?n��?~<�F�����?���E�M�t�����H$��s'h���;;�	4��WA��z����S!!���&�-//_�h���Gt��/�^�~=f�5556�������o/=����m������J�=~�����F��8�������������������
��������ri4�������-[jjj:�=0����.\�@l����_�t���7>�!�.L�:��_���C�&L����XQQ�������k�����S��UA������������$''�/�b �����[��������WG�ill�`0z���j��;w��_>��*�V�:N��6�=z����UtkPt+P��@ ����@ ����@ ����@ ����@ ����@ ����@ ����@ ����@ ����@ ����@ ���?SH����a���-l�J���R(�_�u��%��u�������|�s>����:�annn�n��'� �UH>|�`ii�^�a���{�C���F����={�f-`�}��+V��
�@������zxxP(mT�B���D�Ks��mz�h�a3f� YB�@����^��aX`` �z�!m6~�T��������A���L�2�=��2e
�z�!���C�m�	�n�I@������#F�h�YA�F��������R��l��R��'O���X �U`f���4G(��5��n���[�G����	KB�@����?���`c�����tC444����[�@ @�@�� �U`������4��N�O�0AMM
������3���8jjj~~~� ������3�|>�7���9s&\=����G������t&�	WBQ@����5JCC�[CCc���p�tCTTT&O��?�466�a��A�������S�2:�>m�������1���f��[Ba@���L�:������q�����tS����h1���($<������P(���jhh`V\\K�P�������(�R__������������WW�7n_�~�F��������9G��A���;B�0==�������YYY������������p���������z��������k|�����'�������������������NNN...���$F(���H���r�����������ruuu�177711�r����������1�����������������OO�Q�F����U�;�>}�z�jBBBRRRNN�J����������r�x-p8�&?=}�t�����b<����o��}��ufffQQ�N�����������
�FJts������g���r�J~~>��2d��A�<==�����V$eff��w/111>>>77������o�����D�W����������<y���>d�OO�A����_�]�D"��_�|IJJJLLLLL|����������������wSD9�����������O��1%%Ev�={�l��M�z����k����+N!
�W�^����R�AAAW�^����Qq�>}:|������t�����+^�~-��r�_��������������^�:33���322V�^����b�BCC����,]N�����{���%�N�2e��[�i����>|�;>|xrr2iE#���������WWW711��};�(���������X,������`)!���p+++�1����,X2�BaTT���;�a�����A&�! 
�?nll����������V$�D���{��e�����aaa���������S(��� �i���{����N�/_������lA�K6���c���R�!!!%%%������888�J����}��������l�B������<y[NK��#G���,,,`�A����k`` �����8�chhx���Z���p������'����4��7m�$
a�A����q��	:����eee����������0233{��aee��[,���}������3g������ ��$�u�V�6l��@m�P�f�|+u�Z����������EEE��t���Xmm�a��UWW��� ��d�k�.�>[HW8p��a����-D*^�x�f����d7�Wv���������ZQ ��9'O��0l�����t�m��av���B���

���+E4_���mm�I�&)���C������tuu�����iY�|9��R�q���������������HE\\�F��gl!�@�?��������&&&*���


^^^|>�����u-7n��}�������
�������??|��/�Px`���;v0���o��B���L&S��_���C�;�#<==���P/�r��WV|��E[[{��u��<##c��-nnn��[]N�YV�^���S\\LHn$0~�x���FYd�a�SRRV�Z��_?uuu���g������\i
}���B9��4� ����b���zzz2�s��!F:<OGG���~#$7Y�������Q�F��'N�/^HS��i����+M9��&�)����c�X�����a��M���R��,������;x��@  0[q��!kkk???��a�����}�������j�w��KK�������KS����SRR<x M&��
@9���ddd�� I*�����&11��e�P(444����I(K�?|����*e���-�2tP�W&��{��������9������0���'���(�k8::r8��w�������?����&�k������%�*�����W�c`���Y�fI���y�$�/I*����1c���/���#G��X,)��X8G�H���
���������	������8w������ohh())������!H�T�������V���������'�2��BZZ���+1[�n�4�vvvB����R����T�ND{������I�������7?vrr2d���c��K�Bi���/..���JJJtuu����ZHKK1b��[�v���������EEER�����r�d2��B"))����yM�5�����T"�}��	�� ����@???)3!�����l6 ((�����������B@�?�6�]ZZ*M���III������Y,�����-[F�Bi �i)k�lvII���RW�^>|xii���:$~�z	�/M�k!�� tuu�B��h�����={��y�u�RTT$��|B�H]'N�X�`��		��?!���y������	�{�~���49<���S���|>���(<<PWWG�@�x��������w�7o�H�"e-l��m���|>?44��?�$�|�?������Q"��D99p����&���rmVVPP��O[���j�����b��Z�_�|�0�����d"e-���R��8|�pir@���+�^YYy���.�p������[ZZ��t===���8p�@�]���������-�������/]�$M&�Y���W�^1b\�A�������J]]=::��=z�@ �q�l!s����+W����c�����/Z�(??��*:��++���������B�$--��������-D"�O�N�P>[��={����!�UP�WV���jhh��}���w�}�����d�o����/�dffr8�Z����C��/OKK���'l-�������{��%�B��������x�B:Auu�������a!���?.]��1 ��-.����r�y���w����/�-����q�B�?~�i#G����*//��A��WVTWW������;������*���Nee��)S���w��[K������a��%K�<y[�Tl��)!!!<<\��+�������M�6���|���111�����������u����A��������.�������lvJJ
l-]d��-��X�B ��� ��D������@�add���?��SSSuuu�RZZ
Wag)++<x���>	{y��������JWW7))	��N�y�f����+
����t��ii�� ��� 
���===�����n�Hy����������7o���������fff��?���*++}}}�L���gak������� *���~�H������P&���pv��]SS[ B*��J����
6l��;w�����svvf��������2��]322rqq)((���0�|��%K����z�r: //o���-fQ�~�z���t:���>|X�=>A��E�|~XX����J
�pG����`�t�R�����


�0,88XnEJCXX���f������`ki��g����������������t[[���pB�F����p�����{c6n��G�u����H33��'O����@p��qSSSCC���h�rdHNN��A���+��S�������T*u���6�������h4������Q��a IDAT� 
���#..n����M�4I�^������S�T���h���P���L��BCC�����!�Px��1]]��[�VVV�V$����9s&�B�����P����)S�`������(;�bA�+)			�M�2%--��<SRR���aX�~�.^����@H������������xs�����k�HYY����b�tuu���/_�@����|�
;;�3g�t�~�7(�7�|�4�!� ���/^��-:������������fdd�f��:%322���{:�>}������)))��i������y�&9����<��_?@�~�.\� }Txx��������!���9��Q^^�|�r����!�^��?n���������n���j�������k��upp���o��
��p�����??j�(
����7g����/�b����o���?|�p:��������ohh��{������iXX��-D{����F$�>}z��U��~�m���T*����>}z��������,55�~��������888���3�N�V__�����������>{�������������oy!Z������������x�Phgg���6`�'''GG���&,����������G�=|�����l6{��q���#F�`2�2��5k��:uj��a�v�����,JAH��6x������_�z�v�����^MM
�|��{��%''�~�Z �h��={r8.�khhH���A��������������|*�jkk���������iee�������y��YMM
����G����&&&GUU������yyy�����������nnn�
rww0`@����~���[��������khh�P(BB�������+V�>}z��a�����
lE�G]]]FFFFFFVVVnn���


�B!���0L[[�B����s8;;;{{{{{{����������������������P]]]WW����'�����h:::���fff&&&����������6��DG�Y�z�����C����n��y�������l6���Cr5,W�M����1y����
���cJJJ���c������-!��'q�|�2i��i���1"33s�����E_������nGQQ�Bl�f�>��?��z����i��=B��������,8r����MjjjRR�������a+�
����[H����V�B���}�����������������nM����?�3f��E�����?www����������S\\�X�lmm����+66����{��~�:lE������N�rrrz��u||���[�|��@ ��BEEECC�B�?�`��aiii�������={�B����tG�����?~``����������`+"uuu*����d������

���������?�����)lE��n��iii���111QQQaaa�����a����IF��g��I�?��������w�
H%����{��qqq133KKK7nl9�������LQQPp�XZZ����]�v�����M��������]����1$$��o�
		�z��b�0�MM���J�*����jjj�����H�F��qc||��{�������[Q��[�oqq������'��?�s�N:�[�L@��S\\�����xxx<����l��������(?������nnn>|HNN�2e
l92�?�OII�2�/@__�����/X�f�@ ��H�Qr��y����'��}��Q���a��-ZZZ��K2�5�BBh4���[8�k����'�N-���������G��5���[J�Hi��@>���:::�U��������G�y{{����Di���~

]�n����I[�.�����\i�0�������'B��_�~/_��-G	QB��D�/��e��#G6o��alE$���|�������cc��w�Z[[{{{��w�eC�����q�����������o`�!���|�����7n�1b���#�\�[�R�T����g��1f��r������)q�C***g���3g��	�9[��@�(� 
����k��]�vm�����@@SS���Z t��ny@���C�R�������/6�p�B���%�_�|���n�����HJ����H$����&���������m�~��7MM�E�Q(��V��(���\����s�����|A�-0��#��������f�������`���+�Q���s��={�����[L�$�=���?466.\�PCCc�����(0
���N������m�[d��$������6o�\WW������[�����=z�p��y���\��� �%�������c������)))��(*
��EEE�&M���<x� l-r��d***�T�,>�5(JXX��������O�`�QH��|��)SX,��K��u=����� ���j55��3��5#""��f�3�����CQ�w��M�?�p����l-r�G&555jjj�U@��bEGG���}���h������{����[�����W�^���h2�����������|���}�`kQ0�+**���;u�����.g�a�=6fffn��u���
E�li�(&��?����]\\X,�������������H�Q[[����������_uvvf�X���c���u�V��G�����W�ZE�&�
+�(��mV�h��;����������^�b]��U���;w���gu����E��d�/^�)c��U���"��H$��������:�B���c{����������j�c����;E�����_?~����{��#>^������M�RSS;L)�
��}�n��=%%������]�r������l���d����u�D
�@ �<yrVV���uTT������v���!CZ��0���c555��-#P�����z{{f����s�����=z�����H���ktx�AAA#F��0�2���C���*����3g���"�������>}�$��k�0;s�L{	�8V-x��=�ajjj��Q����m����8��xS�P�>��Gjkk�.]jhhH���o��������c�Xzzz���555-����{�����t���������7[h�0���j���ZZZ���{�������5KGGGOOo���"���M���-&��������s�K�,122�$&�F��?��e�JJJZ���j���'E"��	���"�^ 5���g2����{���\���I��<��]TTdll��\���Os0���lq��������ruum]U�a�m������[�����___�O���c���h�'P�P�������k��=z0��������N�������>}z���;V-���\�~]L����3gZ[[�����i�:hq����������m�����qqq���qqq\.��Jm������k�������w��0`@����_�x���BBBZZZ-�xzzJ��.����w���t���D���T---�%<���h�"�R�ZEE�z�IKK���?�w�?�����n/&J��$%%����|��d����=�0,<<���+5""BLz��nLLL�����mVj�|bcc�������sL&�����������c�G:���l���c,K|b%�Ijj*�&Z�v�$�	���m���"�5>����^�|������4""����/���&M�p8�����>���jNPP�����L1�w���B����+���TLz�_VV��iiii���"�s��a��Llqb]]��P(l��a�����l"<<�0���b����f�AAAb�2�W�^?���H�C����{�n���o�����w�H$������h}ST�X5QWW������K�)�����F|��?.y�������U[[+����:<Q�#���&�W
��(}L�\���Z�p!��+�z����o���:�}���h���x�tz{g����L&���w���j����gg�S*�����������[��R[?����HR�����L���(�U�$)�aX>|){L�?�?H���@1_�Hddd�{�n�R��n����p�;�����������A%�U�G��������������;w��Of``8s�~skB�J�����LHH���JHH�����R������+)))++�p������*U�����%����'


Y�����_��:�����DFF����/_���/_.>>�m...����
����F��h���B�)E������sww�0��9s���KR��?n1����F�����&h�i4���P��Z�,((���(qL�@��(���h�O�)u�E"��%KZ�����y?�����������D;v��s:D��7;;�B�DEEu����|��E\.�i-`��$�*�^�~=f�5556�������o/=����m������J�=~�����FYTj�o{�������?���H����z����EJj��'Ozzz�X,�acc�n�:1s�Z��������>V�{��;wN|���P�D�X�x�����{�2zv:�!B��J�JX��Bqc"#�wP���X�/�S�N���i��+=�+��\^^�x������	+**>}���_�_��w
�������DF444��Y)}�7o����s��Y��R�X�����;���Z����������\;9���n��M�|�)&����� }V�!��g������M`%�����=:k�,�EBYW�^9r���1�������U����CH��|��C�b"l�v�P�_�����7��,V�H��X$%%yyy�z����	����k����v��������y��>C�!�����?��%	=������?�������-8����o7a������M@>��������s���-D!�f�� ��,vvv~~~[�l�-D��G����nhh�:u*l!
	Q��A����[���#|E�O�={���Q����`QH�����.��������+�r��%%%7n��>}:l!�
�_r@��5�������w���"���FDD0�q�������o����kL�8����������r���������������d���k�h�=z��������������+�lB9@SS���Z ��� ��2�����x������G�����k
_��5455E�.���


t:M%�������;r�l!��/��z���A�455aQ`����B�444��o�Y�p��{���#�3�������-�����������_3f\I�~��_�544��������|���
���0|�p.�{����#���;s�DIP�u�D�<|�022R$��t;;���2�UQQ����#�V�XQXXXZZ������555===����E�utt���`�TxRSS�-[���������������v���)
e��9

�|���3g^�x��W�3f��F*�����_�������W4-(((88������g����9�!��x�s����)�J9r$�J%Y��akk����c�.^�����������������J*����(��%���r�L
�YYY�������'M�X�lY{	���c��)FY���S�Nm���F���5�dI
���o�n������g��;w�C��)�ad��p8M�@5��`8044�|I�H�>}\]]�l�b���K�$�d��)����h��#G��l�%)�n�Z�v-����;�6�@�������m.@,
�=�
�G����K�Ba������ _ ��C�����>.
[o��hMpp��9sh���=Q��lLMM�6"m�J��Y�����$%  @[[��A����E�RB�RZ���������������K��@�_33��_�fii�a�X���p��_���F4��XZwA0�i��1�LX�&��������/�����8"�������@���,Z����c==�~������x{{���ihh�={6,=�������g[w<��_�111i~������<x0DI���9rdS��N;v,� K,�� �����������r���o�1C�_���hM/4(�����;�JRh�,Y��Z�����Y���N�����&��l��������0�!`ff��!
����/_�����\.��B��9��d��!M]|>u>t
�������1ko\��-,,�[��1c��oR�aXHH�F�0l���h�,�R��D
���o_kkk��##��/����|�B��w/l-���9s0�Dh����4i���R����a�*�*
����������?���CMMMmmm]]~����x�b�� %%%%_�|����{�.�N�x�"��TUUUSS�r�FFFh!�.���



�BaYY���Fuu���Fll,�B122233C]��LII������KNNn����T*������TWW�T����~&=���O�<y��UjjjZZZvvvaaa��2���������;::���������N���������W�^���gdd���u���J522���qtttrr���������P����������������������OTWW�p8vvv���NNN�{�vpp@o�Z�����>}���Y��D��P(LNN�v�Zbb�������������������������9���F��<x����f�������?|���/���^^^���~~~DIUP��{������UUU��r�fff���FFF����;00���������������7o�dfffdd3�LWW�A�������w�	�"�(%%����III���������6�bnnnbb��r


��D���+))?~<��������������OO�Q�F����U�D�?��7o�l����?D"Qaa�r��������7����-Zt����?Jr�P(l��@ x�����{'M��?w8;;���O����hV ���i��>}�tuu'O��w���/_
��Ni/��)((8{���E��F��������	��$$$��p�\����������t�g�����1	�F��#G9���<$$���{��W$����b��T�����<�������������A���466��uk��ET*��������(H��u���	�T���aHHHlllcc�,
������_����{�>t�Puu�,
�x<���{�eF�����B���g��m���W�^�^�z������Bv���:���[ZZ�z�j��`��������j�@p���)S�P�T''���01m@�������999Q��)S���u������\�z5�����\�zuYY9��I^^^hh������>��^������W����X������|2K'��i�G���������qcII�,du��g�&N��a�����g��h�O�<qss�P(�&M�i�L���������4008z��$�
Aee�������MLL�o�����~��w###��q����*XJ��C�����|������`�[����\F�:�g���T*544T	��x<���K��RSSa�����Y���`xzz�|���
���766������?���`+�D�����{���lSS���0�r��Cg���B����UTT�
F��Z��={������������t������������������tooo��{�*hC���p��1T*5$$V�L������T*���������t�]C"�-//;v,����s�|�������`0���[KW��s'�N�0a���H$
���og0�����x��t���X����Z���p

���[K�@��e:�����^�zq��'O�� ����]�vQ���K���|�r$���/Z��F������x�����y�>}����'�tz@@�<<wHYY���?������ak�������~�����������AR���6i�$��"����	&���_�r�������������7o`k���[�b�a��l���P(\�f
�a��o���c�?H�8������T� IDAT�r����������������_���N ��9SCC������t���rWW�=z��On��]�>|���p������[�8�?HO��[UU��������I)r��k��t��u�`��U����7a�4EEE����{���9'O��0l�����t�m��av���B��!���,`��>| S
�:t�B������67n��0���l!]$''G[[{��E���Azz����w�}[��,_���beee����m�����K#+.'N455��\������S�L�-D*��=�a���\�������������i���0`@��}��Z�?E�[__��g�i�����X����l���[HKV�X���'�C�:��)S�����v���d2��}[1dgg3�L�5���@����;w2��w��������U�V���O]]��`���3$$�����_����	�SJ��}���B�/j����x����[�!?���|����-�~����-[���������FK�^�ZGGG~�YI����l��w!�����!����-[FF�m�����������333[�jQJ���~��r����,466�ipbs		�����UN6o����WYY)��%qUY�/�������������������"��C�/�?���a9]�}����}{JJJuu5���r����%`�������?�����|���:6���/��\���u�r��f����a��7�����|333�=N:88l��)55�C�%���+W������2��5����c���'\h�]�;w���;)"�����UUU������0�k��aF�[��7jjj6��Bx�����|�
��v���8��V�m����~bb"�9w�����{�����]I�?��o&!!���������pww700`0&&&�'O���m3������8---mll���$$$�����!B�������u�O?���K$|||�!�w������fC�N}W���������{���p��I�H4a���Idhn�_�|�0���k��y�:,���G�|}}	 ���������g�:t��y�����:���	�m)&��p����� ����5k�49H�]F��>}�0SS�H�W���1���Eg���������X:D��u>~����C`jjj��1??������$&&����u���T---�����_������kXZZn������7,,��+#����<}����;������~W;������2Q���~����>i��IIIcccYt�C����?��������NNN��}���'KKK��{�������F������Y���E����^qq1�yv�����[ZZ��w���1c��!��===�����J����U1�7.!!�����������6m�F����<D@��%1s�L*�J`�80���GDD�N����b_�Q�F�Xd:99��f���d�(����`0�����S�N������7OCC���o�'���z@dd$�9w
&�)��|WE�	����&&&���9q�����,�������h������������������'�X,@��3W�\��A.\(�����cdd$��;������o�����R�����������]���D�wG��x<�N�R�H$��c������H�D���8;;[n����7�7B���
��t;�F�����������������G'N�X�`��		���x��2EEER>����.�O:��W��vb)**D?�vBb+�����<)**�a���|�={6��6�?��������d>}���|�����|>�_TT���l��m���|>?44��?�����>}���$��;���i�m}��Oi�7!<}�TMM
=
���{�/����`J�W_}^XX��������a�2&N�(�*������G�|��d�������7i4��3,�90���Ot����.*�f�AAA�-����(B���f��
&;w����'��ELx�KLT�Myzz�mg9p�����4�����_P��������T�Kklld�X���<����c�����	,�9p����q���fff�������---�t��������������_�����WDe(
/^��Nd����MLL6n�Hl�]����R�N��7))i��9\.�F��X����o�����F��w��<,�F�?����p��9�Jl\h�k����0,&&�Y0}�t777�*�?...����UFDD�B!a5,I6l���l�������y�A�@,m��
4b�������\&�y��A�B�?{��USSS�-�����M�zI�p��i����[����R�������  �6�7>> o�t�3fXYY����x���g��
[DFFb����B��@0`��a���B$C�uuu���"q�?H���c��qpp���%Y
�$''S(���O�����0*����C�B�������n���������o.]�[1\�x[�@�@m�/��bhh(�j���������W~Mkkk�N!!!:::r������l6��@���w����/�-�%����������0LA��   ������/���Maa�����3��� 	��������������VQQ������-��/@���?���r�J&�)o�>��l�2UU���$�B��d2W�\	[H��}������5k`i�w�����z{{WWW������
dnn.��#�q�+
�O����%�K�P(\�n�J�|�2l-s��E
���?��	���555���������;d���?�LYY�������I��C�?HO������L�B<h444��3��`������H��'�t�7�|�/�.�\�pAEEe���r��|{<}����������7��HJnn����������ak��R��l(�@�r�J*��q�Fy�����!C�hii������9n�����9t�PB���������P(�����|��������f��/�)	��]322rqq��oB�?H���QO�8�b�����d�S"##������#��l������W/==���(�Z� ''���SCCC~�SUU�`���.]*���UUU������H1 ��X
 ++���EMM��$dV;!dgg�;����+�����������'?�����7nTUU�������a��:���fff'O��������MMM


���a��:��@�Vcill��c���r������QXX�|�r'''��E||�����\�b��1���G��p8�v���GK	)--]�x1�Juqq������"
###���i4ZhhhYY\=�����te5������g�h4��'O�?>1??�������v�R�wA�����}�v}}}��v�Z�����N�8aeeE������4KU�����
�~��]�x�����������������������j������D}}���Wggg(�M�|���7���i4�����;��LB����m�fddD��'O�K�S����W�Z����`0���'������h4##�5k�dee�SnFF���o``@���O��d���� �j��?���?��������?�|���'����7nP(�Q�F]�tI��i������C�P

.\x��
b;���/6o��o�`kk�m�6��������[�n���8::�[�����?5744�����{{�m��[�|��A<����hD"���/^����������>p���}�:99YZZv*����������'O�������|>���=  `��Ifff�V8������/^��������0`���������<+�H����W�^=�����<(//�p8S�L�2e�����6��[�>}z��������,55�~��������888���w*������������O�>|����g�����������������U�-����mB$�|�2!!!111))����MMM333����i}Vaaa~~~~~������y���i4�����������bllL�N�����������KLL����eeeeaaafffnn��n�yyy������YYY���SSS/////�A������nk���������������k�@@��z����pLLL�\���!�Fkq��/,,���-((���������T*���������������
���Z@������$55�YEGG|���������i�=MMM*�j```jj�;���������������)���������{��133
�EEE����O�d2UUU����\�����������������-�=���222222���>|�p��-UU���r�PX^^��p0����P(FFFfff���������}�;��^�~}��1SS����n����&�={������eccCBq�����1a��Z����dOO���;;;�Z���������������B*�������)
��%�����mg���cmm��WFDGG���v7�����

��yA>y��������;v,lJKdd��q�`��y�kaaANY��w����lMMM�B��7o����������ddd�y�f�����@����� ;���no�����:::�
�-D9�r�������a�I�[XXhbbBNY�^�=b������p������S�T�B @�������N����DWW�
���� ..n�����('YYY�?�9s&l!p �utt�)�RZZ��WF\�tICC��������s���C��-d��H$*//G�_�QRR��+#��??~�x4tGF�={v���
I
Ay�����x��e��>|�����SaQNRRR����M�[4�����2j��|:,�_Yp��%6�=b��B���/r�\777�B�A��VUUX,	euCjkk�B!
�,�;�t:l!J�@ 8u��������Od��P(t��%$ 
�x����G����[�rr�������� �B`B����m��e
�_q��1�B�����C������k�"��|> �%������O��3�����OW�\�7ol!�A�����_4;�X���*++g��
[�rr��)�5y�d�B ���� �;6f�CCC�B��Ht���i�������2M��Mrz���79!�����};<<��$))����aaa�������������PV7oyy9l!���={8ZpRF���������������@�������������_7nD]:��������g���-D. ����<F!;�����Q�8qB$}��7��('�������I�`���_UUU��������F�`���_�5��� �����G�.^�
��!iL2������������l�2�B����0�H����5�<�E�_������K���1b���5l!J�P(<p���3��E$=�������SV7�������U(<IIIw���q�l!�����������a�#Hj�r�\d������!
�W�2d���l!J����qc`` z�hI�_�GNY����<�P�&yw�;w�$%%%&&����9s������_�-D� ��joo������Z�2�0LQ�
}����+�������d2���CBBrss	,����������De�@�m��Y��&��~6l���W
U�p�\��O�>���L&���j���999�+�������3f����gg�U��VVV�_����NEEEKKk��!.\w��233O�>m/Ag��)^J������ht���j
�r��%�$�P���������j�N�y�& ))	�W������6��g�X>�Q�'N���h���"��mii���C���[���SH����F&���>i[��D��0`���������%%%7n�pvv4��Rz���y���>U��6QWWgmm���4h���w��J.|����[|||EE��������?���]%666���M�6
�W�c
�p8�/_.-----���033�0���y�puu]�dI{�*q�����7UUU�;vl{�v��n��QSS���O�����/��(q������{�� ����d����h���t�_%����9�������}�t��6O!/xh�"���G555K�,100�R���7����???uuu]]��VWW�H�^>����f�255��h�N�7n�h����r��9���FFF�w��D%%%3g�������]�n�P(�<�P�O��}��ikk��u��fff2�]�v�/���*ss��3gv�p������VVVMr���ttt�������5��>�����VTT��)�����i4ZEEE":��������.**266n~������^>��0,22���'Nl�&**�������'OJ������x�p�����b�<}������u��:������Q�I�mj5w�p:t������PQQQQQ?`��_�%a�$g���zzzeee�]�2���f�WWW��S�����?S(�����u�7�-����^�z����y����`aaWYY��r��������^�v������!??��]��7+�Dgg�/^�x������V�#����/�y���;vL��u>��f�w��!����+zx��d����_lkrrr�L���[�U�N�>��������t��9I"�)^�zE��8����_����DFF����/_�p8���)�v������Cl�DDD�Iokk���i��i�M��������5_�yG~������?~l������ko�ug�X��/���Jg�1cF��H�Ko��B����D__��^lk&N�hkk��"�8\|>��~h1X[[{��
mv^I���o����|~��J��?�]���M���uR�w��
�uz�����R1��W
M�8"������Zi���s��Z�����:���m&Z�0L������X�b�$�HNXX����x�?R����7OCC����^l������j���k��
�����x���~�������������q%��H$*,,\�x1�������mKNNp8�6�����=<~��
bkE�q�k�E&�`���������Z�HTUU���������H�S$����N���?���?8���������}}}��T��ebb�y�fbb��Y�����g��m�Q�������&Mj�S�����._���q�W��?i�$����$&&F�Z�������HTT	����PWW��	�8q�W_}�����������ohh����6?U�p1�L������600���K���8��������.���Qd�������Z�4�����g\Y�7�3i�Z  �4�"��Z��*����7�k��]u-�����u-`�.�bC�
�*(UP=@H2�����<4)�$���3g~�!WN���$>���W�-[���������������g����V�^]ZZZVVv��������`G����#�\�R\\����������g?F���"�E&��~'(��m?|�.\�hz��%�\�
����_TVV��������t��-���9��o�x��8>l�����������k�����<<<�:�.�����{���O��9������+������M��0a�B��:��[�6[��Y���W@k���SSS�Z����������]�l�o�������g�9s����o�G�ihh�444?~��6See%���2eJ[3(���[{��������9;m���������M,//_�hq���{��w���7NCCCOO/000--
`hh����@�m��������u�����ohh��^ILL�3g���P(�g����/o�E��
6���VWW7���������D�G����iv�|3���222���geeE��h4�������333�YD|AAAFFF_�~mk������c��������������kjj��B�����~�Zv���I IDAT���g�����[QQ���Z��.�Kq7����I$���w��R��\�������YP�m��
���={N�4I�mN�0!>>���������C����={�Hq
��d��<OZ
*��}��%�N_�r��W�����|�bff6}�t��E��-������e����-���I�EQXX�����H�A%��&&&c����]-)�������!C�8884;�%uJ�m��_�H��O///i5=j�(�fmm�b��VoCPK�.���k��NP������
��p�9.)E���:��_UWW����W�d�N��q����$)""V���r���g��;H�0w�\---9T�t����?;���Vq�;w.��n�L4�iQQQ���wv�6m�D�Pbbb`QNO�>�����-�D!���_�|���_�`��m������MWT5�v��0L#+"8�gdd�X��c�6d����xLL�a�O��CYUUU999��������q#�D:r�� ��(�C����6�r��q���~b2������(���T--��S���|�Y�j��
���NNN���E�>}��t��Ld������]__����M��D�������<���#�_Qz6l���������W�*--2d��<000�G�A��8�����oFHH� J+11QWWw���M��RV���;�DB�|e������l6�� jH't����xLL�L��]�*.99��f����b��.B$�^�������H��������fgdd����J��q|���T*]/%;����}�����R^�YWW7c�
�r��!�Y�S~~~�=e7z���B�W$M�4��b��V�����/�0l����t�uqqq�~�ttt�<������������w[��#���[S555�F�����������Gi]�p!((HSS�������GR�������������(������Gkii��u���v�A����`0bcc9����?}�;���2eJJJ��������E����a'�����:�N�?x�_Yx��a���MMM��������������/�������|��|�>}��b�:uJ$���aG������
k�LFD����O�P���Z>�
�\W����������������\nPP�L6lXZZ�8�*//�4i�DZ�n��U�BaHH�D��s'�,J���_��\n�~�������agQ~��?����BY�`AAA�8����lkkkdd����Huu�������N�:;�2�������Rwww�7o����n����wo��eOs9r�N�{zz�������233���������agQr]���8^QQ1t�Pmm�[�n����|����������7m�������x!!!���������;F������3V������q�@�x�b2��k�.�YTEuuuXX���������kKKKa'�?~lgg���{��Y�Y�S}}}`` �a������|(@�%l��	�e�YUU��-[

���V�\	��puu5Q&M��e��(�O�>
4HCC����������8��;w��`:��(O�����m366��hs�����O�>������;��<��R"##�Lf��=��n9S������O�����d2���`gQ-uuu����0���������^���o���F�yzz~��A��RY%%%���d2y��u�
_�S����xuuu@@�D���_���
J �={���`oo�g�
�}��={{{uu��[��#N2oeeeffv��m�YT���_���G555�����};�*z��E`` ��PSS�2e���?~���t�+�Tuuupp0�D�2eJW8������8�������m��U(����***����Q������%y�\]]��u�444���n��!��HS�/_611����y�&�,�N��/��"�h���jjj�z�z��1�8�+!!a��)T*��dv�>������{S(������R!�������Y�f�noW������7o�����/_�\�l���k�t:�D2W[[���[TT���PQQ!�$��dR�Tsss�o�����?~���|����g�?~���Z�Keff�Z����+��wo�����VB������uuu<��������E�Ptuu������0��� �����a���G�8v"���D"����Yc``�c����������={��mjjjjjjNNNii�7�����p8���NNNNNN}��������.\�p������3�������=�o��-����shhhDDD��=���////9�����??�<��rss�|����������;88888899�����sQ <������6%%%88����!!!�������z�s���
�-[v���#F�����z��������bbb���������A"�8������=���p8l6����F�5[������������������eff~��	�q{{�A��1�K[�/���FEE����|����|��,���&^��������d2���f��I"u����?������OLL���&��������vvv�����������zZRRRPP�����������������_�R�TWWW//����K�q�"����?!!!++��������K�FDD�9r��=666���&��?d!!!����L&*��<���cc��QSS�R�C�Y�v���w%9���xMM��;w��];x�`*����6v������x<i%oGJJJhh(����������luu����.5�!77w�������ijj�7��?�HHH���������K�.����}��!�Hc��I�N���e�H4w�\�D"�����8](=z�����b���?�8��*P�����P(<|�����������|Nvv��e����h4����O�8��re�����������F�����X�B*�f����~���-�h�i����}��\�+����}||�d2��
��������������c���R����K�.}��]G�D�g�&��D_J__������wuu�R�K�,��_"�Y	UUU6l���644��kW�1�������$���)<<\n]���r��1��������N7���;++��.A��xaaa,K]]=$$����[�lqvv-^�8>>�����;w�����R�����C������WRR���7_�L^�z��)S>>>������H�2�_BUUUXX��������u�JJJ`'�������B�899�9sJ

e��E��.=z���df����W������$�H3f�hVrssw������a���^@@��k�:t��[,**����F���?b��DW�^0`�a&L'�������9�������'O������_B^^��%K��\�jUW����,���������
�g��a��FFF���3T*�(T*�q|2.��y�f###2�<m���G����Q����			���x�b@@@��/�z�j���$)000??�-���������C�|���?Z���L&�����HBU�/���r���&&&�7���D(1�\���/�J]�bEuu5�����Z�|9�B�<y�8O���e�a���B�l��5###  @MMMGGg��u:����+Vp8�����U�?~�N!�;w.��fw��'���O*�:`��������|��C�XZZ���m���sF][[[!Nx ���_BEE��;�u�1b���W�9���'O,,,���=z$��vHRR�����l�6	������o~�E�������|���"�())i��e�>233

�������2���H$���kDQQ����i4��-[��hGQQ��q�����~<x��{:(��M� &G����� .^�8h� �����U�:t�so��W�jhhL�8�^w�TYY��������[����v���m]��x�b)v�����C$�N�{{{�8q���?z���Wo��G�������������/��Pv����T���?1�_TT�8J����.�BP���(///,,���
����s�Nqn�7n���;;tY���G�drpppW�v5AAA
���M����
8�B����?~�,�|��q��C�!��t:}���&Lhv�	�B���8}�t�-<{�L__���S��lv������_�t��f����YMM���n���K�,��������|����}||(
������9�X[[K��'L� �q.\�@|��Zb�X�f
�B�|�2��������S��v:_d2Y�O&����v�Z@@���v[f��QUU�t�7o����������^�IMM���i�����sww�9s���kO�8����N)#��oseee������6�������z��m�m@�Ruuu�S[��������2��,\�P]]���Gl6��� �H6l�u����v�R�T6��x-mNN�����#���8^^^>g�:�>`��7o�t�s��$P�m��G��.]J�����^�j��/�_�\����/�+���m�[myy9��;v�BvhI �9����Y�B��h4555555
���w�f�e}c����:B ��$i��u����������z�
'..�B����+�Gp����.^����Gkk���'_�v-==��lT*U[[����&Lh���Y�bcc�������O�N��9������������&�/�����������������������h�>J���'&&F(~sNkk���������+���7o�����'�2J'�
�?��g�BCC{����7_�8y�����%%%av��E��������u��jkk���I$����hMo�m�S,--��|�P(���8p OG9��o��;wn�����-Q�TCC���O6���I&����e����)�\�===�T����f�eggo����djhhhhh���0


---mmmb���������S�����Yt�322�\�r����O�o�Vg�|�����_�~
pvv^�l���;��g��������3~~~�n�* �~�`��o^�a�����x���R�a����Xk����4���We��8[{���-���;$Y��i�\\\$i�"P��0sss1?�tttz��!�T��4�����d�i			�������;88�[�.%%������E����i���r��6m�h����N������.{�$">T;&;;@�P�t:�No����077wss5j�F:t��KH>�w���zzz
q!�H$222��q�����_�f
�����D����*�~��'IZ@���VJ������������300000��/===}}����^�|����w�^i]� :t��������r�����i�F�Z�r���o����������1c�H�����8b3k���g��'I�1c�4^��(0�Jk���L&S�]�y������{��M�����,X �����Vxx��[��C�ijjJ8�R���Q[o%���EEEM'~���b�$	v��%�TQQ!I#t]���J���O666R|����g��������������_9rd�y��y���

>���^XX(���d�����O����,�_������������5�H��V^^.I0;;;�H���#I#t���Jii)�N�@RR�_�u��I.����}��-�����������-**:y�$��*((X�n�JJJ����Ie����!244|��vD"�������jhhH���G����������SF�M<Dp��Ub���z@@��=z���7��@��y<����:�'��o���,))�r�FFF�KKK:::�#^�B����++���\.W�
zxx��>11q����'O���������Vg0`�M����6�B�5����N��-�����y�tbrrr��:�xi���������������S(@vv���uc���������tJJJ�m/��/�6oi��aIII'O�lz�������C�J���d%��!��e���)33���JZ
<������������QQQ���:��#�������������k�&M�$��***��{��gO�6+�z������_A�����7o�F������?������6o�A���'�u��g������3!
�J+//p��=i5���l�W={������G\sZPP �fe���/�EGGK�H;����6{O�z�����%I��x@@������ ���+C���!!!�j���G�������R�������0����s���p8
ESS�O�>��'�����-^����^��������y�$i��m��Wq�t����'��`0����.]�$��<OOOo��-��@������1�����A����Z[[{��m���k���t:]���)�c�����)�S��V���2���_SSs��i�A���������
a���$)<<vi
��v����A'���%lhh����������t�����tzNN� Rs��55�>��H]�����w�;�DV�Xq������w^)
�ggg7p����H�Y����/�z������{7�,�4��P~���$�����t���wI$���Ga��[�n�H�����")�P8j�(���r�Y�@�W�L�bnn.��� //���l�����t���k��g�`�����J��_�~
;"5���<TTT4��Hx������
4�J����kii���IB����/..���������tFXX��5k"""�M�;"5��y`2�111���������2UZZ:f������7o*n������H//���$�q:l����W���w/*��v\�dffZYY988(����?������������HGUU��1c�����9;���d���{agA��_�***������Qll,�,����Y,V��}���:����0[�ti}}=�8����7l�0---	��F�,T����z��y$)44���v��jkkW�X�a������fN�8�����O���L�Y�t��]]]WW���t�YYA��3g�������\�v
v���r�J�n�ttt��;;�legg4�F�-]�T��I���C�%�����]���H�_h>�<}�t���#�<y7��G�F�������3�0�!��;�b����������`'�������I$���_�z;"s��Bv��www������#�HLL������O��e*�����+Wjjj���o�����/Pb<������.22R$A�����]Bttt���...���x$.��������������u���h4??�����A&e���������WW�����B9��"P��B^�x�p�Bmmm555oo�c��Iw�?>z���q�����L��E����Fuuu���=z4�D200�3g����eq�oVV���{����T���NPP��������C��u9<������������x��u������_�^�z���������\���o����<y������G����=e���c���t�
�VXXx���K�.=x�@$�������������������q���O���o��y����'O�������������w������� ]��]��KJJJHHHHHx��Yuu5��f[YYq86�mffF���-���������sss���

���}��4h��A� ���U��M���/_�{711������������E��a%%%yyy������'����I�~��]���N�����:T��?~LMMMMM���!�+�����
�H �HL&�J���������l�������dii�a���D"��O�������rss���


���x<^}}=1����B���533c�������w���wttT��F#����2����?v�u����S��w�!h�A8P�E��_A8P�E��_A8P�E��_A8P�E��_A8P�E��_A8P�E��_A8P�E��_A8P�E��_A8P�E��_A8P�E��_A8P�E��_A8P�E��_�W!� IDATA8P�E��_��a�a�S�+###,,���$����/_4h��������A��\�"���d�����+W�tss���TSS���Y�xq^^���*�q�I�����?O�%�����fo�Vc���c���-'.Y�D��8����SqW�]�jQ�����������)&��Ui8�+�;����n������f���^�j`��M\.���n��	���G��%�...����W�jjj***n��aeeUVV&��?E�A��������������k��!��Y�&===""���c7n�}F%��]������7n���a�~�?~,�\�
��G�W?���Sjkk������(J���-dee�?^SS���`���<��m�������6�M�R���G��,�a���s��e2�&&&�v�p���3g����Y�F�������f�j:��o\\�$-�	���L&S��*	Q|S�L�2eJ;�������ou:����_MLL�.��������v��0���+��4iR�y�^���o��SN�<)��m�O���PTT�t����,K���)���k�-�"���#G���#����_e@�_��w1���,::�����t�����,--���������8N�o����3&&&����������������lAgg�7o�TTT�Lf�)�������^&�J�����|>�F���r����l*��IIIa2��%$$����A�W�Y/]���t��=z�_����k�����o���;w|||��������-���#������N�����W�wAS)))Dw��_~�M���2��r��V�?��������r[}�7k����m]��l���:��"���)���z�z���?��MEvA���$===@``�H$�M����]]]Y��a��.\���Y[[��xuuu��49O�l
.��[[[��7o�NLNNn�tJ����^^^\.��<x���`"g��*�] tbYKKK����$&&��`VV ,,���V]]p���N���a�'O�l:�����C��A�w����8q"��

:p�*�����F������DFF��Fm�����-[���������������j�`�����V�^]ZZZVVv��y##�o.(����5gVV�Fl�����4-++K��;��������[��
		����2h��s��i��U�7qq���q�e'L��P(�����-���
�v������<��oo9�����iV*������f|�����U���������/Z����Wt������w������������044lk~�@ ��m[�������u�����744@y�.]�����`0���g�Kd�����.hk��ok��;��q��6�w������C���!�hG���]����7�&N����PYY�������(4��
�5�T
��*i�[��vssKJJ"Nj!��V��������DGG�5����F�Y[[�X����{��/Oh�4�$�?c��;v,�*
������ p��� ��� p��� ��� p��� ��� p��� ��� p��� ��� p�����={~����G�
�B�L&�K"�6o�����Z>�����w������1�1��������D��
)''�����}�a��O�,,,��J����������������K��?�@�����p<<<H�Vv�D���D�W��������f��!�<��A�WQ��do���G������%���n�$Mi	�_E5e������)S��G6��.0�D������������(��o}
�2r�H]]]X�TM@@@�.0�L�<y2�<�bA�W���9���H$�9s&�<*h��I-?G����
+�@P�U`&Lh�d0�6a�XyT������O�,
�G "&T���0aB�5�T*u���pS���k�������<�A�W�����g�@���7�
;v,�� ~�R�������p#!��_�6z�h---�g--�Q�F�������&O�L|ihh@��"�C�W�Q���S��h4*�:m���c�<��1��YOO���vDa�����N�����N�
;��6lq����_��!��oE!UTT�D".�����aXII��;wH$���1��F�@��@ (..�����x���}���u������[��d2��233��������;]�H$JKKKNNNIIIOO�������������������������W�^��2�|S}}������}���������������=��N�������;::���������N>����oW����W�������������r�a�_���������������k�z��
EEE���yyy��������zxxxzz�=�������D"QRRRLLLBB��g����

������lll������-,,�FDD���8^TT�����������_���,k���C�����������.���%!!!22������g��!�
��������Y�322>|���������\sss�3fxzzJ+���������v���/_����
6d������������|��D)))<x��A\\\ii�����I����knn.��(�***v������������_�z%���|�r��u={����s�������[�����>p�������e�������XQCC����-Z�b��d������we�"��C��������ahh���!��������hjj�������s�]��


��������^
��o��2e
�Lvrr:q��P(������_h�����Y�`0LMM���/�=����-[�kjj�]����V�
��244���Y�vmii)�/_��4i�a ����T!�D��711100��o_]]�D8������w����333;q��8�������A��V�^]^^;������E&�CBB�!U�����7�L&��m����d���d2������vY�D;w�TSS>|����|��3gLMMmll�={;"[�����;wX,���e||<�,�������022�w��,�W^^���M���o�.�`�iEII����i4��]�`gAd�_�����T���_W���Meee���4���S��HS^^^��=9����agi�H$��c�L�� 2�������a����v�W�D"��U��G���"���333svv.((��E,W�^�������`gA��_y��c�a�����t����1��g� �����p8��������������2w��I�v��	;H�m��
����H�A:������������v�����R��W���2Te+--��`,_�vI-Y�DSS333v�NZ�`���^NN� �t��A�t���AiB�?���www���			�>2:��8p�@ x������k��M�0���
�Xx__��O����������H]����������H�+X-�h����������1|>�����MS��8|�pmm���	;"=�;�J���/:::2:f����������p��/^�����{��E�����lll-Z$�����P]]]�:��}�vuu��?�a]����W�����F���<x��s������������')��@����l��������J��C���Z&����I�[QQ�����H��<	�Bss��~�I��r�-7�?�����l��+�� ��2!�l���+e������u�RRR������{��������/--�u����3`��A�z��e����rG���71��i�����������\.���t����0L������_����E�A$���L���d4zlS�D����N�K�F��'$$H��|��;w���Y1������N�{�. 88XZk������J�A"t�M&���oee%��������b�h4�������������s�FFF�n����haaq��}	�������#GJ��v�KQQ�O�>M�www<~�XZ���lmm����� ��4r���3gJ���y���_����������{�nIRf��1f�����/_�`#�6��/���Z�����K1��������� ������%|����g��������������_�hW�0�ttt���r�;,I*B�=�o�]q�G�=��f;�e��q���g_�z���������+s��TUUI1�����O��� v�TZZj`` I�������������������|>�F�$������D�F�������/�6��/6l�u�Vnn��������9B"I��c``���6�p����.�#$�=�|���-Dg'�?�_�t�$������������K>�/�6��/EEE�/�p8T*���r��mIII)f8u��F�b�,��������;$l���!11q����'O���L�6��<��~��`ll,a*����o6�-y;�F\�"��x��_�]�����K1��]������������"�B������dgg[[[���v�5>��t ������R/#zzz����%�f��/EEE�����1C��~�*��-��@��d�W�^��=������>}:??_ |��5**
PWW'���F��z���/_��o������(I*��g�z��-y;�fkk������)���~>|����y<^UU�����RZZ��������^�x���$�h`w���������%�I�����o���V������*�Kkhh���T�������h�")6���bgg���/�"�HOO=N9��+�������G���?����J�xxx���7�o�����9s�p8
��`0z���|����BI_���q����,����5k���l)�-��~���3f������F�^�6n�XSS#�U���o���n�h�_Y1b���v�� R6v�X�Px��-�A����Gkk�k��Ir�^�2c����l)�P�@��������cbb���a������������".++�����v�����|���9s`A��eE$���_KK��U9>����������
!>>~��!7n� �OSh���O�>MMM��&�K�}D��������H��<��������P[[;�D���H$RDD� �����l-\�����_�&'T\�>}rqq�����w/�,���GWW�Y�f���v�N���tqq���Gtt�}�@����l���yxx�����}��WJUUU
>����555�q:������M����������D"������ychh;"5���l���_�t)//���������555���+..���R�����[�t����"���t�����GEE���l`Q	)))���� ���tLYY����


��,Y#z�L&SQ����H$Z�z5�L�|�2�,����+'/^�055�����`gWnn���#��~��5�,�Q__�������'E�|��9sh4��S�`gAd�_����svv����r�
�,�cll���VPP;�4	��e������k�644�������!C�0��;w�����
��rU]]�`������~g��TWW���`�p��.RB���������?~�;K+�\�b``��wo%8����_�\��b��l���'�B!�8�#
�?nfffddt��5�qd+33���MCCc���<v�����{ooo�/^��,#���/\.w���d2������k"�n�Ht��ggg
�RVV7�|444�����������pG-Y�DMM���)>>bDnP�����WDg�������}R�������;����a�������������Y�fQ([[��'O����9@~~~hh(��`�X;v���g�@��/|�_�����P(����V������z���W�\�b��T����U��6���{�bCC��������z�� 66����B���������z�i��]EaaaXX��tGG���W?~�X����|��G�~�������m�������U\\�u�����\\\6n����,��C555�n�
d�X$i���/^D}^���?�r^�xq���K�.effjhh�����������������_����������x����'/_�������������uuu���Ph8�?y����QQQ���:::������������U�Z������)))��?��������������{6�-�W�t}��v]���OLL|��aRR��w��B!�B������055�p8FFFJ�'�
���������������l�@@&�{�����1p�@OOO(�H��8���������XXX������e��ZZZ-�***������������B���<x����bbb�!]������.======33377������w�������;�0�dll�f�MLL,,,���������w���#%%e���.���/(((((�����x���������&��,�����f������;::�]�������p8�����/�D�l��a��}yyyh�sD*��g�������v
"��?>k�,T|iA�W!�x<����<��{7''��~�Q��*������t��Q�A�
T��r������/+�������B*//�����*"""������`A�
��
�x����� �������Og0�� J�����B��x�������<y���r��1�Ae���
���V]]=�\>�=������;�lP�UH<|�����3g���;vD	����x<�N��B%DEE544��1vD	�����K>v��=u�Tt�"��*$�D"�������_�^�h� �rB�W!�H$T�����������QN��*$C��\ii��s�~��G�A����BB�_98q��FCg��A�W!��+k"�h���3g������QZ��*$����a�Pfw�����^�x1� �2C�W!1����
tXv80p�@{{{�Ae���Bb2���������������YC�W!1�L@EE� ����������=� ��C�W!��+;


��;w.���5T���s�����b��7DP�UH��/�\.� J�����������Q~h�u����������;��y��IRR����aAT��**���<�)����;]\\�
;�P�WQYXX���t���FEE9rvDU�����p8������a�=�(###,,���$�������}��N�>�s��lK�|�r����{����PWW���{PP�T���Fh-E�u��}�����%�wkG���Y�h5�8��T]]mnn���?�]��i;*�%[-�L&���{���2L�JP�WQq8���B�G��q\QJ���a��u)))�����'���%��M��������{322���KKKo�����\QQ�d�y�Tn��������?����t�b��:M��)���Dvvv�nz�m�f���lll�t:��]ZP�WQ���2���_7����k��������`###
��tzcYYY������400X�p!��k6C[�<|�0  ��fS�T}}��#G���6��aXuu���s�L�����]�\.w������k���R�n���������i�����P�T����t�Ui8������x���S�����M�4h:������&&&M����m�w�~;Mav���fN�4��<W�^���o�)'O������+�_�������Z.��$�������s�v��-N��8P�U`�-���l6���1���,::�������/_�������������p8�V����3&&&����������������lAgg�7o�TTT�Lf�)-_Q���������W�7n�sq���M�����c��i��
,<<\SSS(6��~��t�R����{���~�z�o�]��j�h���;w|||����G����-���#������Na�X��v)��~������flgq���M�a��� IDAT�����%K����i��
�����������\.�����jjj������61�~;g��m���f����m|~R�)��E�IZ����@]]}��=�/��[�������t�Rq�E����khh`2�����_5��.~�h����`���������8�WWWsAq��EZ����~255m�\�,��[����G����83#�@�?(0
�2|���'���
ZZZ>|�8%11Q����aaa��������w�v"��}������K�.%�e3hK6C\l^UU;����H����i���b"##��S��vw����-XYY���WWW���[YY5[��vlll�W�.---++;�|�UJ�,(����3�7�Y�z���auuu��U�-9r��+W�744|������NNN�Q�F��,"T�������S�����G�8U���������&LP(�V�o�u��f+�5k�,�hCG��q���L[[{���m�K��d�����OMMm�Y�CP�Ux��w_�zu����-Z��p���;T5p����q�444���������m�O��m������Z�n�~�����(UC�yp��i���Nyyy[�R�-���8g��C�PF��=�/_^XX�N�HG�������\]]e���={C��Q��TUU������/r[��nID�������{��eG��i���*++?�|���5k����-�p�����z�(�����D$���Qx"����r��������������-))I�\__omm=y���;w�n-��%	����#�HS�L���
���=j�(�fmm�b��{��)Y�8q�DII	q������D$����������/^l6&��@ �����#:;��P�U�}�������tus���������,��C�WIDEE���%''�#�
��{����Wdd$�,�����q�W�^����������:r�����333���.T�Gddd@@��7oP�U<�{��&L��?�,��A�L�:�����
�a���������� �P�Ud2y���g��}���,]NEEEXXXppp��!D���R
�...l6������t-k����o_VV����,�P�W�����;w����������m��}�����"]
��*������>99�q�.r���>0�Y�P�W	m��%+++<<v�.!77���������"]
��*��+W<x������=WY>���h�!C����������������m=OW<|�p��A/^�����A�C�Wi=y����s��=�-������;���_er�����d�Y  n|�����3�,�
T�YMM������a\\�L�G�x<^�=����c����� �C�?(3�q����/_*�M�|>���;vTVV����P� �8P�Ur���;w���e��;w`g��}��M�0���O�?��b�
###���=���J���}����/X,�,21m��s��Q��5k������};==�N���� mB�W%�������������J�26�]PP�P(L&��������g���A���?�]]�������~�v�+---,,$~eee����#)))p�!H�P�U��w?w�\dd����ag��g��5�'�p������O?�TYY	1���_��w��_�~��U���/�,������U�B�����������C��Q`@���_-**����}����'�8�����������T�����C�tuu��
A�	�S9B�p���			>����G
����\n��
���>&&���J*�&TUQee��!Cjjj>|(�+����������222�|~ee�P(��dmmm�fgg���`oo/��eyyy-��&�H������h�I�+C�WEzzz2��{������zu\.7>>�������OKK
�4����N�kiiQ(�@ �����xYYY|>�B�8886l��a�n���K�&O�������~�m����<��P�U]���C��������Jp]]���WO�:u��-����G���_?{{{KKK���$>~���������w�>��D"�5j��Y>>>���Mg���_�o�N�L&��d���'�N�*��� R�#*,''����o���~u��MIZ.((X�|9���R�>>>���+//�\Seeeg������R�:::+W����s�o
D�%S(}}�G�IA�	�_U����b��
V]]�8�����������[�`����������KJJ����������������

D"���&�J����feeIk]"����}���ekk������///�Phmm���&�C<��]���_����j��y������������������N�������b�������aaa����/&F8�8q������6D���@��w����lgg���t� ������-�y��W�^T*��_~���iu����������GKK���Imm�>}�FFF6=��Tuu��+�A�A'_9����������:thEE�@ �D:����ebb���G�			qvv>r����C���={������?�P(���������vvvt:��������6777###55�����^�}������6mZ�K����_XX�o��9s�HgC ����@�����=z4;�@�R�����Ruuu�f�"�H�W�nhhh�����y��Q�T�1{��������C�bbb�J�?~vvv�>����W�\�a���s����oA�C��qohh5jT��a����V�*//>|�����;w�����800�J�Z[[<x�Ce��������w���J�.\������f����L����k�N�������;�}e
!	��P`@��x����0@"�aa`Et@�K'$B����"��7j����B��v�����r�-�z��������>���N=u��p���T[[k���	��z�~��5��VP*�c����R^^>x�����0�[[[�}��������'N�xf�������������>�g���C����k�6���c��B�kn�|��'�U���
��w���Rf��{�������~�zcW��D]y������~w��}�WEEE���C�������A�������x�b�J�T*�a77�.]��7����1"**���{�~.]���S�=zP/���k��EEEu��9''��N]-9r$�vf�����F�����}	!�7�*��7�x�Z���cPP�����2�=u������3?�f)�Z=}�t//���tf��7���k�0C�n���������P(��*�����|����;����G�*�e����>�������Ry��1f�������>��#{`)�_0���G�w����!�z����������y3s���t�B��k�IgRR�R�<{�,�q��M���7n��**������//X��z���A�������Roc�0������{{{���t�N�5j�����h8,�_��������HHHhkk�Z����v�:c��s\kk��i��u��������[^^^������������{�����g�����_��������w�=������7���qqq]�t�t��^B�_���w�}����[�n�����������;v��v�Z���?�~���'!�B����;v�����������

��s���%�d������[�������l�"aT������2������YVV&aT������x�����o�o�Y�hQVV�O?�D���q444��������g����111�����{�nic`��0������#���t��s�Nrr�[o��h������m��#G����P-�����������Z���� ��iii---��������{�v���g�������[���655�:uJ��������������+++����������#!�B�j��'NTUUQ-:t�:u*��!���B� >|���;g��������/����Q�5w�\�J����n�3gNVV���/�B�K;y�d����?�9s&�,��������g���S����eeeI�/����G�x'��������8�[XX�c��Q�F���{�E���?\�z�����G�a��egg[�3�X��������9��x��%OO�q����!���"�0a�R�������H��7�_����[���`Tcc��[�F�A����
>���G�m�����7�(((�C??�a������-#F�(,,ljjkV���***joog�Lo��i��/!������������}������}{����o@�����"�R��G��^��������#�����?��������J������Y�.^�(^�l}��),,�?���*���"�m�"���Q%%%���t!�������u�,]����������S�N�:u�vO�����������k���OO���0��8�a�F����+**!�_����B��ysYY�N����:w���6����B<x@�����n����������g~$�0[,QXXx�������7n�����O'VC������3?H���������>B�-9t��/�������I�<���G�������D�SQ[[K� �����0���Y�G�=�����/_��s��Y����.\���+�X�)��W�q`�F���3?B������T*G�=z�hBHqqqLL=�j�K����������v[���`�l)u�A���?�����/++kmm������O!6}�{��uF@Z���Q��������+�������|V���s��`���?Zs����{��.]��-�������;��`TLLLiiiss3��[�n����',r���E�EGG{xxt��q���������������088��g����XVVc�-X�_0�O�>mmm�������g���n����Q�F�e�[[\�u��i���o���~~@t���Q��������;t��k��I�E�^�:t�P���[�
�85����(oo���{��Wt������+���������&M�[�����}�:����� ��)'Nd�"��'�lmm�|���!���������O�-/^d�c�!��)&L�y��Z��>����1�����F����'G�M?\WYY����O�0A������q�������t�������)����S�N-\��n���T*�O>���Q� ��):t���@�<���������FeVjj����s�=G�=z��g�a��
@r��`�/���_P/�$�'$$���[����f�N���m���K�l{���K�.��z8�_0��g����:q������������I�	���������*�r��	??�i��I�^f%%%%''���x{{S-�-�t���?����+ml,�������:u��������hj�.ml,���y�W����cV��kWCC���%����^{���i��t��C����V�^-aT��xx�������Z-���{�)��+W�H��_~�T*?��C����><<��W^�0*cp�x��������E���e{{��i�


n����cGi�#�TTT2d��Q������V�^}��q�E<������K��m����o���T�����#GZ[[/^���&mxmmm�-R(}��|����={��������W[[��Q�<==srr��_�����7e������0����'N|��c���ZZZZ����\����y8$�O�����};00p�������t�B��k�I��u��J���g�����JHH���w��
�,�_�Lrr�����X�J�r��e�������5!!��������O?�������?�g0�B��-^�800������s�������1C���'�Z=}�t__���_��7n�����	@0��������5+???//�_�~t�W_}����+��'O����4�������c[[�����N��������8qbZZN����,�P(�������y����o��#G��y�������~�z�Vk��744$%%=���z����o�����[������G�E��zrU^^>x���]�~��w�������w��122���"�nii9~�xDDDpp�����������o������a�<x �l
��������~|��E�W�=Z�t�J������o_]]�5������{���R�^|����J�.\|���jkk���=!��U����������a���������������������.\�`Q"����������G��r��_~����N�KJJrss�������l������<���8d���2��QjkkSRR�9r��5�R9l�����������'""����z�Zcccccciiiaa��?�x����7o���>���������?�z.((X�hQAA�|�`���,�X�A?����y�~���5k�l�������LyyyvvvNN���7����1
�����a���?a���]�r�ihh��e�������c��
0@���=�_Mkk�{���y��������/\�������������hllljj"�xyyy{{w��5,,��ZMMM���cGmm��-[�/_N?
 /�� �����������;v\�z��y��z;��G�����~�m�Z�`���_�[�n�� 	�_�����������Z������;w��)StU]]}���'N|������K�,y��W
����_��������c��}���z�>..n���qqq111111t5#�V[\\|������_�t������S�L�?>U���{`#��`j�:///;;;;;����j'w��-�?!������555������}�N�0a��	O>�$�����������������;uuu�����������111}���������:XB���Q 
�_i �H�@���@���/�4���� 
�_i �H�@���@���/�4���� 
�_i �H�@���@�������`bE;Gk����'�x��������'�8s���=0w���<\�l\��^��:������J�(�c�{��U�VqW�\���.[����������WN��e����v�T�������B�n��V��j���[	!���+))�::1!��c9|��N�{��6n��q��^xA��>|X������T�s����+V�����R�d�����s'>>����c����-�j�������_��7�{��:t�<yrff&7����?������������!D�V��;788�c��7n41���&���?��H}���amH�(���V�]�ti����������{���������>|������������;',piz�-��Z�����u|��]YY��
<��s��L�����v����������ddd�1�����ll�:v�H���`6���B:w�lb�-7�{A�{��UUUz�^��M�<����`���G#c�?{�%,,����uuu�\�f
!$***''���.'''22�`���3u���>����Z����������Zq��!��}MM�K/�D	d��3��NyxxBt:�Q��BT*����
�{I
QvvvDD!$))I�����'�������{���KSS��+Wf��)Jl�R�e�X�=}���%{��M9w�����g
�_n?/^|��g�v�J�� �xyy�V�z�*�����[�3Y;�_�{q��Y�%==���o_�^?x�`B�G}$J0���e�X�U��&����$�h4�[�Zm0���III1v���bSS�����`�������y�A0�{�"*G{{{B>|h}0��p��	�������z�~��eEEE���z�������T�'��Y-z���z��E������?���������!�����(B��_~I�\�|���w��!�����W�^^^^��K�.���	!����F���������^��������K���&�P'p222�\��@� IDAT���o�
�;�����WB��������������B8���$66��a����*�F�����K�+��r���JE��m���Ju��3#���0v�����&������������������� ����������]�2�
�1c!D�T��g�������t-
��?����w���;�X��1���u����'r#�8�hdLX�����n��6m���OHH��%K~��'BH�N�L�����k���={zzz���c��----���z�����c��������3f��;:,�/���-Z���;c����bz�N�k��A�yyy����?�y�Ox���{��X�b�����g`����f�����_[[[^^~����7��>�v���+����c�]�r�������+:���)SBCCU*ULL���k����|��_i`� 
�_i �H�WN\��qaa��;F����.8l��m7���79q�������R��
�?�`�+'��M4\���Z�_�~o��FAA������2��3,kv�_p|��:'�l��Z�����f��"����{�Y�?6��|�������|��?�nd���O�����������|��?�nd�X��u�c�;(
�[�����&c�+<T�Z�f��d.��������h����o5MHH�\�b�s�����g���Vljj�
n��zwwwn���]���-w���}||>|��S'��|��?\sB���:�]���?����a���Qp���c�lw�����������|��?�ndLX�u���'
������7�3t�!������w���������:�p����p:����"�?C"������`:�b���R��6b����*�V������/^|��!�����_i��/�4���� 
�_i ���+T��������{�1???OO�����_~��_~��U�7���F��W�Bop���srr
di?z��p�VF#��_�a=Bn����v�T��C�����y�fCCCMM���~��hV�\)uh��j$��a�+{.2��~����#����Z-���P��_�_'��U����G	�n����-aU�q��!���@
��H�8Mz���	!S�N5��������
�����7${����T�������nnn����� *HU���� ��d�X�u�*��T���^��<OTH����A$�
�����V�M,I$�h4��j��`�e����b��'k���&�#]j�����fv��\�Bx_�dI{{�����B������7!����&�1pM������
����'M��V��.]�o�>\�'�����
�������9S�����K���?l�|T����o��8;��v�BO�ZNLL4��BQ��Bo6x���=a������,B������i����[�]~C�',���
�����*��� 
<�B)u�jjj���������
��\J���j���G����:�=�]J�@���[�����u�?~��)���*�*&&f���YYYH��)������7�_�^�X@�0�����@���/�4�e������V�<x������W��=_z����RK��QMb�]�2X��d�e�fee
6��~�b�d3�j��E0��
���&
�h�H������woaaasssUU���>d����){ .���E�Ww��������50�qa��<������!�~���=�����fG�����u����(OO��}�9rDX$x��\q��4e����sssG�E��g��}��DUc�#�p�B������@��+n�Z���13��������������G&<<���s555���������c��!��_�2����13�����\��������a��1������[���	!�������W���_�({������JY�j�U�2Q����PUG)�>��\s6NP��2y����OB>��cA;aT�Q
��k ���/{����!uuu��f��������L�>�����������������g���pB���;�juuuuZZ��%KDo��)>lmm������O��0��+J����#��Z���>�w�^ss��k��6��p�������e����q�~��G���`����������\	��z�.{|���DFF*�J__���Y�����f��?U����/���]���[��_�����`d��0�u9({lF�L�y�f�c�1bDUU�V���tQQQ�/>t������qI#v��/�4p�@���@���/�4���
����;WX��
�,�$�&��#W(D�t�����z�
�����d-izE����e�������8j��c��{�_��h��p��[o����������r�B�EEE;v���e����
Y>B��,Do����/)�={��4�����5�	�q�Z����	���bp7�5�a�=�[����L___����!�����+�B�G�%�����Mk�(D���1==���344��o�+pe���g,���}UUU�N����cb7�a�=w[�����+��������8�� {�k�T�Z�f�0f.��������h����o5MHH�+���<yr���6�������z���������F�ogY�hQZZZQQ}�D�[|||>|��S'���?sww�����k�D�������9r����[�n�'J$|�A�PR�����E9x!z[�o��B�����(��������6�\�'=@L��h��2�W�^M���������������f�h����XB��
���4Mjjj�.]���?H��i���~�����w���������W�������F����k�X��+C��=a������M��L��v��x��I�BA��}���0!������w�B�|vS@'L&
����D���p�p��
��)555AAA^^^���R�N��\��si��}��Bbbb�������{#���c�u�V�$����u�?~��)���*�*&&f���YYY��|	!
�"66v�������:p~��H�_i �H�@��2c��������4/��2�	���.�Gss��u����=<<�%A /J����o���t`%�e�����F�+�1R��/�����$��:u�����b���g�&�[��(����l��nQ�T������S+Z�-
����:����y���uKJJf��I���/���j��?~|���AAA������III555�v���!T����{�H�{��?��<x�J�
KHH����}����G��w7�����s����i�����% �n����O����17������w����$%%B"##��������`����-���VVVj��+W����B��[�Oa��7c�W����z}|||^^^cccEEErrr���	!�/�3&f����B��W�����3w�������<�ZT���={2wS�x�e����q/�����1������Ow�����{<W1������j�Z�%�T��B�����t�@����d]�����'�TVVZ�@Tlmmm����t�t��!��"/~����Oa���4J�I���e.��B����
�?�(1�_�4}�tBHbbb~~~CCC~~~bb"����	!;w�T�����iiiK�,=��'~��'---eee����J|���,>>��b�����������W^y��u�0>>����w��mlllnn�u���F�-J����q����lw����T���;1���gz�~����d����H���_�c?�|���"##�J��������o���j��;���������!!!			


��.^�8k����0oo�����Z������~������1�p��E��1��0�uQ�W��1��a���P�@r��H�_i �H�@��2c����Z�+�����m��!C����L�6��/���kj���t[��p�Mf��a<��z_bYY��I����X��oMM�M�6m����vQ�
��WfX�/�h4��#���m��YEEE={����������������g�P���_ys��VZZ���?��C���k�9i���U���������q���)))������N�V�f��������/���D�E�����_�zu���=z�P�TQQQ���������'���������7n
�Zd]���T����J����<�~��7�3b���G���_Y�?��� �DFF�����j�Z}��i�����-�92&(o�g�,�_�����R�%�	�F���U���/����cg<Y+655Q�"��777c;E����f6R�������>>>��B�P(������T����W�3b���7�$���Ty����3��>���Gycp������S������������&�����G��M�����ae��^�����W__���G�d'���Nbcc	!6l����h4���]�t1�"� )Te����3g�P�������+W�43"<>|���k����h���������>����7!��~=�&,�:x�c�^�|�r�\a���3���?K��1K!������w�������1c�����T�^�zm�������NL�������?BP��r1����(�?�FD����B�cKa�@t���7KH`��UUUZ�V��EEE-^����C��	`FD��/�4p�@���@���/�4���
��/ww�~�����7������"�����|�M�[/D���\�$7�hpE;F*�y�����K��[�^F��:	W�y���;::��������������7]����0�uZ�
��NS:r!z�d���3Y�������y^�/Q�q�&�"�B�,={�$�\�p����$��5�`���I���.D�D��	

mmm6D\
�l?#'a,M��=��%K!k����0O
�l�������V�Y5��Kzyy577k4��� �[�F���`?'O��={��k���&���^����e�����5��inn���kuu�?�0p�@��b����V�U(t��_!���C����?���99Y��eddTWW2D��Ko��A*��.�����=Jlp���B�"B�ui��O'�$&&���744���'&&�Y1<<��s�N�Z]]]���F����dff*�J��*X������w�666677��u����G�w[���2��h;��v�/D����~�mB�3�<��������`���I��z9�4h!$%%��V&DK�#��Xp�����VSS������(u, {8���PV�?�V�o�>BHLL����3����q_e�����c�u�V�*k`�����??e����P�J�v����,$_�
Ell������_/u,�0�����@���/�4���T���0�������{�W�<x0u�mll���K���-��DebnIc�z�ts��������6x@e������j��I������]�t�U;���6m��m�6zI>�bvQ��WNX/�h4��#n������#G�������������>|x}}���+E���1�$0��1��gQ��/))���I�{�ntt�EO�����.il�7K7`��N�	j�����{���
Y6:�K�J[[���[���<==���{��K�
���v�=�T��kS/X9rd^^^mmmmmmnn.U���&����������MMM�4���qs�"���'N�0`3�
0���'-��Y�~�����������xB���c��
\�������y���������@)AAA�6mjkk�92��v���dff�-��p������	�W���_�ZmbI���F���U���
����c�\Y+655Q����777c;�i�&BH\\\NNNMM
}�!���_�?8&�b�? T�Q����&�� c�K��9�����?����e�^}����//���???�+ZZ�=,,����������{�x
�I��s+�����5���'5��h4�o�X1 VB�u9^��������������������}���	!�Y�	kIq���=���)���k_�z�����C����v��NLc�+x@�V��G���_���<.,,\�patt�J�R�T����-***����
�_���j�a@�>p����1$���+B�cHB�y�f�c{1bDUU�V���tQQQ�/>t����^.���@8� 
�_i �H�@��r�"�����6n���OOO����q�����Z��E��
�b�3�Y��A�\��F�;v,�40��
�����=k�����`
���� ��F�+�1R�6o���O?EDD�����j�Z}������o����o�e�Z�2�;���SN�"""~�����������YYY'N\�b��={x�cb�j�=��`;��:-c5�Y�)�}EE����zA��k�X6>�Z��{�|�rPP�B������Uj %���Zd]���-;;��H������}�?b�?��O�wff���������g-����0�e]�~��������3g�P����#""!*���A�7����tOO����o��F�M �:	cyD������O=b��2sC����?�T*XZZ*�v�x���0VfX�V[��_V?'O��={��k���&���^�www���������<x���o~������{�����3z�����������!f�3S���{��}������7
@��7'�J�b�����U��/[�������Q�����\�J��q�2����K�.{���{��N�+))Y�f�������B�(,,<v��=7
N���9x-z����>��2g�;l�����P(�/_�����s���$9���Mc����z�jBHttt^^^}}}^^^tt4kE�����B6l�PUU��hRSS�t�bvE�A�&L�������P[[{���^�zBF����fj8x3�1--�:��k�.Q6
���$��_�E�7tj�O�>eeeub�-��'O�T(�����������_�>33s������>>>�
z��7��;�_�^O�� �9`
�������kjj������������:�^�i��}��Bbbb��\�����i�Pl����w��0�uu����2eJhh�J����Y�vmVV�&_B�B������y������\�����@���@����Cs�"����;v�5j�:4c����?��������O<���3g,��5���,o�y�\sh�P��pv�`��w�^�j�q����nH/�\����/��v���Cc=�h����v��*���{��7


�-P\\L��u�V����[	!���+))�_���k�ArJ�����?�hz����t�^x�~,b���?����'>���o�>F�a�+oNP���e�+�(����V0�6av�(mmm[�n�����������#G���</XF�W���p�"�"��w���cGBHEE�������|���4�!Z�p!k@RSS�\~+r����Zd]���R<<<!:�������H���Qxx��s�jjjJKK���	!c��5?�A������+�"��w�b����233����bB��������gr��E�M� �S�N�=�����B***BCC;w�����=����zw����e�7<���3�{�c���o��=���~���:�~wg�����dW��k��	����df#�q�����/x��b�S ��;��v�/rlv�;w�P�$��m���Ju��>=�&x��,`~+r",����1w�w�y���;��c���<D��`
�V�DX��;|�c>�W���>}z��1������c��1}����
�/X�?�"/r�����\���!����%���Y"�?������ln��UUUZ�V��EEE-^����C>>����IDAT>R��@0D`��H���� 
�_i ��
![��Y&�[Z�����p�MP��exnHo�8��u�-��	�_y`=�h����v��*f!�\���5���0��%��UY?	���������0�u�
��?��2O��uE�c��^���=vT��B���5�mj]�9;����\�v�.`���o�[yy9���7�|��n!d�^�m�6��%%%��������t��������FP?nkz���/Xu����#Rt�!a�����jq�B��.#�-�����,�l!dK�u��np���8}!d�A�c��_����	���>}:!$111??���!???11���������;w���������%K��6V����d��/�h2�>|8x����
��3fddd(�J����~v������l�?~rr21yJ�������YF�o����?�@0�u)�;w���cV���};�q�x��U�B���K���_��*�������/������pO���/�T0�u-����2eJhh�J����Y�vmVV�/�$0�����@���/�4������x�����v�V0�����������{������366���_���_,������?�����1$K�%lk�����|~jG^���v��"X���srr
d���<*Z�@c]Y:�"�d)��mM�`=����^Do����v��*f��:������7jjj>�����h�F�r�J�bp�s����i�`���Y���;x����#Gz{{k�Za����#�-
�Rr	�_i����,�t�Vt���!$00���M�{����� �Ba����$��%�����[�FEEyzz������#6
,��^���$�L�:U��f7�����������{��YQ�e���:v{����_Zjj�M�������Z����J��%��YCaVt���4�G���[���Zq��!��������1c��A�


�������t+`�����tOO����o��F@��I�ca�������;WSSSZZO;v�M���e,��TE���j:��k����'�r��q�R9p����R�J�X���agff�-������	<!���X�U��&����j4�[�Zm����OJJ��y������t�vV�����d�r�
U�~��%���|����~���������F@�R�$���s�T�jV�6�x��73\������'M��V��.]�o�>;���P(
�;f�
�g6$�K�
�*YM��E���8��al|�������c�h�������n���0�"� �� ���#�9��^zI����MSO�:Emt����Cu���9��2���w8��W�^M�����������������ccc	!6l����h4���]�t�$������*11�O?����4*q����O����_��#���8p~%,�>x��k���a����Ri�:�����o��K�0�!��������`����'
!d����nK��G��@\8�����j�u����O?�D�����~Z[[Y�[ZZL�uY$k.���_�^���B%��8�m������;g��G�g�`8"{���	!����:GQ]]M~{_�(���KBHRR�����L����BEw�Z��}�!111����������qB�C�a��(�/&edd��.P{��%K�H�C�����c��������������;BH|�4l����Z���������?TUU���?��s�6m
�:.��T*�������i�&����0$>d6��� 
����/�4�������+�9Z��V>���oW�Z5x�`//��={���K����n�9,k�\���m��d�5���\���_��a��W�v���q���6l����g
��3����m��d�5���\q��z�D����U�V>�����woaaasssUU���>d����+�	�8�eq������;wbccE�|�����a��:\q�ku�+{xxB�7a�kkHR��,��vl
���7G8
�8P-.U����:77w��Q��={�X�:�MKU�XpT�W;9
������"�����z�:|�0�>y�7-a�c�QI^�Xp�(x,��F���T>f�_??��+W677������-u,8*��s������h�u���z����a�����U�V������-u,8*�������"��)!!!�'O>}�4!���?�[��:&��vLP���H��w����9*�B|}}�,����:%*k�_D���GE`�u����'O>s���ZZZ>|x���B�L���[�6-a�cQ�r���G�cg��"0�:k��:����m�l�[S��t�v�J�����5�����Q����||���DFF*�J__���Y�����f��?���Js�[E�v������P�pTD���vcMai�7r��� *KEpa��7r��G8��=�=���+WT*�$�����{����z�K^�9���p�|�@����H�@���@����Cs����v�V����;v�5����O�s�������"�=��-pJ�������5x�UH������t��SO=E-c��[k�v�C�E`���XO+�h4��#�J�~��x�����K677����s���CT�����8�4��������nQQU��_�5���X�{�	�;w�������u��q��eZ�����~����y��u������C��'O����`�R�EEE;v���e����`�����S�Z���K;v������������b�O�����q�b��=������l���s���2������3gX+�U���or��	hii1���?i��N&�{��UUUb��
�WN��_n�{��k��!�DEE���������DFF���~�N���g�UWW�t������wB���X+�U��D=z�(!$''���b��������fggGDD�^xC��c��[���$�T���g
�_n?/^|��g�v�J�� �xyy�V�T���ZUU��S�9s��]RD<�����tKzz:!�o��6
���������%������V�V���~RRR��Ne�(V�vcYu��������������;��
`��9V�{�����,[�������Q�����\�����9RWW��[7�S'�{�����������!T�������x��B��;z�����E�t��MB4���-�}�����;77�BW�0
���M�>�����������������g���pB���;�juuuuZZ��%Kl���qc��b���}��������999���
!��g��EH���u�D�=d�"�����fg��A~[��`?;w�d�Z����Z�OHfi~��'��Y����3��WN��_�^���i��������,Y����~"�t���t?����v�������g�=�l�����"�������/Z�(88���w�����������{��X�b������R���p��%��93??���������7n$�}�
��_���I����r��J��$ �������O�2%44T�R����]�6++�@Z��H�_i �H�@��
��i���+��c�*�yO���94>����
��v���X��V�d�h+���_��zZ�D����U��?���r����8�4��������C��W���-f�pt���f�{����d���������Z���������������TSS#V���}����Q-�P���j���*�*,,,!!�Y�����z��Q���MZ{{��9s�������Qb���+'���+�?�f����{����V���$b��1���RSS+++�Z��+W���!����QT�d���X�u���z�>>>>//������"99�s��������V�>}�C����F�I���c�EU-������'��or���C���jV�L��^^^����&((��V�����0�2����'g��m��Z����*��������-nnntid�v���?����������{��.,��A����j�
��n���!:��Q����7g������qBHee����G�Q[[[[[[{{{{{;��t������?���������a��mL���?!�������FQ��A�u~NP�x����|�IEEEKKKYY�����j���.DO�6�Q����<x���������[�n8p`���6�
��
�-������Ad�;A�c��8P�V[�!������W�Xa6r�C�����.����/_^�`Add�R����>|�����Z����Fqqq||���oHHHBBBCC���/��5+,,����������V���������pE��p��%��1����%p���������%��1���@��H�@���@���e�]�2!���a��mC�����6m�_|a��lZ����'\�B����M�4�����n�>��8*�O�����E�W�c�V1[���m��YEEE={����������������g�8D���,9�������=���:t(((�������#���I�H!���B����M'_[�u5;���B����Z��2�J��W�����G�*�****11������b1;| �����������F			�����~�'�����,��N_��������V��j������/[��O��0;| ��������Z��<j4�[�Zm0���III1v:��bSS���v�jqss���Bhvv6���J��g��
>p���8}!d��������qqq���Z�3�G�4�_����T{��
f��_Ma]Z��
�;�_������G���������h4��3g���?����8��'���{��Mf�B�����/�.0`��ym�������������!dJrr��1c���T*U�^�6l�P[[k����g4����.
��$���������������������@���@���/�4���S�����e�[���P^��S�_�6���+lET;����#b=$n����v��*f��s��?~<a��@�p��8}
s�;���;::���������_X������H��0��%�6�B�N�9s&+����kII���3�a|���Z����E����
q������Yz��I�p�����y��U���0����]�v�����o�[yy9���7�|��n}u�^�m�6��%%%��������t��������W�\�}�vhh��I�X_Q?e�6��s�������Hj���Y����0�O�#E�8}�y&����5k�t(�>}�B��=K�����oD��o2���C���jV�b��^^^����&((��V�����0�2����'g��m���Z����*o����{rY-nnnt!z�v�����k�����?������v(">� �?���W��eddTWW2��������T��=z�Ht�ott4!$??�n������$9��)c����z�jBHttt^^^}}}^^�J��/����XB��
���4Mjjj�.]���?H>;�TQQ�T*�JeEE������Da^�������!�����^����	!�<���~Ll���l�!���Rm~��A����������������}}}CBB�A������<�C��7g�j���_g�j���_g�j���_i`� 
�_i �H�@���@���/�4���� 
�_i�?8){#�Q�aIEND�B`�
source.pngimage/png; name=source.pngDownload
�PNG


IHDR������bKGD������� IDATx���w@T��7�9���HET:z���DH��Q�5�~�^5�k4���@
*�T4
�`CA��tX�n;��><>J9���a>	,3?�/��)s0���vB�f�>P��@i��������J3M��{w��1jjj�]�@�U�����#F�T*�L\\���/�����f:���:��d2�����J3t���D"�R	\(�t�������d2eJ���� �%A��L�
�~����#1SSS���_f��	�(�_���a��������	J3B(�}�4#�����J3B(�}�4#�����J3B(�}�4#�����J3B(�}�4#�����J3B(�}�4#�����J3B(�}�4#�����J3B(�}�4#�����J3B(�}�4#�����J3B(�}���(�O?��������r8���S�����###H�Q���_�������.��a������2@+
E�aX�_b2��-����JC������w����2>�?t�P(UA��f�7����g����>��P�i 00��Ob6�|����Y����L�2��8����3g��`Ai�����w��a�X������K������9N���$$$b=��4�������3�l��C�����$(P�i"88X,�l�������aWJ3M������D"��y�`�J3Mp8�Auu�)S��.t��b���-//����H$���%%%eee==�N�h��V$yyy�?~������sss���Z[[?�-L&SOO������������z��q\.���)��,�^�zw��������*%%�Q����������HOOO��c��-]�Tv��������������|�2///77������988������8;;3�Ym�4�����S�N���<}�T[[{��I'N����@��R���������������o���
2���/$$�������pD�$%%��5��d2d���7o��Ddt����������lll�=���LFG�Ai�b�8<<�����d&%%I$j������i��������M�������p(�r!33���Qv�������PSS�u�Vuuu]]����K�R(e�J3d�`��UL&s��i���������6o���p\]]���`��;(�0��wo������.\�]�������'r���*�$����}��l��Y�jkka���T�g������
���J3b�8,,��b<xv-q��}###[[[>����C���&�������.\�0c���|\yy���OCC����G���Ai��T*]�`�_����������^^^555���������}�j*���7GEE]�tI������v������iii�]N�`/u����N�8��>***����]H�P�)RWW7t����@���Kdd$�aW�^�]H����"�������������]K�=y�$''��6D9��i@(,,�r�����������Qv](��r8�_�������TX�v����_�x��>$���?�+V����|�R�����jh���=<<|��%D`aa�}����l��X�zuqq���7���o��L�7nL�>��������~;Vd4���hcc����x����t)))�G�&0�b�����������G__?  ������+%%��{��} �4iRhh(�
�����GI������������~����t������6x��y��;�|�P(���������"���5j��%%%Tv�Qh?
����jkk����q^^^zzzCC���������/�����jjj����P�I������D`�'N�NLLLLL�}���;<<\WW��^>L���Gw��Zi�n��A���6���RPP����k����UU�7n�Y���.>��� o�5��L:mmm���Y,���������h���45�������������z������q��Y>�/�������mmmv�Q>TVV9r$��~��I������?�8����z+55555��';6���K��8��Q222������#47�n������iiiD5����x�bSSS6�������r�������G����W�N�<��{�������-,,"""`B�+W�6v-�����p��K�.����.������(47SC(ZXX����������bcc���322a��J3E"""BCC���`��w���c��5jTLL�Z���L�T�������G�����.��V�X���c��t��)�`0"""�-[��3����9r��q��2��Pj%''�x�u���.��n����r7o���Ai�ZTT�������^HNNVWW�?����������l��_~I�# �u��E.�;w�\�P���@i�#!!A]]}��I����k��H$��u+����q����2(�����X[[���������EEE���jjjg���]KO�4�����|�r����^�|	������y��mJJJ������rz����d��v����*���D����������_!���Bi�B�p��=�VUU����M�b�������fff,k��E
����P��HSS��������l�l�
����
6���p8������B�{$J��
����^^^c��!��-KHHhii!��D����o�����0j����w�]�]�!��������������b�������&L�`eeeaa��]�p/..~����'O222������`ll���@�}1p�4+���_'''���?������b���b���
6������HOO���jll,+++--������o���������������#�P�L{{�����?���[VVVVVV^^^]]-�He���xJJJ���&&&������VVV��g�P�i��.�.tE(B(�}�4#�����J3B(�}�4#�����J3B(�}�4#�����J3B(�}�4#�����J3B(�}�4#�����J3B(�}�4#�����J3B(�}�4�S^^�O?�����`0z�ubHH�a���"v)������u��?�$������,,,�o������W���������PP���LO999=|�?�PYY�k��3g��ZP������~�����r?s��VZXX������+aB47\�o��s��E���y����[�~��y�<==a�B��j��
mmm{���]�h�����S�p�����y�	}��(�����y�z?�
=+��4�S�+.:>T��~Zi ���fz��L�i��}�4#�����J3B(�}�4#�����J3B(�}�4#�����J3B(�}�4#�����F��Z�)S������(�X,V��&l6����FFF�
��Z_���������NI����`6~���e�V�.88��M��L�_|Am9��4+6===www&����p��$�P�������$�����OL}=�4+�9s�0��8�w�rzCiVx���������d���f��U,(�t"�H:>d��3g�TSS�X(�t���������X,�X,(�t�������l��C�%A��L����D���raW:�Mb�x��!uuu����)S���47���


hiiM�8v9p��4[mmmyyyUU�D"�=%���!>>^IIIYY���DOO��3���V�$//������={��ynnnYYYkk�����d������[ZZZYYY[[�7���j�fy�������;w����UUU)))��&&&���FFF��<w�\�����������R>����������������������������yD���,�JJJN�:���Smm�I�&yxxL�8������q��K�d^�~������r������!C�������xxx����������Y�f1��!C�,_�����"����rss���{;;;������G������2(��B,���[YY1�������$�DBM�yyy�6m���RWW��iS}}=5��Y.dff:::2�9s�<~�J
555[�nUWW���=~��T*�RF�4C&V�Z�d2�M����
����n������5++v9�����{������������?�8q"��=x��M�(�����Ovrmm-�Z� �J�����p>��S�@��Ai�@,����X�����#���odddkk���a��q�x3�D"QPPPRR��f�����+//���ihh�}���#`��!(���J�,�������`��S�������&55U__v9���YM��y�����K�.)P���]c��>>>---����������a��'`�GEEE���aaa��J3E������~����0������Z7Sd��u���ZZZ�k�����'O����t��(G`�:
���\.���dw����
6�;VEE����1b������vQXX��p~��W�$
J3�����������Q���A��>}J`/��/755�����C�4H����d��Cv_���{��y��qss�@ �z����i}}��_M`/�W�...�y�&�m��Iw������S���������=����hcc���f����t)))�G�&0�b�����������G__?  ���������AT�2^^^)))��I�K��4iRhh(�
�����Gy��q�����8~��U�jjj�m����L���bsss<�<`��|>_(������yyy������u��a�e��5
����b��'���jkk���	l���8///==������������������rrr�N�*������X@GGPSSCl�������l���g	l0--m��a�����+++�}Mzz��4���K���^������[��� ��A����	l������ --m��]���7n�X�fM��]�6e�����e��=z��{��l�;�;�	�������}�v��/,,hii�><u��l������wTVV ''����������z��!�
zxx�={�����������h@[[`����-���W��������e>|���<r�H���#��N��o����8Mv�s\�tiw_����&���.]���J`��@s3�&O�\]]���FT��/655e��:::...��;|�0Q��X,�z�����)�����m*�?���"""v!��r�J@@@aaa�C+����
.�t�Ryy9�B�q��AOOOy�2@s35�B������kxx8�Z�+66���?##���v-��4S$"""444==���v-}���:v��Q�F������(��J�>>>�^�z�����*�r�h������?611�]K���"#""���q��e
:�\�x���#����(��7S+99����[�v!�v��-.��y�f��|J3�������_���Brr��������|�P�fN�>�f����K�A��/r���s�
�B��|J3			����&M*//�]K�D"���[����|V�Ai�&''���ZGG'66v-](**ruuUSS;s��Zz
��������c������K��������mSRR?~��/`��(��%''[XX�x��k�VUUA�D$?~���XMMm���
��J�\
�{��<x�������o��mmm�O�633c�X�-R������,G���v������f�e[dP�;��/6l������pBCC���<(�rG(FGG{yy1�!C�,[�,!!�����.$���O���[[[[��Q�v��
w�Ct���*++�������{�.�����wrr�0a������E�v��q������gO�<����{�nCC���q`````���y�\Q	�Y�~�:99����z�*���J�,���l��a���FFFzzz�WcccYYYii)�������-����������������!����0p��������q����sss������������%Icc���<OIIIYY���������@ \�t)//o���p��BiV			������������VWW���GFF�Q��@iV���---}��������]�r����
��Y1dee%$$��_��s�����_���%�*y���<hff�������s��e��7(�
��������W�f0���RQQ�9s��s�,L��4+��G����.^�������Q�<Bi�w����^�x���r?��6m����/^�HHar�Y�����


�W��S,+  ���
t�N����������tWW���,kkkB�+hn�k���999k��%�Agg��������D5(W��,����[[[���	l�?����3g^�z��#$��n�:���.���������@i�_������������=������4�����3g����Iw���/^�({���4�)���ti������			d4J�<jkk;|���_~��3&]��������b�Y�;w���a��U�u��_	���J���q|������a�|n*�g(�r'))��3&]RWW�>}:��������iii!��I�d��*--%�M�Jhn�/YYY7n� ��I�f�����EA_�@i�/�"��I�8�������@i�#���k����
���������|j�#J�9v����jhh(e=zxx���:�fy�����o��w��K���??w�=�4��=&��1�Rpppaa����)����\�q������������nmm=i���R�5���,n�����-;c�����O?9991jv=�7o�����b��_�a�<o���f�0}����f��Nq��TZZ:l�����{{{w��[�nM�:UV��f���=���3&��o�����cccWW�xnoo		���>�x�s�}K�,133{��T���9�������.��m�6uu�7o��yf��������������������r8�?����/���q8����S\R�u3d�~����KKK�?�,[@S�����J�W�^���O>��������,���z
�o���������i��.�J�����,�����O��������������'Or8���GqtZ[[544~��������<x��y�J�-��������.\������6/^��������@����x��aw/������aX�0?|����zo�f������c���]���<y��!C"##e�r;w��������Ss�I�1���>��c����������-�f88`nn��=&����C����=~�������Aeeexx���+��
�	&�5JAo�Bi������=&���CYys������H$��FY%���L����C�-Y���{Lz%$$���7l�@8�f��?�=&=7b��	&(�b��R8����700P__v-���
���Ai���[�:�1�g��yKK����a�;��6�f�����|����|�������b=���������3&�	�v�Z]]�Bz��:5j5�r������l6���.���DDD���.)�S�Q�)r��Qee�E��.�dO�/++�]HO�4S�����_��3&]�6m�������a�S(�T��3&]b�����
��@G�H����������3g`��kiiinnn��=����]�����t��wvv����������TQ��Es3�|}}�����I��n�z�����b�?��fr���^�~]A'f���2������K�%u��`�V�JOO������
t��Kc�����;w��P(�������|��i�uu���f�?~|TTTEE�����C�`�/�d��e���jjj�1&��e��uu����V�������=


����0l��9���������9s�����F6�-�d��r��\���VD�����C*��8^__/
MMM�.]�X�}�q��O?uww?}�tcc#@�R�Ri��L��4w��mmm���VVV!!!�_��RXoa�����x�N!���f�{?�2B�P"��}�VWW�����������}�������L���g�X������,�"�����e� IDAT���m��.3�4�_�if�X����.]b��P���������w�%�q��������L�f����������0,<<|���VI��L����w�S��pF�}��
�U����j||�������(��WQQ��E��122�y����&������4::�y`�������f�����}[�b|���S����@�u3������l

�;w����H7n���c�X����.��t��zb�������������Uv�����d2uuu
���;^___�a���v����#!UM�"##������di����
�����gff>{�,;;;''�����upw��������3z����f�s��5jj�R{{��G����bbbbbbz5>������vvv�G�&���~��T*MOO���OMM}��A[[����G�=z�h333######ccc55�N���xEE�����%%%��������������g��9l�0�+�t9>����d�����C�H����;w��;w�������=z��I�<===<<:���[���������������w�����������_�h����?<>�^�255�m�R�4;;�����T�����9"�g���~��������,�n��H$JJJ
���e2��g��u�!��������@i�����i��������M������W"�$%%2�L++�����/h0>"�����<x�����m�jkk�����#����=z��.�f|�����,��e�������YYYS�La2��W�nll�]����i�J���������O({�����H}}}33����~�C�4744���r8�}��u��LN������q8�P�;-���i.++���611����]��H�����3��U�V��b������0�/^�000���+//�]K����*++��3G$Q����ni.++311qvv�k����4�����O���U����,---,,jjj`��k���l6��]Wh?>�J��%K���JJJ`�GG�e07o�$�}��}�����]H���������@�����}����9�B����FKKk����6;@��&i��o��{���=|��_����������533#��{���<�����6)��K2	l��C�4K$##�5k�P�W�?*

���E[[�����
�j�����O���i�~�:�a����5a��C����������&$$������	�e�����mmm��F�����fR��n|���E�9;;��]������m	i���� �����NII���"�A�X|��aggg]]]����p���._,��k��!`jjjnn���BHkp������C����0,>>��6CCC��N/khhHNNvrr<x��p_�p��)S����#����-��100X�d����	�]���Q�4?x�PTTD`��'��������������8//����#477?y�$������������P?>�������kB��_i�������������g�������:__����._������,�PH`������C�����������VTTDDD������o����@w�C�o�._�
��������xoo����N/������]���p?s����;�G���}}}���O�����
e��D����]�v����;����+����8p��6���@ ��lb�r|~�#---@MM
���X,@QQ��#�|�l����[{TWW����������
���#�w���(��������=|���6=<<��=����bquuutt4@����i�bcc���d_�z���jnnnx��!!j�x|&O�]QQ!��|��c�,X���'����;�C���F`�]���K�����vNN�H�R---���>>���uuu����!�[�n544$�������������avqq9v�������/�������b���X[[�_���������g�i
������?��lii!�k����i.**�0,..v!��;w���#Q�
���C�qwww�:u*�*�QZZ����9B`�d|h����d���WaB�y��������������3fXXX����.�_�����s�oy �}�\TT����z�j����@ >|�������O�q�p��a�.]�]H_H$�����C�VUU�����Vi�q|��u</99v!��f�%%���4R{����-�R�t�������k�)�T�e�&�y��
�����-�8�����x<�xK
�_|���9s�5=�x|h�f�%��u��L��m�����o�|������y�u���C�4��>}ZUU�����}$z+&&FGG�������|����i�q<??��q���;v� �j�>+((����0l��p�l|h�f�E"���{UUUMLLN�:����������r�VVV)))+�@����e���,X�b����#""��x���|��M�TTTtuu���O��M�G��(i�)((���<x��M�6���X,NLL�={6��:t���{�������}|V�e*++w��5r�H����w�}���E����������K����2oo�K�.��|������m����]ZZ���������doooee���H��������������'O���bgg����9s���� �"���Ms����RRRRSS���^�~
PWW777744466666VSS{��***�|>��/..~���X,f�Xc�����pss���������Jsg������999������%%%---����9���L&SWW���������h��1���c���r�p�'�<�Js/\�x���>C#�����; H�f�>P��@iF����f�>P��@iF����f�>P��@iF����f�>P��@iF����f�>P��@iF����f�>P��@iF����f�>P�{���'7n7n���*��533[�bEYY����
�eQ�������aaa����###���ccc�*���������������f�@p��USS�������vi���V�����^{������1c������w���U"��fXXX444`2��4������4bgg��r


�.]���
zDi�����u��a�e������O�
�����?��c��	�GL�
��_rrr�N�*6o�����y���������ZQQ���[^^�}�v�;��3��������t---���K�}���4>n�����'�47���k��L�RWW�l���G�Rsv@A9;;�������/N�>=k��������9rE��RSSzzzdw���k�w�^�h�X,^�z�o������������+**D"��?v��������M�R�Nd������]#Lkk���:�@s3B����/�������b����?���w���A������5=���\\\\\\�t��f�>P��@iF����f�>P��@iF����f�>P��@iF����f�>P��@iF�CW�~@YY����H$�}���X,f���1sttLJJ�W d�6>�j�122>|��G����ooo���0H��y����E�1��.��a��y�(�G�����4DPPP��1&����A�]�rN����#<i��.�����S_�����Ai������?�0����(���������g�����,���[]]VIrE~�������f����L"����@,I�����4�Hpp�D"��PYYy�����7r2>(�=2}�t���l����y<������Js�p�����Y.�H�3w"'����S����������2e
�r��<�JsOM�4I�/`PPP�?� ��~*"�+++KJJZZZZ[[�����d2uuu
���a�	���������gff>{�,;;;''��������?�����ddd4f�KKKkkk;;���GSS0��|z��Rizzz|||jj�����<z����G�������^�����`��|>�����������V]]]77��'��9s��a0�{��`�C�v�r����_~����.`���aaa�������������H$O�>=x���9sd��vvv�|�Mii)��SA�g��������#VVV{{��;w������H$JJJ
���e2��g��u�K��g����n��MjjjZZZ�6m�����_�D����d2������%	5]�

�g@�Y"�����������m[mm-�2=z����a�����~
9A�������\\\8��-[`��geeM�2��d�^����v9�:�Y*����/\.��O>��}��"##������<x���m���������p���'���������p8��wZ�=�\VVfmmmbb���	���J����g2��V�����K���a�_�xa```ggW^^�����UVV�3g�H$��;���\VVfbb���,`��iii***.$�M���C�4755YZZZXX�����������l��-[�����C�4/Y�DKK���v!}t��Q�q��M������'�������(���������A}}=�-���I����G������.��jjj���6n�Hl�d|h��}���x�W�^Q����Gb/E��w/��+..&�M������������UQQQSS�>}zbb"Q�`|��f�Dbdd�f����y�&�a��������p��
D5H������5��k�?0>tH����1����������#Gvl�Fl�;v����nkk#�5*�G,;::F�+������===	�����C�-Z���Lq���mSWW��
i.**��L��\�x�������z�n|�p�vJJ����
�����;;;���r8}}�����7ov� ??���~���oH��������<%%��������V�\I�^���y�@�����0,>>��6CCC���L�4���Jv���a\�p��)S����cdd���������9��a�V�^]]]M`x7���i~�������6���;v����B����6..���K����p��;wd����;w�����������,Y��lZYYI`
]����4jkk�n�`llHOO��gODDD]]���oBB���n���������$�������������G*��\�RWWWWWw��eCC�W�^m�����]��|�2@(�fZZZ�;����eSKhh������.�4�g���p8�o����mwt���w_��-����5t9>
��;w��}�q\$������+  @UU ;��q��Kp��==���C�������}���l6������KKKPSS#���(,������PTT4b����DN�f:���:::�o����0a����333'N���b��}������(��������=|���6=<<��=����bquuutt4���
t5����������M-������NZ�palll}}}}}}LL����g�&�������''���0�r��.]���;��R�TKK���)��+W��U+++/�n|����[�x_]FF����MMM�l��������c��k��4����=#�5��'""���UUU������o������:��������8��f������D�6p��i�q���}����� Fii)��;r��m���I����W�^�]���gff���N`�d|h�f�g��aaa���
��~IOOg0���#���0>�IsQQ�������a�w�`���>>>d�C0��>i�q����]�t	v!}!�H����ZUUER�Z���u���x���d�����5k������H����C�4K���s�jhh��������R��-[�L��+W(����C�4�8�������-U(~�����3��H���a�q�H$���c2���m�f�����������o�%��=�,s��iUUU777�������[[[���Q�:������q��)++������v9�_AA���/�a+V��{�f�C�4�8.�������jbbr��)�o�_�5�����JII�XI:���,SVV�`��ennA��+=���7m���������~bom�?z��@I�LAA�����o��������bqbb����Y,���C������Lv�}���3��,SYY�k���#G���������,bO&777'$$,]�TWW��`x{{_�tI����(������8~�����������RMMMggg'''{{{+++SS�^�&
srr���333322�<y"����������chhH���<�8>7�p���JIIIMMMKK{��5@]]������������XMM���������|>������H,�X�1c�xxx���yzz{_',��9y�dBB���o�0>���/_��`|P�;���������)(((//////))iiiimm���	PWWg2���������G��;v��1��~h�q]]�k���v|

�����ciiI���4�Wuu�����K�f����\�z���/33s����k��f888���;vv!��q|��q&&&W�\�]�G(��0�`���'N��?����r����O#""`�qhn&��{�����>}jcc��I�R�6�rN��:�&L����~�:�B�����c��������`��������!�---'L�p��Y���Z7���g��


����k!LdddQQ��k�`�Sh�Aooo@RR�B#�������333���J31
�����DDD���)��Y��0>>>����.�����~��_|abb��^@i&����+**=z��<y����?���Bz��0vvv48N�����w�}������)�f�`���M������.�n�
��^Ci&�������	y2,---?����e��rV�f"M�:��d�����>����e����J3����]]]w�������y����<�z(����H$���_�U(n��v!}��L�����������X���w���z�jbcL%�f�YZZ���(�b�����_�v!}��L<�;�\WW������ZCCv-}��L<��VTT�.������r��]��~Ai&�����\��7`�SUUU\�v�������x***
�t��k�����U�`�_(�����IHH�D�������~�m��
***�k�/�fRL�>] ddd�.��v������b�
�������fff���(++;v���M�x<�Z��L������q�~�AWWw����!J3Y|||���JKK����G���]kkk������F��|��N��LQQ��'�l���7\ss���;���TUU���g���`w:�s�\�;��������������G������C�+

>|x���eee�F�R��(R�
���������L�0���Cyyy������			vvvwww�k���c2��
�p�������#G���
������xOOO���f���o���~����/JJJ�U%2j�(�X,�P�1�����7o(��@h�L"__��������a���!C�PU���FFFn����d�>s��y���+������X(�$266�����8�@ HII����_ �c�ss�y��u|Fv	����/��2b�.�kjj�f��+����_�~��1�>�������<y����<y�a�����������%K:��������������������-,,���_����
�����7������I�T
HLL�r�J]]]]]����


_�z�}�v�j�/��N4'
544:���d�4���k��������cv���N�4h�����~���[jj�?��-�������~���.�Z\\ljj������
��������w�^���;����o��}����o������l*�:��4H���������t�UYP��}KA%w���v���m�����	����~R���"m�����^�~�a����q����������� IDAT���DUUUqqqVVV�i��QP���S�����Rjj*���8&&F�n�r�����_�5���
vvv�V���Y�ikk����]��;w7n���+W�|�6++���z�k#
J3�l�2|�p����d���X,kk�����~������<<<>����WWWUUU�cnn�e����F
j#
�+�
������{~~���9�n��5e�����{��IP
�J3$��!C����|���P
pqq��x��7��)��iP��dN�:��(�����=�����f�DDD,]��������q�0a����B�\�Chn�����H$���>..���G;w���_(��LGG��c�9r���R������I\\e�B��~I��'OR�������������"47S���������=���#�T*���=z��K�(�N�u3u��?d���l�?>//��o���;y��fJ-\��������b������ce�H
h�L)�����$�={���W�]�JWh�A)��r7o�$��P�c���s��:�J3�
���D�����������m#�9��L5�s$��s���}���,033#����L�����y����'$�������81�f����vz��H$***"������;w��������bAi��a�'d��������~����F������o���:><v�XCC���_��U4������o��,����``�d2�v��P(d2�l6{���o��ill������50�4SA,=zt���-�;v��r���m�C���l6�������xeee���(�J�
L&������]kkktz
7�����}hV��(@$���_�vM,��w���B�4Sd���,V'_�Ri��\XX(�bTF(���S�N
6l������}/W1�4S���^�x���b�%I�Nt���l������M���x#J3u,--�������J�����=�8��#._����=�4Sj��5^^^���oi�����;��f�mll<x ��h@Ai��ajjj�V}H3���?���b�����}[���@��L5]]��'O��K���u��7o:-3�L����_����3�f>������{|�ss���L�����k����	(Q1�4�q��ccc�i����z�Baaa�Y���p.T��4����r��Y��p<��#wVXX(��1[�b��S�:�b���T�8;;��w[�nUUUmmm---����D�@��f0l6{���FFFJJJ�~{aa�P(d0_}����?�7�4CP]]����g�����*++����d����mbbbiiieeeee����������'
jV��m��}�6>>���[���yyy���d�����������?�hhhh``���W(��|>�_ZZZRR���������b�T������?y�doo�>�����\��������������R������������S�|�������?������VSS�s�NFF���<yr``�g�}�iA2���|�������[�����p������������������3g��p8���6lx���?�f�=z������`XYY�n������c��YZZ2__���S���@i&Rmm��e�X,���Udd�D"���X|��9���aaa$�!�'�f�������_�xJ��%�H"##


����4���n���l6{��
MMM���_o��]�~=��
P���:��_���d2�������r����1w�\��������3����_M�4I��j��2������'666���4�g���;q���\�j�UrO�������X���p����������L����a�;[�ne�XW�\�])P��"55����\�v!}��W_�x�������k�������2..�WrB'�H�O���������~D��x?�V�Z���v��)E�2��d�>}����k���]�`�9(���t�.]�����x�"�a����]��J�w\]]�LfJJ
��tw�=�a�n��3�]]]�lvrr2!
���N�$--
��?���Qw?��'��������'�M�r��������\]]��������, ���'�������	JsOI$�+W���?���KJJ�������m988���KD�^�Ci���O�644L�6���b�������uuu9���~@@@�_�]7k�,�o��6mZ]]��g��m��6�������

��Od����7n�u�X���v��1�[���=U\\lffF�1f�3�w������Bammm\\���W�����:t��)Du���d����2h��������&�Acc���������+++OOO_____�N/������NMM
-S���Z[[�����������������x{{�n`�xM{{����G3�������BR�C+��4hP]]�
���������+  @UU�����6���644���Y[[���������Hj�bhn�)mmm���e�-������F��1O����M����bWP������������}KT�g�����b����::: {h�Leeebb"���7oQ�v"^�xA��O147�����D"����4i!
������v�dHHH����;'��O�.{T&<x �J����BssO�������`FF����MMM�l��������c�>��
�111c�����'�J�>��H~��'

���f�����I]]}����!��{!88��������!Fxxxkkkpp0�B��o����W�?�����~�@ 033�?��}�`�B47����[���~��������/�����.�P��:����c#99v!}w��-�q��	���4�"((�������:t(�Zz���;99yxx�����k!Js_www����555a��������l6;%%�~�@���������ohh�1c�o����������������2@i�3����7o�������k9T\\���ZSS�������@i�;ss���eee���$��|HBB������Fzz����rH��P�����`06m�������Z[[7l��a��%Khs�;(��������433����`���bbb����y����P��0o���;w.�����X�'O�y�n1�Ai&���7'L��a����]e���d7:::�����J3)�]�&�h������d�(�=jggpqq���'�G9��L��~��W���\.��������v����'N��1���jhh���
��^v@�I���r����/^�v���e���...���666����
�Uk���������������+__���������l�3�TjiiIOOOMM������
�CCCSSSCCC�����B!��������EEE���UUUwwwwwwgggb�FP\(�������:t('''''���D���
�H$d�2


6�=t�P###��Yw��u���E�u���@��L���tWW�[�n}��'}����'���\�p���h��js��)))�������<yr���F�:
J����[���-`F���t��fJ-_�<!!�����"1  ������H@s3����O�>�z��~��|��-��
�](�������������~�3c�MM���(B���f�477:th���***�l�����=���s�F'(����hnn&��������������F(�T�H${��	&jD###��t�O(�T���-..��aQ
2��?����s�����:*8882$..��6�>}jggw��]GGG�Uhhn&]ZZ����_Ol��������o�w�4�n��=NNN�����<o�������b�[VP(��������]�v-���7�������Lh�L�������[yyy$=����������3d4�p��L������O�Y���(����\����DR����DG�QSS��y��

���-Q\(�d���#�6�A�M�6
��Ai&����[[[W�\IvG���			UUUdw$�P�I!�H���;��w�M???��38�fR\�r����?������5kZlt��$W�{����������("M�# v;!*���DcKb7�Xb�Q#��
�����
�(�a���W��c��^�p�w{e>�s�o���������\�&��>|8r��O�>���S65�'�m����xi<����C����]�pAf5�'�m��q�����'$$��������w/33S����m�������uK6=������X���4�+W@7���}�lmm��/�z������������xRTT��O?�H���S�^�pA ��j9�O:�����w�a�HH��X������X�m��yyy�H�N�]�v���OKKKKK���O�r��iW	����������tt�,%
����g�n[��/�������+%���78���YQQ��>��8qBz������[�;::n��!##�#7��K��y�f���p6o���h���RR�;���������.\��>����hhhTWWKIFii)�B�r�JG;t��u�����[�����_��P����SPP���\TT���������FFF��
cd���'�3f�,�6�>}��:�C��IIpss�4iR�����p��=�*9s��F������nhhh�,KQQ���X*B�t3`����/;�{4hjj����*�����`�����~����T*����e!���F��P){8�k��A����w���������{�
CSSs��1*���������� ��7:����QWW���H�}�6�D���o�QG_�r�4`�,){�����3fL'���q�������o��2�4r�HCC��������� ==�e��7oD)��QTTt������w�B��h5b =(Jhhh�:����������&6F�}qPl��Ycjj�����>���
�B����k'`7�o��mU���.zz�e��VOO>�,�8�,>�����7w���������Q�!
{���f�l�+mY�O����#K��,>���c0�����������*���c2�B����Q��������������������f	����	�����;v�����>,���!>>~��ADk��.PL�\�RXX(�t��`oo����R���b�k��I�&Y[[-�3���/]����D��,O�<y���,���)S�p�����-DF�~�8744`����Ze���&==������0c�����y���-D@7w�}��999-�K��*������f�;w�����Q������"#�������FFF�+F����2��
�\�_��x�blJ���:��C7w�'N �p�B��t�Ye����x�={���=[[[�h-�FEV��n�*�/_.))��G���"��C7w	E�o���7�XXX�ETd�y��.�����o��Z��h!������/_-D��'�]b��Q|>_�����o``�h
�P(|��m����U�#�mn�+W�\�|Y�:�������_�b��$G��|zz��U����'M�D�(\!�]9e���33���������1����hQ8K&�---X:&�I�(<�ms;`y$�|��|��=z\�re���D��������>}���������J��$��$�xzz�<E
A��������u�c����d
��n
t��	l�������&�9���������=#J�L�6���A�P���v��v(++k[(
I$Rzz�����%�
�N�w�^�=���*WO��5


uuum�)���V||�l�o������[�(J������V�
���������2���������C7+9m�L&��T����]]]	�������/ou/����r3�D"�H7o����!J^���s���-���J��[����+��
#V.�����h333�!t��SRR�}��2��.];v,��pC__���{t:{���)9%%%�����'N$V�888`���k���Q2�|~III^^^}}}CCCcc#V���M&�������
D��x<Av��%���2f��������e���hqq��/_*++y<^mm-VN��544����������t:q��������)%%����������cqq�WRWWW���tppprr�VK�����5��R__���+333���&�������=z����trrrttttttss311��������Babb���w���������������mmm------�Lf�5'�6��f��������������tE���
4x��1c��y����������>z�(111--������fgg/]������d���ak�������������f���fee}��!77W ������������r�lBf����'O���{ccc����?����Ibn��)==����&M�z ...���{�K<�9����O�7n����Drww�����]�VZZ�� ��


qqq[�l	f0$���c��-���6
���������������e����L��c��1x<�����ccc2�<q�����U�Ta�X��-�����h�G�>z���V]ihh�}����s����d��q������4�s3��Y�j��������U�X,�l�>���o�d��������l��.�=����.)���UUU2�Zt�(J��=������F��0nG�522�������:ZGZ����N�0Aoo���TB4tDfffHH����������,k��Y4���N���(����y���C����]+���=��
#��K�,���&ZZYY�d�*����G������?g��4x����_��Fyw�P(��o�N2d���]���fff�������x��)��466>v���^�|���I���m�&myr���������g����P^^>v�X���~��.
��_O"���SRR"{]D l���J�<X4�"
���}�����JII!ZKg���{������c�\�������'�h����Kf�JBrr���������T���������...���Dk�7n�����4i���Au������O�<�AuxQRR���ehh���+i��G7XYYy{{s�\��t���MM��3gJ�S���0t�PG�eF}}}pp���aFF���������L���r��t��w�R���k�J�
�P8n�8}}�7o�H��R__`jj���C�s���s�������"&G�!�H�=�R�]�vQ��g��I)�l�r���������i���o���|�2�B$b��	�������G~���F��u+��eOzz��������cL9rsSSS�^�&O�L�I)//���_�r%�a�B�������*���={�������9r3vl9992����z���}����h������/^�1�������rssq�y��9�$�������[�zzzboX��O�hnn�����I�$�!/n���K�.�A]������X��-,,V�X�W@E���;m�4��+���1�8&&A���,\���������s�,Y`2���]�p8'&&���A[����&�a�������q��
�8�+�t�@`cc��O?�M^�<k�,ooo���%0n����������UKvv6����D�������K����S�}�#""����P���v\\��#p���>���mllL�����BCC�����nnn-�www<�/666vvvqqq�D{��IPP�$:9!�TTT�b�p���oBBJKK�{�.�1g����������f5��9s��a���p8$���������+���9������<�\�����>}��3::�f����+**n���5��G���9�����������_�5k���G
vvv��������
���������J���WNN����"AEE�eR�a2�,+11������9   $${5c���������?~�h�������c�&�CC���r��`A�}���trB��z6� IDAT%=���@ss3�1Ze5j�hpqq��E�����T������;����9s�F�I�������zI�t~BDt��;'$$d�����7?}���|s�����c����P���A�o���q$E�������H'!!�f�%���B������/_.y��i��������xA�P|||�L�����z�z��A�{:t0u�T���I�=��sssI�t������2\��rqhgg������+c����={��f������+W�DI������������[�nTTT�����IK��W���bkk�`0���%	��	!������?������;.xyy���8l�`����������_�["
����z_000�����$BwOH[{H�B7o�D������u��YXX�8�5))i��9666T*������'22R���AAAZZZ�����iS]]^Uc`7o���%��ahh(�s��O�n�9s�����A���(����� ��[���S�L����+Zqq1�J����+��PZZJ���=�K4yq3��~~~��'Z>��������6�����4��16n�������r����X������S�N���mjj�1fff&�J����1&�������o����r�fEG�������@��HLL$�H����=�?�`bb"�+�$,,���Z��B-�/7ggg���.Y��h!���r{��$�<���={����O�����&����,_nFQ�����\�z�h!� ���LMM��|��������)��
��?�����q#�a���(�����jjj���D�6K�.UWWOHH�j-g��!�H;v��j-�#%%EWW7,,�;Zyt�P(�2e���N||<�Z��P(\�v-�L�v���;p���M$&&����9�[dyt3��MMMaaajjj
��hnn����h4��3gdV��}��d���3�a)q��5uu������Zi��S7�(*~��g2���o��&U�x�������7���7o2///��m���~�z2��l�2�eR�_7c�:u��`4H>�����������...��������
,���CGG����R�H����hVV���544"""p����?��� �h�"b�W�XA&�����F���TTT,[��J������+�]��(��x���w3++��'O��(..^�l�Nwvv��EFRSS}||H$����e���s����l����obbr��)��+��1


f��A�P������d�z��l6{��U������{�����/�
�g�����#�����D-�URR�q�F}}}--���W�r�%Er3����##�U�V}��Q�5���L�8�B����������8������]\\nnnG�����|��{�BCC������p82��%��f����;v�������i��7o��{9�������y����I$��Q��^�*o�q'�|�r��:::4m�����1���������3g��������/5h�����(������/_�r%??_WW����������������[������{������������k>����6i�$)�Tihhx��ALL��[�*++MLL<<<<==������hmm�%��:'######99���YYY����&M?~<�k�+��E�(�������������/_�������,,,�L&�����j�_���l6��f���~�����S(�A�aq@��������={���,}�����377g2�fff���[___PPPXX�f������������/zzz�>��P7����"##���w?~,,,,,,������ohh�����M&�������-,,,--����t:��e@EE��w�������������/_�TVV�x���Zl:�������fnnnff�d2---�Ui�h�e�r��.]�������Qw�Q�FYXX;v�h!�C.2@�
�$�V�m��!�@&���!Jt3Dy�n�(����L&�B�Ut�fH;�1
��{���<@7C��f���Q�Dy�#t��4 �t3Dy�n�(����i@�8�Q`O�<@7C��f���QH$��(	�mV0
�����������������??;;�h]r���,k��m^^^$���s]�G6P��@^�x1l�0Q�@����?�|�����{xx�M������;we���m��e�jkk===ccc����\���O���jkk�-[F�:�����q��
����}d����iii���hkkk�$  ����666�G*���������]�G6�h�lnn��G
�C_���"�r�J�������kjjjjj�������V�"Z�(�����4�������u�VQ���stt���~K�09AA���m�@ `�Xl6�e!�����P�+,�@7+�6m������O�\.6�akk�y������6�Y��� d]7�x�"����j%����#���W�^��|QIW�B��T�m�p8m�>Fee����$	�p�
u���; ,,,..������4����VG<d2����@�����;������\CCc���D��07�V�.D�h�.uW��
*�6{yy�����=����F��h4�9s����yzz��xDn&ZH�P����O�����BN��+������P���9
�6C7C��i@���n���i@��f���Q��!�t3Dy�#t���A����(�����<@7C��@�gr��(((���?���6Q���T*�D��������	�P4hP^^�h���EQ��$���O����i�:�?[����g�����-�MMM��$M�@���;))����D"
2D��T��1k�,�#�A�N�*c=�����;�P�(.c=b��=
@YY���i�^ �L���{��	!��gg���������ZEE���!���J��FFF����6���O���e���m��J3f��[�����Oo�������PB��'���m�f�����'������'L�@���-/�B5j���6Q���=z������%�[������������`��iJ�Of����y�R�c��USS#PR�Q7���[�jhh�3�@=���	ZzW��@��,1�R�'NT�&G�hhh�����.ihh�5�XI]G��L��E������1c���)�����D+�**�f���S��I__��aD��S�bll��x��n�j�900POO�j�"�D"aO�455�7���hSS��/_
���=<<���ojjz��=
����gnn��Gb����\naaaqq�P(4558���[���$������B�4���vQQQJJ������_ZZ����R�����{�vttttttvv8p�����P(|����7o222233���������������L&����������_�~�����(��������������M&�������������,--����L��������)///,,,((`���?�����*++�R����6l��!C�`�E����{��%$$$&&VUUijj���,YYY������;w.,,�i�������������_������||||}}G����J�1*��

N�>}�����MM���___???77����r�n����&$$�������������1b�������h���������}��f[YY������v���W���,���g������������c���:u���/��5d�b>��;w��3�L&��7���;


R����(22288�J����O>|�R]���r8������DDDZZ���KMM��aC��}}��=x� 6�_�(�����gccC�R�����b��eCUUUddd�����
KLL�Y�����`��%���FFF�V�b�X��=33s��U���c��%l6[fU+���\�bkkK��������E��Px��
oooA��G��v���Y�n��������]�d�:��r���o711a0���[mm�*U7�������H�y������9O�<8p �J]�lYUU�rP�Px��ISSSCC�C�566�EQ�������������O��vur�f>��u�V*�������B�����G�Z[[�������x���d2y���*i�������1c����H�"�usqq���?�F��}�,���E��
6`kS��G����*O�>e2�=z�����T�����b������{�Z�
���'�J
ojj�e��N��R�aaa����*���'N��hg���F|ytsrr������oYY�Z���G�tuu�RWW'��m�� ����	�&��P(\�z5� �v��=���9==]__��1�B����3661b�n����� Hdd��+��F��?��7�|�9//�G�C�UD+c������N�4I��eTT� ����^�f�����?��r�f�������TSSC��x��)�B�������^SS��_~�R|��l�2��������_UWW��� Zl���N��~���MMM������lnn�=��ijjrwwwuu��X���?~��h
}�l�@ ���4h�����w���}����D���G555��c���q��9::�x<i�����u���'6)���bbb
�`0��A��]�&I�/_�$�H/^�$H+JKKuuu��]�cL_=Kiii+V�0`���&�F���������%�w��Uzzz����A��������qCJ��2mp��=m'���W�z'O����*I�Vl�����PJ�_=K������KOO��^.������H�?
%!9K�,�����7l����������g���y3���p8�7o�h���l��}��9K#+9|>���b����Dk�W������]��������\����mll���V���?[ZZ��|	��f�P��G�M�6������u�����[b���_�^��.]*IO�>dff���>����uuu	k�~B����!���������H����>|�������F�������>z�����%��1cF�Bl�����Q���'666���bG��,�������#v'''&������� 9G�e0����=�+G��!���[���%C"��\�$A0F�1m�4I"Hx��r��1@PP�$�0�N�*y�����\[[[	�[DGG"""�lvsssEE��[�F����r�}}������*I�����B�z"����#I�$>K�x����?�� ���k%Q���O���l	��O�����$0�L���������BI022���I������
�g���w���r�k��4h�$�0������%�"�5BB�O�>f�	�$$$X[[�<�Q�F����!K���%��u��$A0���$|}C��$"11����7���S�NI~7I|OC__���B� >>>?~LHH��cGhh(���w����K���vvv������o��}$6��I~����s8I"Hx�0���3l�0�3��#G����K4�=
.1P(@vvv�^�<x���
LLL���j�����<XUXC�.'J��8u����s�|���<�c����2~��\&$����$I��������9SPP���JKK�o����h�[G�,zz�e��VOO$�q��---���(>b�I"Hx�v���}�d�Id����Cg��!a��\ZZ� ��;w$	��u��y�|��k����={$Q�������
&a���kkkK����,u�@���x<������������+����$%%��3Kchh���)����fEcbb|}}555555}}}cbb$���h}}�������%�����A���+v	����|��mA$�(n>|������:/!'N����8��8d������� 	;Qr����JMMM\fQ�|>������8�<w��B��[U222�d2.Sg���(�n��E]]=//�h!���_���O�>�S ���2������������������r��)D�����=z,^����?\�z���p��e@ll,.����(����D"�<y�h!�"F�ikk+��-����������������]�h^���(����o������D��������K�W���WWW///�~������������#��f>�?q�D}}}����*[�n%�H.\�j-999�����Y^%|�����������NI����hcc���C
���m6n�� ����ePWFF���A@@���Au8RYY���odd��{4r�fEkjj�������������7o�L>x���*}�����Y�>}�9�*���NNN������Q���?��#� ?�����n�AAAA``������������E__����2�Z���kbb2p����Bi��S7c�>}Z[[���M�dh����� ��O����v����,^�Xn�����K�,Ad���)�nFQ4;;����F����O��A|�������d��U���\�~������"**J�����'Ob���yS�u���Q
�'N�066600��m�<Keff����H�A������Y�h�L8p���7	O�,
�_����B�P�,YRYY)������+W�d0�7o.--%DFJJ��)SH$�������	wL[���BBB0`����	I����t��EA��������0n������a���!�F{��.��Jee�_�5`���.]�$WW���~�:,,�B�����^�Zf7���+W�466�R�S�L���1�����/^5j�D244�����]�&����?>x���a��T�������pi�N�����m����prrZ�v����qO]�������f�,Y������;[�2,x�m��/_�_�+
���===���������Z���*(�����{�.==����/^�())���;v�������lc�z�����111YYY���8p�������Y�ijj���|����W�^�x���������0q���'bW0BPl7��p8	�%55���`jj��gOKKK333&���������

���?�\[[�����������������k���?^�~�����O�>	
���W/&�ifffee��G�������������������|>�L��������A�|}}mmm�8��AI���P�������������|��������������	�MKK�B�������#����k�.'''\�-�'Of�X������������YYY����Y*..
�X�
� ���.�D211���055e2����t:����_d���CJKKI$�������A��*�X��mWW���H��H��#G���={��h!RAyz�|��qEq�x"o<~�������D��m�/^����JOO����Z���=z��}�6�Z�l���������?����n�z�jjj�����"E`�����1#///66�h!�������<<<��9C�)���'((h��UUU���Dk���'O������h!��������Q�>$Z����GDD��7�U�f�����������{�.�Bp����555���+�B�t����-$Znp8��[�._�[�B��n�������SSS���v����+V� Z�,�n�\\\�������������o�����Zdt��� ��Q�����y�fSS��-DF@7�&((�����,�B,,���c���[w�/+.��Ik������N�8�����|���YYY���$���Y�r�]G[[���W�;/^��|����U������s��m�������d�����#����u�gG����s8���d�������>|�m�6�����vprr���R�����W�=z4.�_+�����������[�-�`��}n��9~��/_������������ms�:�N���w�h!����i�&��l�;d������/^$ZHW������whh������
�X IDAT�B�m���������x<��t������_��h!���!���\.7))�h!]B�f~vts�������*�8���;�t�/��B�"�n����`��c�����W�����AAAo�����o�����u�������t����K�.�X!F���,k��m^^^$��L7�_�^�r����N���]�hQAA��UK�2�)


G�m������b���2���I&�O�:�m~��m�zzz�����?��_!$$d��	m��,Y`2���]�p8'&&���A�W�^�RaXXX���E��7l�������]]]w�����VWW��ro��mcc��li��:�`0��mii	x��I����/^,3y��?G�����~�}��@]]ou���+���=z���J�Z-�U]]
pww��������Q��\SS011�S�����d2���RRRZb�H���e����G>��y��q������x�"�N
�/�����������0�����c��k��1�L�F��*�P�����]�~322ttt����U @7�7�je�/_�`]��`WSS�����/�H�N�0���322LMMk���[ @7���f���*/..^�h����J�����sgbb"�`K[������>}z'�|�������]�����e<���KL�8q���_����~L�4I�z�=J��srr:��s7��}[CC0�|��2
��E���ouu����N�)**���z��T�������-Y����:q���'�e�.\�4VF�����/_���Z>x�����������vvvi/Z�}�vmm���4���w���}�������U\\\Z=i;@doo�f��*���BWWw��
�����N�����*^�����|����%<

�����������M�^�zenn.Up�gg�sR�������PPP����o�>5�3�m�*����Nw�f~���j�g���
�L>|8���dff;vl��
������w��ATT��y����	y�Cs~vx^�APP�����e_5��s��M���������9`�����K���1�������2�W���_v����'N��Rl������m�/_����|������ljDQ���������[��Qq�ms�pss������we�fUX�/`��mf��YPP �{A�������%���6wlqy.����#�����<�vE���6#G�DQ���G���������?������R����������
����������;^@7����To98��m��/_���
���\TT$�q8�S����������x8���r~�Y�F�s~v�fq@$((����G�7n�����-[����p���[�����G��Msss|||CC��O��L&�DBQ�D"ikk����+����-[�L�B"����'N��3?�tsW���u������d�@ �B�B��YYY��O��y����O�>��o�i����^5�n�*d29==]�j fe(�������'�������^�z-\���x�����{�L�
�b����w� (�������O����R6B�
ts7����.]j���=�nll,**j
���1}�t,�.�+@7w''�����]OD����O��nF+� ���oCC�8BU��n�t��#F`��["��333�]k�J�:88��������R%�n�6�DEEiii��r��f��v$�B����={��G��U=����������z���Y,��oYB&�G����]]]�T���b2n��9s����m~��m��>�4c���W���tT����������_^^v�����;H�����Fcc��d�����mk�'
�*�mMM��g�b������;
EVFd��}��@�|(����6mZ�n��hhh���/..��x\.�U�H$*�jjjjii������?|���{�������P������,99�������[x�s��������������}�R��/_;v��U+9�����������?���g�X$������~��i��=��u������y����f6��f������������+
6lXSSSMM���!��4�������}�����W(���xyy������>}�t+l}}���c{��������D"����7�|����:$��B@�h�!;;��������hc��=}�4���1~II	�GEE��S���C��V�X��zS�v�nn����������YUU%�z���"##���H$RHHHZZ�l�U��[SQQ1�|
����|��i/0�.|>���s���~�����?�>}�����d^�t��D \�p����G�QQQ��Q������8q"�J]�bEmm-�r�����_~��B����VVV-G��c����o���L&�?����h9����4e�A�\�2p�@���)��6�y�f``��������oo���_���/  ����D��W��8�����d����	�%w>��p�B
�r��i���#*����/���NV��O��[G�P�]�F��Cu�O����G������������"_��] ����������[�1s�@ ���SZZ������"qa������'O�TD+�d��S�jjj�.]J�y���$&&"r��U��H��K�y���B�U�i��������8iWTXX�g��G����566ZXX:t��U={��%>�����T*566��
�?'Y���x����+z��y�������'O/_��+�B�rn�5k����*��xzz���VWWs���O�������q����s���1���Zn�������w��A]X
�V��srrjjj8V�c�}}}�x�#m��^l������F��W@>���aoooccc�fff�-�fnn��YXX�%0r�H���b���s�)�������={vGg���#OO������������Xwww�����E�|���Vdd$�1�j�sssmmmqc���DDD���������[�n�10��s��������kkkkkk`�~���x	��d[[���\c*(�����
2�L@bb��]����8NHH�������b�������lQ&}144,//�7�BB��A�L�:u���8LHH���ny>G�����~�z������O�\n�1�_�G
(��;6<<����j�y��E�������x			;v�

��'O�������`L���_
�
Z�x1�1��c``���B����������{�������i�3������WCyy9�=(E������YYY555x���?{�,�����eeeW�\`���������������������0���.������}��SQ!�� S


���/^�=����CQ4))���t��?�K��>�SAQ-7�(jgg�d���%%%��3����J����DFF��|�S�5{�l�F��lll�������W��-rpp�7���rn��m���N]]�B����V[[{���D�T�����;{�,�B�����


���D�Tq~��%K���?}���� q�\[[��������h-r�����u��566���D����7�x�5k�-Dn ��C���$)66�h!����c�t��q�������{����/LMM���m�l������������"G����\���� ������dee����J�����K�D��:::w�����=zt�O��������������Z���f������������������urss}}}���>|��$i��n���a��=<<�G�r����===uttmmm��#�}*�����=�D"�Z�����h9�ihhX�b� s��U��������p����������7����\�~�g�����/^$Z����?M�20b��3b%%%
:^TTD����=z���� ���c	�*�������q�����!w�������=z���J�F.�{��������w�]����^�z�`�mmm:�r�����b|�(**:~������t����?���}�-�������K�.��s����g��>>>������������^��a����y���������MM����o��&88.�-6������>111>>>>>>99���`aaaccceeeaaannN��Z�Wss3��f��������������������������kW�n�,>(�����{����wyyy�Y���y<���^�&�H:::T*���������������������A�B��n�����.]"Z�
��O�!�t3Dy�n�(�����<@7C��f���Q��!�t3Dy�n�(�����<@7C��f���Q��!�t3Dy�n�(�����<@7C��f���Q��!�t3Dy�n�:,k��m^^^$���suuu[�lqqqa0����G���U����NZ����rp�'��f6,++�U9�v�l�������
222:�A ���fee������\.����������P����{���bbb^�xa``gbb��5j��Q�W�T���x���?�������n&���d��Q������W/:�ncc�t����r��)���SZZ
8q�����������sss8����}�"�����)����k��q8�caa����a���)����`0�N�?~��������	N�>
�u���	�f��������,tww���@�t3�`�MIIiY������I1�n&����f��y��������������90q�D��)����������g~���l����s||�����D*�m�������(___�A�������]�����-`�,-���������<@7C��f���Q��!�t3Dy�n�(�����<@7C��f���Q��!�t3Dy���q���#[�n�fSS�N�c�d2y������'L�
���>}���wG�"����^�z�R��{�akk���F"�sJqss�V�6��x2c��v�L&�g��!{=��i�Iii���)���%d2�������U�l�����x���d2�e!�L<x0���n�,�KW
!�{8S]]mdd���,*��heee����R`��3����������P(!!!�����M�&z�"������:���466���FYY�����T�6����Zhh(�J�R������2�Y*|���<���}���DkQ!�z�����������{����\UU��7�~����Oi4����������hw���������=y����'���4���V]]]KK���A������������?777S(GG������@===�B��w��������g����>�����C����tpp�����%%%!����m����������������H��#G��1c��1�o�(�����/:::T*u��1/^����hg�P(
;�������!!!T*UWWw���EEE�Q�B@7w�����s���tss�={��������l���fffjjj,(,,�+�
{_������?""B__����g���6������������������nbbbnn��566?~|��m���7n\�h����D�������~��Q��5k��������/_��;7w�\777--�����������y���?�Q����v��T*��������<2���r���%K����;v������%%%���g��MII�P(pwwwrr���g2����������������|������/_�����|������'�����1g�����C�}��w�9X%����<�����E�v�Z������?��=�J�jjj��9���{555]^SSs������kjjR��9s�dgg�����y������5���I��Q��[SUU5d�}}�G������d��yT*�W�^G�����R]]}����={R����������{:::��
�����"���(**������EFFF�r>��o�>]]]++�s����|�j��xg��e2�zzz��g���^�266vuu-..��F%���������_�>}���[�P����Wwt/(!���!C�|����GYYY������\.WU+����������������������z�����,m
��?���666~��i����?���zzz���J[�B��&O�����j\����t:}��q�<������v�����)))�����M���EQ���C$	�w!����d2y��8������;w.�B9s�L��;w� r��QY�Q,�����D*������kd2y��5D�Z�r%�B�y�f�����������T�9��f��������r\966�5A�0�P�������?{�LT��������_.Uw��;���>}�$*)**2117n������G�633+))~��AMMm��=
�[T��l6��`������������ '�555���-Z�������m��v��E�������E%����������jErr2�F;t���������r�����OT�����T*�����6��������~��Wmm��OU�9B���l6����u����������E%�g�n�T�	���L&s��y����Fss�e���JQQ7���2���w�J>}�D�P��?O��N8s��Jm9�n�����Rz������O�<I��+**D%3g�trr��>���O���g�J���i4ZTT���
us``��I�D����4���cJ�*���t:��+����>|8���
UtsII	�D�z���d���:::


��*uuuZZZ��������d2�WnU�����c2�<b�Q������/�I-444��{��QIPP� ���/���
Ut���O����YTT���,��q��]�������������~��$����������RlSKKk��O�<�C�R@������W�^-�<s��N�����={����{������J�^�pAT�b�
'''<�**�6744|�����CT�������oE����W�l�����p8���7V�Z���#^L�1`����XQ������rw@T��YYYB����AT���&��#'N�hnn_�n��������u�������O�8!vXoo���4�����@ ���#�Ut3�B���'���hff����x��|����������i4���Yhh��G�Xw��������O��ooo�b�D����d29++K���������������h�fQQQ]]����x�������-**�z�*6����@���[���_?��x���q����b�O�����rmsuu����h���`ff&^���h@DD��nnn����u�6���r���-�700TUU�+`��JJJD%���X]�k�kjjZf����t�?�s�L&��JLL���rvv					�Gk{`��a�1���Zn�2*�6c��ZnZ�t����[[[?x�`��}��}��������`��i�EE�����`?���jQ���6t3���m/�$� �E������cBB��;BCC��{��.]
������-�����#�hW��*�����uk�$i�(�����+._��y������@@TTT�������]&�������p�XUw3�������g��e��|>������+�Y����i4��s�����������-[��;w�F���5Kl�m;���TB�D���[mllD�������X���{JE/���d[����9F-��3��;vHSiP���W�^���MMM�������N���"))i��9666T*������'22��������/������������������Y�|�$�Y,���6�hhh`���z��$���r#t�������ONNNXI����~������S�	&L�0���;�������\f�
7��rQ4/(�*��������SJV�=����R�_���4;V-M��v IDATLS|
M�b"��v������� �0����9��3{�a�~��������������Z���W�Y�^���D����z���k���\������o��}h�M�9s�o����^����bX��8�S����c�=v��YC��a���=�}�+X�����??|�pC���g{��!p?�6Crj�a����X�|�������O;�$��:uJ��<��r��q��%�����t���*]pp���?�g��Z��={�4�p�Uee��K���HS�C�qvv>v��!%%%e���_������oRRR)G�uuu}��'h���������~�����R&M����333h�U233���&L�`H��}�3�<��]�p�o����_���r� �����sg��B}}}XX7T���7�������@���D����[�v�!���T������C��U���k'��yD�jff���:t��!%%%<<\ ���TWWw���U���:  ��Y��������s��������0.rjjj���U*�!���>R(�����i"���kAA��2��~puu���O
)��)$��{��,^���������Ow�����k�P^^��C�q����zC�����]5�"i53�����������A����3���s��WW��[�:�0�"u5744���	��5�a��������� �8��E�jf���W*����:7���_.^��������~~~��_w�U���0���������c��������e2���;��trr�q!@j��i��)��.p���===�������1�=5��������������=�m�)��?ihh?~������������aaa��������
����:u�����/^T*�&L���eH��E��������_�z��~����c��d�������.\�P&��9���`qqqXXX�������Q5&H��CyyyLLLPP���0z�~������;w�l����G�������0__���_F���?���_?�K:�)H��TUU=��S�����7����{3g����]�t��iS;K�F����v��Y.���=�t�&''G�T�1B����"�@j6C]]���S����,Yb�G���,--�
*��K/����$����������l	����q��Q�N�h�"''�W^y�������N�0k��?�<---66���?�������f�����m+,,tuu���_|||�^��w�������������eeeW�\�|���s�.\����0p��W^y����i�����W_}�����O>y������Hp��I�\�t�O�>2���7�lj�w����;wN�>=..�B�v�������1c��]\/.��`ll���{�'�7[���a��
��������o������Y���������Z6������GPPE�)���������t�F���������J.pO+����8�q������c��[��;�*++?�����vg��[�Z�d	Bj��[�n-X�@�T�d�g�}v��=UUU�+���_�����7�L����h����h�a3uuu��c��#G����6lX|||�.]�t��N�L�j����%%%���;q��������G�5u��g�}���
����R����ssssss�����		i���h4�Z�.//�L��G�������'�|�����m���ux��QiiiqqqIIIuu�F�1�
o�����w�.]�w����u��h!5x�b�#+�f�f�f�f�f�f�f�f�f�f�f�f�f�f�f�f�f�f�f�fM��a�o��f��q���r�\�P���{�������Kwrrrrrj
;����5x�`ooooo�������N`�����.�0I��<���6]b[��g��u���_��uY�~�����q��7v�X���]�v����^___SS����n��y��A6�n��\RR"��`���*�J�R-_��ryiii�WgRs3����>J����~ki��y�K�.�)S�p�L���-k���BjnF�6R���?|����������cbb�P�111�W���t�-�-��_����������w��A�54p��x��'���,l������?<<\.�w����k�f�:��c��!C�J%{~���
�F����@�^�g�466���&M������f�����
�b�����]3���������PWWW??�#F�(>M.--7n��������Y�jjj����v��(w�'f�{xx8X������|�I����d��m��>T����
n"�000��m�����#�233y��_�z�~�����{���V������������������2D�f/�0a���;�������������7���{;v�~d�����X���������F_����|ezz:���l������w�����/����W�6������C�Y8�
L������t ���7�Pc�N�����juYY;g0���6�[�la[���YYY��j

���`���l�;v@dd�N���t����o�>#����������sss���`��El���G>|���J����ys�������-2[��<k�`'�@>w���4M���>}���m�����9����Z�??������|��QCJii)x{{7��HHH���|nbII	t����2f����O6n��'O65�{�|VV����������>�lPP��	www�M�����*�m�Y�;���3Vi�H����	w��S���W�T���9��[#������g���<==���������������U&����yS�T~��uq��V�T%�����������bZ�!�Z�������3V1�z2p�@p�b�����u�K�.q���G��
mo���666666��z�^ox��=2d�����dZ��}��
������0�f�*..f����C�9[�d�������U��:���b��'x������[������h�7tfk��lV
��dVO��;w.[���+`�����5��v��W0j��&[i����H�������??�u������t:�V��o�qWO���������++++++�m����g���[��z�b�
�������o���1;00v��ey��~����l�r��5�V[WWW\\�y����y�;������X[[������kd[S����(X�d����<x�����C[�lu����@>w��_����<x���C�5�����1���n���i���>Z>f����Tul���]U�T������l��;w@XX�a�f~������|�^�����S��d��V�����);M��|gx�dV�^�w�^�����+::z���g��1����KOO���{�c�>}V�Z�=��[�[f��}����i�����oB��f���1���j�������3M,�x����'����d2�^�z��?�����_�V�����z��}Q��/pm{������������5n�8�z~CC��5k�v������s�w�}�0�������c���������>}���	�Z�����O�����������7x 5x 5x�q3���	<��	<��	<��	< W3#�8
W�\IOO0`w$�l0������4iRNN��O�7�~�oF
F�,��}srrrNNNSqm@��=�y����"G��}sNN�����Jeaa!�a������}�*���Yo���[��N�[�jUll������gll��5k,�<X����kkk�����C��\3�3j���^|���;�d2��#G=z�%���������(p���O	����h�,�8
\Z��X� ��f�Q��B5[� ��Y�q��D�|�H��@��Qh-Z=�xA���^z	V�Zu��U����}�7������c��<��JOO�����q��	�X�x��`GG�KK��xs��G�Oc�4>�$�<�B���O<��ve�� hg��!5x 5x 5x 5x 5x 5x@�fF�>�/^\�hQ���
���[TT�k��v���fe?�rq�y�D�>�f������������(���'��f��l���w���.\���Q�����|����y�m�XA�7��g����s			Z����ofA�7��g�g���T*�����Z�v�������=�����y����w�3���fa�G��M�S����������0LQQ�R�trr:u����ek�p8�D�����]TTo��&���5Z88U"�U��|�

���`�������h��v��v(��C�
>\�R��9s��M����Y>�_~������Z��9s>���J���S��O�<	���-)P|8�����g������������,����m����������pD�D��fF�>���fG�K�+��A;$$���������������������~53B���?��??&&�������k��s��)++k��$��@1!P*���}�~�Z�.)��ox�����7^�r�������G����U����y`�������$**�A��7�1�L&��R��,_����a����8�B���9t����l�����������TUU�<yr�����s?�Z�N�9r���Y07X,A��������[mm���k@�Pl�����uuu������Cjv|��
��y��{���7o��*|`V���0������/��?����xxx���wm�
�g�b	B����7r��}����]��ff0�YA���tP]]m�Ul�ha����?�E�AF����;w�<z�����������0j�(�����������o��YWWw���bC�A���/_�l��B9:�n��aR��L��`!!8}���/����w���}�(��t:��5kX������
�(0�lR�,���f�f�f�f�f�f����a�����V�H���c^=��6�'N�1���U*��Y���f�;l����={vrr��
?�[T�/��Riu��U�}��~��v������bE�nS�m���?|����������111111�W�6��2&���_��������X����+r�|�������,�������������5kVMM
�bq�NJJ���~���\5��w�c��\c��[n;>�6X�l����<����h�"0wX ��w���~���'O�lHi���7�G���� |����ooo����I���
�/A5�}C'|��m��UWW���8��.���V���������{4����R��?vD���4�B���`�;l�b�B���:�,d�mS��f�aJKK��������7}�t���`�uDH
��@B���	<��	<��	<��	<��	<��	< W3#l�m's��"��y�D�>�f������}�X|���gm��A�7���miF��h�f1�m������j���>>>nnnQQQ�-R��-�W�����D>���111r�<44t����8�D��O�<���^�z��j��GZ5��g�T�����n����[�la/�������j�����x�b��;RW�c�;vl~~~mmmEEEFFF`` L�6�W�"!!�����%%%��kW��;h�,|�mS���!!!6]���	......�������q�L&��Q�v(|�mSX�+++m��ahlllll���z����ea.��j���)��uPP�MW�����;g��j�I"�M	���l?��S{��-//��t7n���i����������[�@PP��-[�]���j������7o�<p�@��;��,p�m�V����h�����s�J��2yk����=d[�P����\�R��e�Y����'N�*��<<<z��5���/Z�hW�		�vHHR3�R3�R3�R3�R3�R3�R3�I��v���Y�bEll�B�h����1c�;fk!����/�����d�d���H��g��w�n��av����,]�TRO��}���466N�8����k��P��><|���!Cl-�����o����4bc���N�E�g�gff���yyy�rqqv��4A�7?���� 55��&}��v����F`=�h����!����9sf����;w���iiiF������Y��Y�q�s��O�n�����;w���X�����?�L&������,�J�R�������7k�,��4�P� o�����������'N������/�f��@��!������8n"���z�A�f��!`�{��yn��?����6E��ax6�FXX�����qsVV;n�7o�M-�����<�0����EEGG?x����Oi�fI4^�qX222
�\.�����%K4
7������Y !)H�H�H�H�H�H��������#�������?��y�D���7�
:thnnn��%0w��6]�:t(L�:�����}�(N����DFFzxxTTTx{{��.�������mDFF�0���7�2�Q{II���c
E@@��Y��Z�D���n�S�"|om#�v�
999F�VK���4��?a���)�6X���\N�>
���


��t�����W]]����~�I�x��6�3f���_b������6�|����fT�[�@]]����/���������R���f��@�{k8p�@UUUlll����jz��Y�����/�~���0���)�(\�8�����[��������������y�|��� 222??������������Y07X����|�����3�4��jiw��1�/:n�8puu�i0����6��d���Me�S���W��������7c��_���o��4�]��27n�;w�w/��J�����:uJ�����o���=��)�o����������r���(�o���C�F��z$t��e���������7��������������r53�@�n�z���cbb|||������f��YZZjk9��2��K�vE���*
S�
���gm*
���	�[���k*�r���@BB���'5�Z����c�8p�ME��Y��o~ww����k����Y�_����^[[�pE�q��#���6U{&�4�M`ill\�|yDD���[�=�m���*T8���n?��M� !!!??_��h4��'O��n������cb����Y�����^���E�`������\�EGG[������:u���V��eee����'���(Q#u5;0ACC�[o��za���Y�lYcc#�vrj<z��!�}����mS9b����`��e����V���4�z�-�-5������z>Cd�m���?+W����~j�jaHH\�v��x��5		�z9�5JP�h�i?�!��O}���ME����x��;>>�]=�h4yyy��������R�5���`n��#�9s�����(OO���BC6>���Y��V��\����)���rydd����Z\\��Cj���mB�����L���L���L���L���L���L�A*jf���]]]�t��������)��!C�dff6��;o;z��-���J������aK�,��(�<S�H��w�NKK������,�J�R������cG''��~����C~5>|�J����V���;u������'N���s[�:��7�y���X���+wX�gLL�f��y�=��l����oH���$�L�����=m�4��?;n���
�\nScI����������3V����|�ib���r�;o3SQQ��k�����d����5k��6�f�Z(A��Eq||�6n�x��u�Nw�������_sA�'��,|�mS***>���<yr����qh���0LRR���Gkjj4���~�~U
���G6]�	I�\����9�������y�4�r��dH��w�>z��������===�����������!5[�|�	<�����L���L���L���L���L���L���a{h_�r%==}�
�sa�IDAT��������<x������������qJZ�(�^�i}����,W���n�:S���_���Zl�8@�N�{h3��g�w�y�����*JJJ�r9,_���FY�|9�����R{��lj��6�*�.]
S�L�&N�2�-[fW�D
�q��=�����S�N�&������h�(7��{hsi*[@@TTTp��� 00���|�@	�v
�C�KSR��d`����t: /n�`k��=����[l������4ZRJ��E��m�/���K��_~���alj���)III����Md�:th�W�G�8�>���6��%���+V������J(A�N1zh�^kve{��u������U��N�{h�Q3�0���KLL������JLL4}[Bj6�|�1�V�}||���kkkmK[�mH�j��6m�.]�8��6��{	��������/8��6����������7�x����4n&�@�f�f�f�f����?���V���_�y�Q]]=i�$��S�7��=n����V�'���<\�������srr�
<�h��4;�H�������G+����B����i�^�O-4��f�#�O�1&>}���������l'��#6��>8��c��G����������o��&j��G�[���<++���-88���~jvibAZjx�[�X�����ruu���wYYY��H��#���y�^�����G�Z��r��Y ��������+Wv���hC�$j�x����{���Kjj�G}�h[�G�8������{��e_�Y�����<j�x�>u�������V�\��N��G����P3�0���{�=>��$+�hf��f�f�f�f�f�f�Q3#r��/.Z����
����-**���^�q�F3���?6��z�����|}}����]���%�����oF����o��k�^�p���F�V<x022������kK;q#���?6��s�<<<�Z����"����c����J%7�cb������+J�288x��
�R����}}}�.]�U?{Icc����#""���z���m���h�Cq�f'[�������=�������>��s�V8p�����ddd]���b����L>���?6�0EEEJ�������S|��P�oll��K��j��9s@�T�$&&]��S���l�Z]VV��:<���#(��YD��EEE������o�/��*�
{�o��m6�{@7���������R���n�=�AjF��]PP���3f�����Kn�
����:�_�^o6�����na����1�c:th���*�j����6mj�E777�C�F)��;��lt������c�������j�s������pHX8�����W�^�~�������D�5ZM1k�������?vS���|j�*M�)fk��X�"����MjnD��M<�,� xBj&�@j&�@j&�@j&�@j&�@j&�@j&��\�����������������tww�����9s����a0�b�[�T*����~����=bs�� nA||����\�R__���#G������j�[`�}3��%%%QQQ��[ ���X��d2���7�by���v��|q���N�<9`�����m�\
����p�6��u��u+�2%���,��\5+�y��q]
h��,n�0�;��}������.��1�-`���9r��}�`��]�[8��M�#t:TWW�A]���?vA���#G������;�=�{�nvvvtt4�5��75���5n�������M�i��B�[ ���O�~������Y�{���`����o�-�����+��A;$$������������������r53"��6"99��L,�y���6�'N�1�������}3�m����g�NNNn�D��������@�TZ��o�6�QV�x�����kW^^�����}3&��������w�}7((�lL����N���vRRRtt��G�����Q��-@��������Y�I��/8|������}���'[�I0����g;%%�����=��l��@>���m���		q�6��}fA�f>������������ �����.��(A����l7u	�D	�y�!5��		Bj&�@j&�@j&�@j&�@j&�@j&��\���}���ac�y����Y�"~j-s���g�h	�
l#h�f4�l�A�h@�7c���

����68�-h|���bbb�ryhh��������@{��l�~sBCCo����.H��Y�>���;6??������"###00�M���p��V�8|�Ma_8����/\:�����6�mWee�=
;h���g��S�N@S���������zj������:�����6m�������f��`V3�m������hP��c�	�[ v�m�9�
�"..n���Z��l9��|�]�&$�Y !AH�H�H�H�H�H�H�P������Y�bEll�B�h����1c�;f{��g-G���7o>����(�c�+x�f�'N�X\\��k�����>|x��!mi��q��V��������_^^nW���o�o`������jy3>�hG�Z�:u�g��Y�~}����ryDDDZZ��"��� �)8�
���������<���w���{/$���,�x2�������T*�J���o_��`��Y���,H��#�������M<q����/_� ���7qqq����x`�B�e��G�V�����&�������!��?��xl�������������,v�<o��f�)�G��
0���j�!::���F���v��M{�������D�B!���u��d��FcZ�MwF"��uDHf��f�f�f�f�f�f�f�f�f�f�f�f��g��j��IEND�B`�
transformed.pngimage/png; name=transformed.pngDownload
�PNG


IHDR��m� bKGD������� IDATx���y@��7����}����bdU�(��UT����*�V����.�����u���V�q)E�
����HP�C����./W $afN��_g�y���ef�M"� ����@��	2�d���������	2�RUU������;s����j�MC�����f��t��@ @iii�>}wQ@�@��D"}}�����Gttt����t8|��'��D"��OT�G�"� �!&��b��?�X��� ���*�a��*���B����+��S����wE@��� ����`�Pll,�B��s1N�A� �8Ap���	2�d'� N�A� �8Ap���	2�d'� N�A� �8Ap���	2�d'� N�A� �8Ap���	2�d'� N�A� �8�$	���9x��?� ��?��|������`0"##/^��>�A �@;^�|��_����F�������������s1�������<=h4����!�Q �@�BCC�� �J}=@S��h��w�����b��3�7o�XXX`�
h8����5j��h� ��5j d����s�|����PMM������y)�U^^nhh��*�a�8t���p���L&S�#��������3����"�h���x�����,MMM������!}}���rmmm�E��A@mm����kiiiiiM�>2tb����@ ��9w-@1qTQcc��W����Amm���B������[ZZZVVV���:::����T^^����g��������WVVv�������������������C���)�h��n���6!!����������t:���������������������Z�}>�~T!����\.��}��Uqq������WTT$�H���F�9f����dP����x���.���b�x����������������%}��h��hhh�w�^JJ���w���G����3c���3g�)�
2��(,,��o�����������M�6y�d�'��x��]�t�Rbb������,Y��wo�'B4�����t�����C���O�����?t�����Nx��	5����*++/^�d2]]]��=+���A(�9s�����dFDD�x<�k���4VLL���k���w��5m��v���2b�866v����`�����{���A@<�����v����:������k��a2���O����]P	p�i<x0c������zzz�.�����5k�F�x���A�p�0��jh��W����}���O�<Q�Byyy=}�t�������_�]�2Hs;v,((���?�t�����rd166�|���y�cbbp�p���i��/�����7�6m�]�\��}�LLL>��sCC��S������4���9v��E������kQXDD��'�����'��T�Aj���z���...��]���rD"���_�|������nH������-kjj:~��:B��`�8q���v���k�����w��������oii���YYY�������<�]�����#F0����G����r���+W<x }/�S�&�HF�������L�D@�@�����#F����#F� |���������w���<x0d����������G���� ������������]�F�8p��#G(��8RW"������o�]�j�I��y����s��m���jz}(���������?~�x��i���<���g���RWFFFNNN�!������AFF�Bu ��UQQ�������0���"���h�3�[���433�]����+**pW���e�	C}���444��P2H]����x<�U��������P2H]���i�9KEE�F�c��@�+WW������Z��������nnn���RW^^^"�(33���i����$y���X,�/�V �����
���r�
�B�t��''��={�.P2H�-X�����$�����X��K������S, o
�� ���������O�>��b�<y���q��������������;w������-����s������]������MMM��=�B���������p���>���]�v������R���maa��@58��������������]���\�������������d�&���9r$�FKNN666�]����F�������b``�����i##�������O�4I�>DVYY9a������~�
�������IIIo��9r��W�p������#FTTT$%%��)$ 
d���p8������:thRR�rdILL6l���Qzz����rN�A���>�{���I������_������555}���&L���O������f��k�����s�������'O�]�����_�j��;t�Ppp0�r�J�� ���g�=�|��!S�L?~<�{(�����S�N���z��9h��z��1u�T�QTT�����������2���'O����UWW���>}�G���Td��:}�tHH��������_����;//��?����#555d�^SSs��!�#F�x�����������=/P?}EPkqqqZZZ_~��X,ny���G_|����!��8v�XYY���y���_~�4i��622���x��	�S
��5��;w&L�z�����|�����o������q����O�>��6l�����LLL�Kz[������������B==����3fL�8QGG����	2H�����7���>;z����^mhhHOOOMMMMM}��a]]B�����������������b}����r�\.���W���!==�a���9r���^^^y�!@� �������������2�W�H$���999999�����)++���b�!D�����������lmmmll���\\\<�����y�6h2� �Q^^���eaaq��-===���~kQQ���5e����i����	&0��7nP@���`��G�R9)��A�@$��9���W			�����f��7���C��������7o�y�����joo���/��������]�2;Pkp=H�]�v��O?��o_DD�2���E"��^� � ����6l����[I|||```nn.���[	P/�Aj���f������w������[�H$�����i�����V�\Rc�W�.//?u��B1��?����c$��h*� uu���_~����3��C��h�������X��u�bj���W�5k����q��?������322p�d���H$&L(((x�����>�r���;wF����9h� ����b���_~�}�����U-�B~~~�O��.�
� 5SZZ�z��5k�:w-�[�h����ZUU��� ����U�,,,6l������7�F��:u
w!@=@��������={���w���g�K�@pMZm��8;;_�xw-�x�������;wF������8Hm<x���p��]�������!C8��� ��Cuu�����.]��wo���%"""..������2H=DGG��u���.D^�}������c�pTd������g���k���q�"/�y��>|X$���4� 5p��A:��l�2��(f��%\.����*
^Su|>�O�>!!!;v��]���������������8H��?���|���QFDDDbbb~~>�B���Ru�


R���|���={��[n �TZnnnZZZxx8�B��d2.\��/�455���(� �coo���6^�xqMM�������D"QLL��9sd�6^�YYY�{�AG �TWzzziiiHH��erss�m����I���U�
%�Z���O�<!�����P���^�W]�W�����srrd,��/FW��rC���D"qtt=z��GC�������?���Z��B8R]����'O������������>�rC���F?}�tMM
��>TsssDD��9s�^�������!�����<�{S��d�UUU����o�>j�!j�
6�y�~Y��A**11������w!�066�1c�4�p�"����m��m���G��k�dp=HEM�2��b������!{S��:]+##���355�����bj������O�<a2��>�A�H,��������!��a�
�./������sg���L&w-2H={�������w![�x�����}���N�x�5k����h��������OcccWW��Gh��+�8��f�����w��q2�!p��k�655����j������^�~}����G:}���,J���/__PP�`0�-����t����W�Xp���>}������^��������������D��!v����r�������2Hc899���������ai�8��4d���������Y���]���PJ���o�^�C2@�����[KK���w!d	

�����#GpTd��y��E��}�|[JG�Wb^��Rb---����=z���Ye���A��t
2H��x��_�~�� ����y<^\\�B~�A*'??������\���'NT�+���A*����O�>�� ]DDDJJ��g�p0�R-���<���w!���������C�p0�R-�_�F���|B��.\S[[���d�j�fP��=qB���g��.��Z^�~�d2---qBss�i�����w!'� �RUUebbB�w����_��ww!���\W555�����#<<<�E��2H����v�B����������.��Zjkk


qWA�9s�����'O�.��Z���BH__������k@��nx.�Z�tiAAARR�B�A����!����G�W��'� ��
���"""�_�^\\��@5�N{������W������j�DR__����t�@ hjjB��uk��1��$�����]�x����PII��#G������p���o�l����}�]G�kdd�Mnq�b�������}����b����q�H����-,,�}w���Vppp7��gaaauuummm`` �F��FVUU��.@:�����?���V����O��$*	��.�=�o��G�����H$-/�WWW�-P�������7�TVV�O���K�,�����9�g������W��A�������?��s�ZZZAAA�@����t����z����R	.���WB�P�O���92i��v������z��\L%TWW[ZZ����Gtuuy<���Xe���?~,�����6��5�8H%M�:��X��dN�<��BHGG������m��jjj��(�*����r �f����������u�����`�~2H�A��q��}��G����	&���z������,���1��{��*�t��X,���0a���.��04h��K�Zgi<� 2g�>�/
���p����	>��#d����PB����������?ZZZ.\�>.�Dbiiimmmff��Hj|������;w���-�bB��������


������n�
������������������������2�H${-[[['''777ww�v�`�����L����4j�(��G�AQG,���'$$���>|�����������������������������~�i�%IYY���r����y����hii���=j����'������mX,������c[���W�����M��� ��p���3g�\�z���w���~~~���>>>VVVm�H$�g�]b�8;;;99999����������������W���w�]]���$��/�I��p@�������"�<<<�n����s2&III���#((����dLD,��H$�A���x���300055]�n]nn.5��D����3f0WW��'O�D"j�V���"�H$:|���������
*++�����c���yyy=~�K
����@)++k���,+22�������dee�;��`,_����w9��� b���={������GSvf!��g������������j����@����,+::Z,�.�S�La�X?��#��C��A]URR���fgg�����Y�b������e��B!e�B�l�A]���kkkww���R���%>>^WWw��i�����?�S�A�+))���������P]��������7���"��d�����\\\���+**p�����--���H����9A)i��E�������Q����t��[�H������x���p�%������UUU�������*���;;;2�����k����J��p�����8,�(w����hmm���B�G~���W_}5`�6����A��LTT���vQQ�c��I/��H����@)F$����X������322z���I$���&��k�5 ���P�A������~��F�����1��!C���������\YY�������9r$�Im�����������H����D���"�?�-���������S3�?�����������@����}���y��'�|����������|����WC1)))����l:�}G[�;F{{{����B�h������������OOO
����NII�9s&Bh��U�����u�����CY����l���Mxx��7o������vA)@�U���I��F��h4ccc___�w���e���:#��)**��8��!��_������#G�2�����NGT@� �PYY���&V�_���������bnn^QQ��q(���)SRRR���bbb,--KKK7n�H������v�= �0���C�,��</33s���{�����QQQ�����K�5o
�#}6BH[[{������������y3"����A
055EUUUQ3��q�._�����_I����I7��������B�����Y��hd��OD*��ga-�;&Iyy���y����?����=z�:Q���R�����~��I��?>>>���wB����������MCy{{�4���G��7��"��3f���/���	.�{�����P�P`` I3J��>���T?���$
��233���!iF�D"�MMM��e��������H�QBt@[p��1c�\�vM$�1xZZZXX��������sss[�f��g������N*%%����=���(�������������2��"�?�-���b
���{�������#$$�������A���8H1������?���B�QRRF����0�'��'99!t��u�� $$��������1�?@!�A��4i���scc#�B�$==�N��9s����?@~p=H����qhh��?���%���xxx�������/� �(w������h�K�.�.D"�(88������w$M�r�R����������q��+V�������:��2Hyb�x��YFFF����k��X,���d0qqq�����������`mmm�8����aaa,���S������*�H�z�j��a��@���q�\___###��
��A���������$�W���\�bnn>p�����c)�:D����A����n�����w9�'???  �F�}���x�����"�@ ���������;~�8�S�����+W��lWW���������� ��WRR�d29NLL����r������������{7������?�5� ����K_d���X�n]~~>�3
���7o1�L++������z�'U�HA�����;v����B���c��-YYYb���)������---�t�����K���o;����� �H222.\�p���W�^{yyyzzzxx��� IDAT������+4������������w����O�B���Wpp��i�lllH�
�@�3� JI$������������4���

9���M�^�z��e``�v���2.���r���^�|)
�L����������������
"�������2;;;'''??������������������I����!��������������urrrqqqrrb��x�'��;�RQ���3g���������r��	2�d'� N�A� �8Ap���	2�d'� N�A� �8Ap���	2�d'� N�A� �8Ap���	2H-���n������N��h4��z����_=h� }}}6�������_���t�v*(������C���Y��%f���~�*J���?x����X��_'��w�0@�IIBFZ��}��O>�������~���Aj���y������d�����k��'O����WWW_�~������j���
�L)��#���1g�����/%����������f�����q��I��
���PF��H}���o����c��S�,	t2(���!ddd��R���m��m���=z��]Kw�b@1���Gyxx�.�g���������f�mll�����yCFm�
2( ''g���4-22w-�����s����{�L�����/>�_ZZz���!C��~���
5d�WNN�'�|R]]�~�zooo������Y�&$$���W��L�������XVVciiYZZ�q�F���@����<��,�v�k������"�����b��3���,X��������J������������+v[pMt������


�/>p��F�������g��<.�X��/�{yy!�����-O����J��/�N�81u�����%K��Z�����������d��s�����B��������RD�����h�1c�\�x���L p��C����"�)�[��g5T�B�Eh!{o*����)//777�1���O��(�R77���d�����8����������1�L}}������@��k�jI��W%�R��dB��g����>��sugp�	2�d'� N�A� �8Ap���	2�d'� N�A� �8Ap��QT%%%�%�P(�����H���
�����@��?�
��LU������������*477K�A��&L���4���Tp.�B����`0��/�Bq=���� �THppp������n��H�A*��������?�s����U��H�A�e���m��3����c�G�@4d�j	d2���&����ohh��$���<�A����`�����D"��9s0��R�?�2H���=[$�����;y�d�������R9'N�����[KK+((H[[oI*��a �T���>}�����������RE!!!�%����;w9*��I �T������	B(88������h��B(�}����������q������VVV������������w��@4|n�������g��egg����������~��]:::���NNN...nnn�������L1�O�D�X���������������&GGGGGG[[[[[�^�zH�?s�����B�������r�������jll������5j����{���s����=AQ����g���z���w����|}}}||���d�%�Hh4ZG�+�������������[YY���8�|[[[6�D��nMHSWWw��WWW�������[�?N�D� )))""�����`��}������2�<o��u����������f^�H���4c�����z��I�HD��
����A�D����066��aCee%�2?~H�������=�"�?��AD���>|8�����|��=�r$YYYc��e0��/����]��2�b�x��=l6{�����Y�����={�tppx��!��?�#�Ax��}@@���������iGEE��)SX,��?�H��� dPW���������eff��E�X�{�n��l�2�PH��� dP��x����������w-r�������6m�@ �`:��d��JJJ���������q�����4==�y���}Z���RR]]������sEE�Z������I�� '� %-Z�������w!J:x� �N�u�I�C�� ����p��B�$00����������?@~��U���|gg�!C��={w-]RYY��p.\�}�v�����A����]XXH�D�/� uEEEikk8&������������g``0q���7o�4��R�H$���]�b���u���)��������f���D
HvJJJ���O��R����R�o��F�����H�����_�~-�P'u�M�6���5552��
���
C���/>>������.!!���������h2H1������"{�
6�y���*((@u:CjbccBfffo��!i����h�������q���:E^^��m�6o���GR'�����p8)))��Fj��;�Z�t)5��"�?�-� ���xzz�:KDD��Y�t)������u�����Cv>|������gO��}�l�����+***H�Q����vA)@���v��%&&���;{�����Y���������w��!��;��W_�������~�i�����"	Q���R@ee%B���X�x�5k��������4E����	9� �?b�!t�����8����._�lccSXX�q�F�&E���2H


!��_�vmSS��]�H�#����M�"������:q����SMLLLLLO�<��v�I�"����SSS�PUUI�?~����g�����>���d��x�M�"��#�A����[?8d����4���.� H����K0}n�����������i�dff�~Pz�Z��������vA)���hkk?z������u���$M�z����&_]Dv�o��7o^|||UUUUU��+W����


"iRD\@� ��f���������"I$���//��Ev����.]�����S�������r�\WWW��I��.� ��3���k"�w!�III��x�G�&d4�����?����1B__��bq8������tccc�f$�?�-�����������k!FHHHAAQ����E�q�b��������'�����$...,,���?@aT}0Ms$''#��_������8884778&�(2H�&Mrvvnll�]H�������3g�>2���)������?

���q�����������q��7@B�p���:�<�F�t��B�!���������{G�� '� ��^�Z[[;99w!
[�b���NZZ��@�< ��'�g��edd�����y�����H�G�\��)��.inn���V��>��b�N�:E����)����D�W�f06l��������522����� d1N�8������M�}��p��ss��>�K��� ����
4HWWw��M


���?���4��/�����hd�ATT������������z����\���f������`����D������P&���pbbb��=��]�n�����������|>����A�%??_�"�����u������Q(��y3((��dZYYEEE����=���?@
2�\o����cG�~�B[�l�����NQ__���niiI�����/]��.��?>/F�D���q����/�z�������������������^���|~NNNvvvff��{��>}*
�������M�fccC�V����AQJ"�dee����������~�!dhh��plllz����W/��k���q�\.�[TT���K�P�d2���|||���}}}I�Rw�@�!� �*++���srr���KKKKKK��������2KKKkkk[[[''''''6���~�A�� ;s�L�;��h�.WN�A� �8Ap���	2�d'� N�A� �8Ap���	2�d'� N�A� �8Ap���	2�d'� N�A� �T]nn��m�<==�t:�F�g��O�~����
���g��_~�eII���?~�j������jkk���o��%�^�"b#(2g��&O�h��g�����[�������N�4)))���wo����?/�;J��vw����_���ZFFF�="f�����n�j��NWW�w�������KD,8Ru���7n�����]�v=y��������������UUU+W�����!C���������\YY������^]]-{-���1g������A��"�h���yyy������������KHH����B�"\U��;����������Qh��/_*�5>���


��y#g��hfll,B������7
�:��<����!###�����B}��G��D����m��m���G���r��9����KI���s�nAz����!�����)))3g�D�Z�������p�.]������l6���&<<���#>D�������o��l6���~��J�
�p���x.���mddD��RSS;]��s���;vL�)����'O"����+}\�.��E���.--��
��F-Z��������}K�FuOp��rrr>���������{{{+���������|>I�u��[�fMHH����L�������XVVciiYZZ�q�F���b����7���x<���|����Maa��A'p� h!�A���������p�X,�������n�V�RhRjH��`����_�<������G���S�2&&&�;w��~����!kkkEg- �TT�3����������+@-
B=z�Pb]�I�#�����V]]�������4�kkk[?XSS���@68�L'N��:ujCC��%K8 ���? =���%�:�H:{S��RSSB�_�2dB(33�����VVV���=Ai��;w��?_(._�|��}r���������{'
����_�>m�4���W�����j��;Zk��1/^,++\.���C������@s��;!4o�����������+W���7!D�Vu7�u�u�Y
yv���]^^��Zfff999�o^��=W���Y�������x<�+������kUU��[���q�?iiiaaavvvL&SOO���m��5��=���Q���R}}���������2����111#F����g�X'222==������5MB�5 Vll���3a�t��1�8�d'� N�A� �8Ap���	2�d'� N�A� �8Ap����*JJJ(�?J$�P(��)B�F�
6,))	_��A4��YU������������*477K�A��&L���4���Tp.�B����`0��/�Bq=���� �THppp������G��g���F�R!~~~�����X����h$� �2w�����������j�?�2H�2���B�����744�U�J��h� �b``0y����f"�h��9KR)���rf��-�Z~����<y2�zT
�G�@���'���I���������$���0�A*��fO�>]�`�@o{��G�@������LMM�������$�A�������!���@A4�?U!
��}[\\������8t����D++���D�aiiimmmff��Ll�?�
>7�Gsssff��g����srr������Z���.[[['''777wwwGGGj
�������X,NOOOHHHMM}��aSS������������������m�^����9sf���!�DRVV��r�\nqqq�566ZZZz{{�5j����{���y]��� ��p���3g�\�z���w���~~~���>>>VVV2��H$4��������������w�����tww�?���-	A"�O�&����;p����+B���c�����?'c"�@���aii�`0���n��M�D����DD
��n�:SS�u�����R3�H$JJJ�1c��puu=y��H$�fj�@@� ��D���[XXo�����K�?��h^^^��T��� "eee
>��bEFF��w9�����c�2��������.��D�X�g�6�=z�h��,�t����={:88<|�W
��� ��>  ��bEGG��b������b��),���~v��2��JJJ������233q�"�X,��{7��X�l�P(�l^��
2�K^�xamm���^ZZ���������N�6M P0�t
2Hy%%%vvv^^^����kQ@ZZ�����y��>-��y@)������������w-
KHH������$o
��d��-ZdjjZ\\��%<x�N���u����?@N�A����G]�pw!]hmm]UUE��� ?�����|�����!C��=���.����p8.��};��B�bp���������.,,$|����F#|.���(mm���"����@)F$����X����;�5j�I$���&��k�5 �(
�OZ1���\.w��%d�v��5
!J�t!6��p��c��5772 �(����(�������f���"����K��)

B7o�$d4�P)&%%e��q��#�H�N�����d����p8)))�����R@yyyAA���'5��:u
�y���������]����;����O�\������VVV�����u}�Pd�*++B����������g3��277�����8��� 444 �ttt�����966Qr������nZA� �`jj����"{��������������=B���I7���?@	�A
�>)8,��hP�G!T^^nnn��q�?@	�A
�p8����="u��o���y��d����:Q�G�Io��E��� ��lww�{���:��3g�B��q�>��#R'��H$^^^]
����1c�\�vM$�7�')))<o����������PLaaa��}�^���b����<�P)���������~�]1JJJ�����������jj*99!t��u�� $$��������1�?@!�A��4i���scc#�B�$==�N��9s����?@~p=H����qhh��?���%���xxx������4����?@�CP]�?�F�]�t	w!��D���VVV���#i
��d��V�^����������X�BGG'--��Y�?@�A����f�222JMM�]���bqdd$������`.��dP�477kkk��I��c�X�N��fF��dPW�D���W3�
6��t������Q|�P��
2�'N�������&��Z]w��ss��>�K��� ����
4HWWw��M


���?���4��/��������I�T�?�d�������f�����?������l���l6���5%%c%-ATT����J�GOOo���+�� �SXX�����G]�r%44��dr8������&�+�r������������{7�����JJJT�?���[�n���.T�Fu�A�HII133svv.((�>���/}����b��u���d� 
o���d2�����������Ti*��.����;�����2� �p��)6�����o����cG�~�B[�l������^__���niiI�����/]��.�U�?������G�~�����t
>/�%��_����;�-[��}f$IFF��.^����+ccc///OOOWWW{{{�&���999���������{���P(���
�6m���
[F)�Oii�t(}� IDAT�)S���/]�������r�R^cccXXX\\���{����YE"�dee����������~�!dhh��plllz����W��w.�H$eee\.����|�R(2�L'''ooo___+++���r��SWW7g���������}Uc7���������9sf��)�
RYY���������_ZZZZZZ\\���������$]�����`XZZZ[[������:99���899��l�6Ha��P(\�|����m����_�A�=�N�ZYY��������'OH������wd �?{������V�"��h��;���/��gdd���C�8m�X�������>{��uLL�����4|��b�<y���cmm}��] �6e��������	&����.GcA)���[>>>7o�411�] ����������c�VVV�.G3A��������zzz���������WYY���SZZ��
$�c��GDD����,w9�R}��IMMe2����������4�A�;|�pxx�W_}
_o�=YYY%%%����3�������(�A���{�_|��������;����s�N��}}}}���p��9 �dY�~��5k�=
�U!CC��������������������������,�]P,+66���������{����A���i���;80k�,����b���;7b���'>x�w9j2�[�l��e��#G-Z�����l�������������������7o�����p
d�������1c�h�+ �����[����=zt����k�NKK+66���g��qp4�4���o����~�����������������������;�l����7�Y�w-@������q�w������r���Q?�A!7g�������o��]P?7o�4775j���oq��f ����9{���������k�J��E�PWW��u��3(???((h��Q�����b��������/**�5k�P(�]����TQQ1q���}�^�x�(t�����7����l�2������A������t:��������b����.]:z����[q�����I���y���z����������e������_�x�����9sp����im��9>>���}���]�@�-z���������?d������x.v���-[���������]�X{��1bD```YY�ZTZ�������;w��e_|��Z�&c2��.]222�:ujss3�rTW�������� OO���(���g``p������+V��Euu��D�f����/^d2���0@�����<y����G��]���F�}�������O���Iy����_=h� }}}6�������_���������V�8p������v�~��,Y���+�k�:@���TV������m���'�N��������#G�9���+��L�v�*�����[�nuww���744�4iRRR��u�B�~�����W�X����R[�Td����4En��E��������vbbb��_�������=z��Z�Q�F����~�TV�v�v����n;����e�L���������^RR���VTt�&������P]]����mQ���]��=�-2������:00���=<<v������������������#����d�6d���{����677WVV&&&���#�F��PU�F�B;v������Q\������[�\�]�����^������x<����C�X�������>� ��
���
C���/>>������.!!���W�qd��p�\ss��3gv�$�[�
{\�3H,O�0���������322B:::
M���KE�***��h���555�.��;����������B�g�n�����B�|��B%uQW2(66!dff�����t���o��h�'N�^�a���=h��������766�taggg�����BSH?k��G��JLL�D"�:u����BsQVa�����


m�����w�vqp��;w!�t��=z(=�{p��	_|�����

���]�lQ�����$������������sy��&L�s����'''{zz"�~��'����B����h������������9B������o��AYZZ�98!>88p �����^�h����e�kkk��w���������b�z���|����r��t�������e���"���e�l�=�����=<<�*�Y>;;����F����v�p��p8r^�JKKCYYY	����i7�(���g��x����~���#�X,���w��k�������2�e����7M������<���;��������?t��-���59��������<�\��������B�����Y������_�ress������#���Y#c��De�j�AS�LIIIill,++������D-\�P�����������^g�|����
B��/��gvy����mc�����e� ������d2����Y8==]�����p�X,�,�W�<<<B�V��g���&�����,�}�ATV(Q�s�������={�X���!t������}[z����r�AD"�������<(�"	�����������O�Yw����K�?h���
�z�(,,D���C����<����,��BI������#�[?�������V�0�u�A���!---�J������555���z�N��l7n�tI
�H�u�k��b[�l�r�����=�'N��:ujCC��%K8����JMkkk�Y������
*U�~~~�����J��Y���T������_����>|�������l��������n�*�W
�H*�8!I�R����`0�=���;v��6a�����?n��+W��}�V �{����k�������w�nYY��d2���%�cK}�R=7Z���u������?��_a�I�3z��.�y�������<xPz�*�]���^�z]�rE�qqq��'+W��=��{�S�w�999566�<H�Ia����A


����ga�,�E�v�733����tF���'N����2>�A^���z�v��/�u7������������K�������Y����(--555����[�x�Ta�kZ�[���������pG;��
OKK���c2�zzznnnk����R@�;w��%��AJW(�3R"�\�|y��zzzzzz#F��|�r�#N���[���?x��~����A�bbbF�����b�8Ndd�<�x�����cL&3##C�#�[�
{�&�������C�?~\��766V��"���(M��������=z�=o��9��AXX�����V>�����k���d���{�����{��.�XYYm��y�������Z0��***���o"##���p����.]����d���`�!��W_���{��5�@���C�o��~�[��������?t����������+W�����]��>�����-[����������g0��
�>�>�6n�����s�N���U���QQQ��w��Z��������q��m-��@�}��g����/�k��g�D"Y�b��!C���p�a���^�xq��a��PD�3������������GG�5k�|��7�k���������[����?8p �Z ����uuu7m���*�kEEE���n��w!O__����?x���g�p�B:���W�^m���������v�<����
����pB:���o�����f����,4m��=����7p�B.����:uj����h������{����?��lA�"�q"��R'�Z�B�T��b���U��������u �*�
V��ZE��8@���� +�����K!���B��_��{�w���s��9s��]�����'q,"e�w���e�:�$����'M�7*e(--�����mmm6������M�8v�0if~������>�1%>>��w����^��=
`��6l/^d0�����R�#F�4d=�a� d����[����WUU=z�h��)������j��5h�����rt:]GG���q�����R�c��1�n�c4������L3�S__obb����a�N'��4�UT?���I���7o�DGG�������C#_PP����t:}�������	40?����-"6�p
�:����;4�P������
����7ntrr����v�T_���~~~�u������x�F��S[[���_���FEE�8.~X�N����C��dP��z���[	������1����s]o=a�Xuuu�C�
��H$�>}zO�Y��{�=�1����Ayyyxw[:4�F��;w��
_?s��N�<���Suuua�D)�������3gv����xff���R�����At:��`\�|Y���R��{�����fB����Z�iN~�l��K�,X��-����}��!J�����NO\b0l6���[���>���-88�8�H�r�����x�Fs�C<�|��5]��Baqq1���G����'��1�L���x???�Q)��i�������L�|��p��D)�������w�u�W��5���5����5��d�����p�R66�={�lb���m����#�
�Ohh��'0�� b2�yyyp�"�k�����?�L�����\\\���s��%��
&N�;����,[����~#��SP
R��������trrJNN������������z�2X�if~����f�F[[[�95���������W%%%MMMo�����YWW�N����XZZ�MO�y������G����Q�F���������t�M���0a��7�O�.
;m������p���������������������
���������vqq4hPuu�O?�4~��k�����(#H�������������U�G������'���:t(??_��Cf
�D����y�fbbbjjjss���������������������
���� ��|>������������fff�������?�������?Y�B!k~��?z�Onn���oMLL|||P~4-?���oKK�������|�/
���������d�bdUgg��>�����/^�P��������#G���5���:t�7�|SZZJJ��$_~D"���
����������'55555U�6���j��7oN�8���6l���������L\[[����?��3:�����{W��G2��4$?r� �@���BCCsrr�
�'B��������t:������sB�P5]��G2��4*?2� �P���?���m�����Za�����3g��0�������Pb���d(?�i`~d�AO�<=z4����qcmm��b�)��'���U�V�������xP~$�������D������w�yGe[�R�p��������"����#��d���jPmm����Y,���%�������3f�`�X?����{G���G2
�O�5���l������iii�wO"�Ht��!:��r����v����#��d(?�����<KK��C�v<����^���rg��������P~$C����\����lmm����k����$mm�({��G2��P~=��7o�4����������J7o�d2�7nT^(?���H�����������������<y�F���sGI���H��#�O��k���W�.]R��f��iiiYSSCz�(?���H��#�����boo?g����������'�Y��P~$C����t��A�STT�`���xJ*�����;v,��T%9p���)..&�M������w�yzz��=��(�����#�o�?�c
����_|��"��D ���v?Dy���������[GV���G�qT�1�J�����t�7���1���_����*�hOV�Z����������+VVV����+�G��o�nhh���LJk�����u��m�=�"���N���I�X:��p�Booo������5���{����X�r��:-,,��������#����uH-�C@�OO�z���\������'w��%EEE���<<<)))J�������1!!�����(�(?h�� ����TUUUXX����p`�322����OLMM�TI���IYG��X�%?h��&���D\1����pT�{��w,�z�jMMMMMMtt�������������s+;?��K~��CM
��?5���������������4  ������`�����i��#���������������.�A�5)���|rMMM---E�����yjj��+lmm�Lf�������h�"��%�r��[S�������?��`~�S�555��3SS�c�����}��W�n��;��$��xk
RA~�P�������O75���N)UTT?~0w�\��RUUE�T��������P����O
rtt�p8���
G��w�y����MMM


��]7n\uu������izz:��&� ?P�Q~��CA�����B^^^�}���W,��k���|>_y=�D"���%7?�|(R~pr�r~�B������t>�0a��k��	���BWPll���?���r����;w�LOO���TRw����@��;�������z����P
	��T�
1�v��b��B>��#OOO�ZC���G2�����$����4i�"�RGii)��9q��m��H��#�O'�����x����i�"���������Bb�(?���H���I����}�]WW��o�*�4t�����h���'�e��P~$C��}
*,,���[�j���CTWW7`�e<��G2��P~��x�.22����/+�B�0((������RI]��H��#�OI�	�]�������+���}��ZZZIIIJ��G2��P~�j�H$����������HJg* �6n�H�����T�����P~$������������� �������|�	�����PM�(?���H����Z�p
�k�����[�n%�A����������������-��P~$C�������0%=7JA���FFFC�������d(?�ir~d�u-77w��\.w���MMM��"�������c�b�
�\��H��#���G��g���8���ckk{��Y���_~�%��vssKHH�I��P~$����sYY�������cxx8Y����

���6119t�Pkk����G2��4-?�#���O$766

���'1�n������~�������������Tn(?���H�9�Qt(�W�^���w����a��������'�^�����t�R�6u����/S���'(?���H�	����GZ�i�\�t��?�(--���������6l�������L����feeeff���%''?z�������;((h��YVVV��b(?���H���CN
�����'O���^�x���utt�����������x]�������|>�������������e���>>>���377'1NX��_YY	P~���G�>��kP'������YYY���������%%%MMMo��mnn&�������&&&���VVV���...�
rqqa����
�-[�������������s��-&���8����W���_�l����z�Qn
����������CPz���#Gzzz��Az������������;J

���_)RJ���'�Jf`` `����/>|���;�q��]]]]///��PBmm���'W�Z����A���5SLL��&�i
�����>>>v �p��I���g���h;��7o�7����D=���w�N�0v �����������������j������ �����I�&�Dm<~�������v �^WW�z�j���Z
266&�Lk������_�;v j�������C��|B�p������355�9�� ������zX@������5t�P����k��M�>�F���R��+WJJJBCCaB�5PVV+������d2a�^�z��������>������3g������4�j���5���V%''{{{��B�i�� IDATm��y��bM�<v ���{���G}i#@�A���������������,T��w���q��ikk�������w�9r$�@�s���FkPFF�H$�����zhkk�s����Sa_zz���w��];���A����������gzzz��(��������v����o��������M��`^u:h����X�@������;
�q��EOO������[�n��uv ���������#
!��z���NNN��P---��������o�����S�L��`n���477988@C����F�
;
�p�������� ��@�����o�D) oa���3�1�XKKKqq1����K�<==�����7�;v����Q
�5HWW���2;;b*VTT$
Q
�FKK���W��XBB�?���q�F��(���]]]333���J������Q�n�����5k�@ ��a���c��� ��X���~��W�1�Ree%����������_&N�������K)))���/�@��v���waa��W����2����������^�x�p�B�������i�����>vat'�k����F{���0T���N__vj ""�����9v 0�9s���������rA�AzzzNNN���p�P���&4vb�p?s���~��p`�Mcc�7�|�d��>}&��y���SRR`G�"MMMZZZ���������������t������M�6�D��
���������;Uhiia�X�����g�����5
v ��z���o�]�z����X�~
�4i��7oa�
t:]$����^�z�r�J����~�z===M�T�Avvv...���@T�F�i��q�����utt,X;hRRR"""����!���k`��i7n���*0�L
���Okk��'�,Y��G�E"������;g����%j���NNNAA��y>|�f��!C�p�\�3p������:,��^GG///_�v��!C���8���CHH���������t�.�����������A�eGQQQ���<������FGG�����K���K�_���kll��{���Cutttuu�}�]��mR���Cxx��G�>�1E�$�[+p
hii��xG��0O�����/==]�������TJJ���N��ttt<x ���q�>lffF����`��<x�k��R�ei����#���C�]VV�� '�����Umm������~�1E�$���VP��8>c��i��I�������c999---���111��q|}}e�h����3g�H��x����g|||}}}]]]\\q�����L�u�b�D"Q��r�;WW�m��u�s�u����L��]��@ ��k��b*����H��L,11����vOOO����^�ZWW������2�	�����u�x<��/��r'A��
���3g��X���J�y��9@KKK�E���1�r����fc�����"��EEE�#}w]���|~�s���z���s+��������7oV�eY����i���C�����

_�|)w��?n���������c��IP�����AAAG�����s������p�x<���,--{�������uE<J��/���[�����?_|"�2..N��I�����_����xy��E���nff&w��?n�	����//�������$�[�Z+��y��x�b777i�������'6��9"}��uK�l'O�xzz&$$���������O����_���+�H���u��Y	����z�4����_�|	011Q�eY��l��	����e����0`�������U�����o��-�C��X���L���'A-�

� b?E�c�������;IJJ�������:���������sss�x��������k�����K�w���MlO����Olmm�X,EZ�u	�������c
�����v�����{���4mR���Fii)����qc���'A-�
���|||�����������O�<!'�s������t��9�BaNN������333�����#55���d}wjm�����������B�9666**�8hz��++����m��I�&E>ni�Z����b�����+�� M�S�o������Sy��8s4l�0��5k�i����9���'���y�f���G\\\]]����-[�H�Nzv��Y.�+�=���p5���V||< 66V|"1���{��'��{`ii�k����{E\���_u���I��d��V
*))a0��L����r��"##C��ff�F�nO�XXXH������������=��3<bbb�'���|||iY�y����>|�p??�N����� >����d2{m�:�d/_�422� H��I��d�������&88������{p�[�~JCC�4-[��N�D t�Hlw{��L���]]]o��)y6����Nxx��D�%q�\?�����O�?�i:qH8--M|"�knn�k����%[�t�����C�����I��Zk�45O�=z�a��;w:M�<yrtt��W����*++�]�FD�2eJ�mVTT0��i��'������������#F�/����_~���"������q5����;]�VPP�H����Uee����W_}��_�	
���h"���(�L��_~)�Y�}�=9s��F���z�A�$�b��\
�q|��i]7�-����YYY�6x�������%''w{�$��MII���t��?�=z�1E�w'�OK�W�<xP����G�%K�XXX�t�����e77�����R���Vqq���n��D�$H��Pg��b
z��!�a�������>��[[[����=x��������v����2�j���Y�h�����b�Xvvv�/�������������?�x)������r���1c��������s��RZ�um���B��$�3f�����rtt��q��+�	��;
������A���}���r$A��
L�2���������������v��}�����R
#��PH����_�2r���/��2>>���v,�k�����'���~����|�RKK���c����o�e�X�{�����e�X[�n�UP��8�z�j}}}���W/�W����jii������0��������J++��S�
�B��PE������)00����R���988=zt����cQ�7o�:������;}uG�'B�p��)��?������p(v�$""��N���%�6m��������a������.�;w�d�X�;���(]�p���oll��R444XZZ�t�l�Cl��<yv $&&2���w��r�^�***���,X;e����0�����Q:>�off����vF��+**255�6m:�u�u������������_��E)/^���akk;eijj=zt[[[JJ�������*ooo���������v�����F\\�@����7...���mmm�cQ��s����)��?�jnn������.//�E�G
�D�����������RSSY,���;a�����hQQQ�Q5�H������<|�v,��5������������C��h���H���,**�N����*�����t��7`BijS�p�����������A����3��n��RS�n�b2��W�����4m��=��:u�A8���w���,[�v J!�/^��r���`�B���4���3$����X,���Ka����8~��U���A6�hmm�2e�����ae�Bnn������c��5��!
���~���W�W�p�0����Q�����?���`���|���#G��u���'>>���~��G�<�����8�k�.:���o��D)�B��5k0���o�nU~��������c��y;UKMM����1cF��e@:�k
�q|��ut:���S�Q�c����lOO�g����EZ999#F��cQ���L###
Aj\�p����1

���<y�d���g���MMM���EFF����f���<kkkOOOiFzD��w
�q����4-44���kmm��e�����8~�8ecccc����L����`���fff���X|��5����O�����W��2��xYY����f�mll�o�N��/._��f����(["�'))IOOo���}ute�5����H�������6l�`nnN������9���;(���s,���?����Kp��mmm���
,�d�#5����tGG���l��(W[[���D<x����/>~�xrr����D�M�6����FhO����lv`` :�5�Cz/_��5kVnn���'M�;�
����oLL����SSSkkki4Z������]\\����?

��{}}��~�����.����kAAA3f����_�L&�p�X��A�����?������w�

����8������������������O<������������������������`(�]yy�|PXXx���9�}��������;s�LHH��|��):�%���v�r����N���?_�O�VVV&%%�>}z��u��M���#��b�\\\f���g��������N�f�������|.�����f2�			SD"��U�0C7���o� ����giiioo�����PHcccZZZxx��
�O�nnn��h�
Z�retttmm���E"��={�t�'�|��o{��
�}}���b�[[[����d2���`G�w����x]]��9sh4��U��Q���x������7o������t:�����o�����4gCC��y�h4��]�4������=V�aoo���'M����bcca��������H$:p���?~|ii)�p����&"""$$�������c�����;::j��\��?c0FFF����C�k�x
"����������?���&���-66�����������m���=��"��������e������U�	�����w:��aX_�
��v^�'���{������F�q��ggg�u���������R(���9��������533S������!C����o��i��]��������ggg�Bkk������##�N��8>d���������D5�9u�THH�H$�4���~�m��9
�����Dx����E�����o���W_A?�����������g��egg����}�V�"t:������q��Annn�1b��V0��������������h�������_�vm��E���.\;v��_�q|��%k������X�����O���nnnqqqzzz
�C�����*��'�0&����4r�H��	�3��A�����;w���w��Q��:t��(**�v�Z\\\RRRee���������ZYYY[[���u]������������?�<''';;����g��Q���������r<�������7o�����������S�V�\����s8b�7o��>}��������M��m���#qwww���H$b2�LHH���H��Y�tiXX���0���IOOW�����~ D�==z4�N_�l����{�M$�5`qq��m��044�={��#G�<y���7���/\���g�{�����~�i||�L������7�F�iii[=]����;w���0q���/�d2
$!���H~����K��b�X���:tH�w�H��5����0@[[{��m���]g�q�����_�z�H/�o���������/�s����������k�e���~��Ii���y�f��:6�-�����.6��dv��%����������VGG������={��S����5��7o�l�����<8&&��������_�x!k�������sss�������o�V���srrBCC
tuuCCC%l����v�{�`0&N��k_w���v���d���I(C����{;na!*������+���T�f��D(,,�={6�a���N�u�����Fss����K�`ZZ���'�F�5kVFF�r������7m����kbbr����%466���J������{������>��tww�vX/
����s�\�����S�N�����?ve�j�����E��=q����t��_E&�idd����k#uuu+W����S�L���TA��	�
6�X�1c�<y�D�_�-�|�*�afff��HHH��8���#G���F��<������� �uv��ub�����`t�w����XXXP�����=?~<��>r��At������h4q�0''��K��;wN��W�5�(C>>>��������666,�#?����
�P����u'��`���=z����<�d2�y��H$��?��z���o��-��G���p|}}7m�t��
i��}�v�������������h�8����%^�|||����.��u Dw}�4JJJ����Ba���t.�{���Q�FuL
�+W����_<�r�JF*������������v�����q�|}}G�=l�0E�D�������u:�����?///oll`���5k���f� 55u��Y7n������f�]���/��p��N�kkk�������5  @[[����p��F{{�'�|bhhhhh��[[[�O�����m�6�{����lmm-�YDn�u&���$n�������"
���y<^rr2��eP[[;j�����+�#��W�u��/��h;�
��b�X�.��0�x�8��R�e�����������D�u���� ���A�kjj*//���x�����/_�xQQQQRRB������1�W_}�o�>������h���}���?����ccc�N�z���E�)�}eSv~������o�fddz{{���/�;H��0S��,�@`nnHz����� �v����]���k``;�=z�(++����� ��]�RAA�����o*;;�������$���i�+W�������������DEE)�5�����b=z��q��'##c��u�����f�X�����/'��Re��j�<V�^mkkK��}��I8x�`��C�)�;a���vvv$�2���t��������c�{'��D�A2knn600��k)����n��-33����;��k�@ �@�,�����rrr0�:l�|T��a�����?##����������vvv???R����	�A2#�)))!����c�6m�Ol�����G��d�R�Rq~�z��@KK���I�����~"			���666�����{�����O$^���������{�	^J*�OW�����#�M��t�j��RRR���U�]^^������{��H������_]]�xS*�OW����a����&��A:A5Hf������*������71�zmm-Y�899�8^RR�xS*�O'YYYk���0l���$6Kb~�NP
�Yuuu�{�1�����o
b~���&M�TWW�a�[&1?H'���������J"���@ �H���/q�\�O������!99y���/_�\�t�����m��� ��$3}}����uG��<~�X|��'O:�E
���rM���C�q����AHHH�CD*��� ��$3CCCUn��������'/��OV/UUU�������������/_~��	� 5?H'�����-==]e�-Z���b�?��o���������{����Y,�����%==���8P��T��}��-\����}��U��WF����J��������d�|.�����$%���K��CJS*���u�����pR��t���d6a�������$���z��+W��3F[[[[[{��1W�\Y�z5Y����_�~}��	�����(��A:Acw�c����������������g�����Q~��� y,X���������!��#G��G�����A����boo?�|��� ::�����D�A��j����;G��;N����������}�[F�A����I$���=|�PGGv8rZ�b��222lmm�m���"��***LMM�����O(����0����Jj���A
����p8k�����<' IDAT������f�7l���^P~�^���K�.�h�-[��D���������S�
�"�A$c2�K�,ikk�K�~��w6���G���h(?���#&&FWW�����O(okk��i�F[�~���Q~���D������]�zv,�(,,3f��������-T��D�a��3�?;������u�V--��#G���A���
� �������r8�5k�TVVB�������S666<���C9����C5H)Z[[���oll������_�� HsssXX�����X�p!��Wq��� P
R�7o���������d��=���;*x^p^^��u����X,��E�


����P~� hmm���?&O�L��LMMCBBbbb���H�B(>~�x���c�������w7Gz(?�/�:eee����K�RRR��a����<<<���\]]���K	������O�>z�(999%%������&00000p��QJ�T�P~4�A�x�">>���ILL���noog0���������633��T}}}YYYii)�����mhhXZZ�����������������FA5����g��={�,;;������������J(����p8---.�kkkkiiiii���8h� 77�>����>� J�0,222((v �����\�	� A`B5A�P
B&T��	� A`B5A�P
B&T��	� A`B5A�P
B&T��	� A`B5A�P
B&T��	� A`B5A�P
B&T��	� A`B5A�P
B&T��	� A`B5H
`=��z�������];d�===����RXX(y����M�69;;���~���7���'��(ENN��={���h4�a=�������x<���ott4)-K���K=z�h���#F����a��+V�(++��}��#������?~��eSRRttt�.������������]���q��������V<x���:t�P�]���|��^���C�������]�T�(��;�����g����������3>>������...n���oo���Z�j���&**J �+W�XYYa���N�["UG~\]]�m������������bv��E��]�vX,Vaa��.zmY�y�Xj��a������hll����~�������O�.��A��m
*..�0������KX��f����'8NOKY[[���'>������+W���u�OO��M�6����'6o�,e_���j�K=x����%kT������p�x<���,--{����UO�����K<<<)))2�J�����?_|"�2..JHr v����;2��~"""@��SW�����3'11������!!!!((��RFFF���4������^fSY^^`��!����;�������
��`o�!��.�IIIss����^?����������v��E	�,Y�`ccM7�������X,E���������dZ[[�'���J���������r����~��a���(kT������s����t:]��B�0''����O������"����v��amm]ZZ``````0s����'z�Q����I�&���m�����v8��]I��������O�<�u���7<<<���������m��E��+V����e2������o����666$�%R����}���
��/_����H�W����S�.u��}���KE"���S�A���;F:t�4�ZXX���YXX����[�f��i)���=#>1&&���#e_Pj�����\. $$�� ���bG�����@�u"�VSS#}�����;W������.>�xI\lEMaaaMMM��/?q���a��E����WTT0��i��'�����������#F|}}%,������X__���:::F�-
IxK�Rou\��{��N�(H�W����S=-�w�^�_�V���M5�j���8�6m���&''���p������v������}3Jz�W����n��8x�`�]���4���rO3���d���}1�!����������-���c�X,���n��������������x\.���}�������xT�W��r���1c��������s�����W��K�a��r���aXdd$qa!��O����	� A`B5A�P
B&T��	� A`B5A�P
B&T��	� A`B5A�P
B&T��	� A`B5A���A�2q������Cikkc0�3�����c�L(?}v���������?---���9R��`(?}���������@��?����C9(?}�A�bff�����3TqT}H������D9����:�N����;������jP~�T�(g��Y]����x��=
�����D9zzzS�Ne0�s���d�
�RP~�T�����?
�/�L�{����� �D)(?}	�AT4c��G����C��jP~�T�������9��d/��������D)(?}	�A5w����6��
d���#���>��AQ�������p����'���ZP~��DQ�x��������a�C9(?}�_�Z������+++�B���`��Q7o�����r����fff�^%�!P~��/SNNNFF���O�={���]VV���[����t333GG�A����
<x��}�h��&@5H�����]����TYY�����?���VVV����/<����g�������JKK�|����srr���_�~��pF������������b����iP
R�����g�FGG?~�������o������4h��o��=�&Nx��EBBBBB��{�rrrLMMg������;V	oB�P~4�(�����t�������������������w��5t�P������'���P~4�A����~��9777:�x��m�P���srrBCC
tuuCCCkjjT��LP~�AJ������I��f�����%���_o��IWW������S"�J�B�A:�D�����+W���)S�dff�6l`�Xc��y��	�pP~��P
"��`aa	;��x�������l��#G ���� ]�D����TWW���"�h���,�������S}(?H�P
"A{{�g�}�`0�9;�^�������C����*���� E���hkk_�~v,R�������~���
�C�A$C5H!B�088���%''��E����F�0`@yy�R;B�Az�j�B��[�b�bcca"���*'''www�^�����
� ����`v��i������POO���>SR�(?�4P
��@ 077��B.\��a�2���� RB���i����������cQHPP��G����:�g&�"-�EP-���~�A����5k���������f���/]����@}�8^PP�b��=Jn�(?��P
�����mmm[ZZHo9%%EGG��O�����H���|�r;;;oE�A��j�����
v�����������������uuuqqq#G�x{{+�G�srr0���!�5�D&����������(�qb����"��EEE���	�F�Z�d	)M�� 2A�Z�,!!������F�[ZZ��/+++e�H�<yrBB)M�� 2A5Hf)))���Jj|����9s�$&&644444$$$�	

UR�//������j��B�Ad{CL�������Gy��?���M�3rss�x���z�q<??����xS(?�L�v�����


���P(��������|~ff�H$RR�###����o
��	�A2{���������}���;WWWG��qpp��k������)���z}z�4P~���S?&&&��b����p����BI��8���K@BB��M�� 2A�A2344T�6�@ �:������QR����*)�P(?�LP
����[zz�����%$$�}�����>��xJ�����r�xS(?�l`o����+i����d��C'\.7%%E=�.]:f�R�B�Ad���d6a�������$e4�������E�����X,�egg�x����OOOe�hoo�~���	Hi
��	�C#G�tuu
�9���f��]PP��RD�A������`����/�����G�7n�_0�D�w�RKK�������aB���h��=����H� 9�;w�N�+o��hjjrvv~���Io��:$'�H���_TT����nG�R+V��p�BFF���-�-�� ��]�XEE������s��	�����]�|YI��� �@5H!���g��������w�l��
����+T�u��%��e���� >>^WWw��y*�BA�A$C5�aaaL&s��%mmm�c������f�?�����V�����H�j9bbbtuu����������M�6�h��������	�A����<x������Wa������1c��x���(�� �B5�LMMM��/�0l����?���ill��u������#��� F���t�j����]]]9��5k*++!F���v��)�w��!��A�A���������766�������U���9,,�����`,\�����8�P~��)��7o���gff�d2g��}��</8//o��uFFF,k��E�{��P~� hmm���?&O�L��LMMCBBbbb���H�B(>~�x��C�899����n��P~4�_Lu�������K�.���0�a��yyyyxx�������X,���q��������=JNNNII������	5j�a�{#J����P
����������Obbbvvv{{;��ppp������������Y��������JKK�|~nnnCC����������������o|�P~4
�A����<{����g���eeeeee���UUU�������p����\��������������A�������l����f�:r����/��#
����y49?}�AU]]mddt��
�x����������A��;�{�����V������������q��n���)��d���`�������f��	;D�P
�(������������p`��(��(�F��5y;(%%%77�����A�mQ��mjj�4g��:t��#`�(�A����:N?k�7o�\�p��O>��t�Q���n�%B�����mmm�1�@�C5��x<�����g���1���v ���c�����A��?OHH����`����.��
����<y2�@U@5��

���aG�jB�0,,l���4Z95���������v�����E��QT��������
v�v���q������QT�������v �SUU���.\�v ���D]������u������\n`` �@�A5������;v����� ---�� ��juYYY���`�"iii���hGL��D]���\.���v *r��YWWW///�� *�juafmm�!5����������B5��lmm5�EGG755��7v ���Di�S���93}�t�� ��j���������B�


���ot4Z3�Di���%%%}~T���sss�� �Di�
jkk�����	����O��7��@#�h"T�(����N�?{�v J�������3b� Jc����5�����G�vtt��AT�������uzyy���k������pBBB
%�����i�&ggg6���_�q�����������g�///��a�|����DEEG��iP�N{]���G���1b�����vppX�b��W���
�#����_���u�������������y��AOM	WW��Km��Q��HY��;F)e��u��R�~5���?~,��B_1��Q]DD��jnn�H�����____WW7r�H���wOM�Z�
`cc%��+W���0KOO�50WW�m��eff*�M1b����oP�N{]j��a������hll����~�:1�����o���h� ����$%%�Od�����"��EEE��SS����{���O�{�.`���rG(�7-##���(G��u*�R<hii���|�i2t<����������DKK���'���VEE��\����HIIQ4P��={������G�]���i����@�>T����Q�Fu�A�����3'11������!!!!((�SSFFF���4������^f������_]�`����Rdd$`��a���7���}��7����4����nnn�������%��d����Mtt4q<(**����b��O�)22��`�|�R���T��233����aX��Det���v����,..&��B�0''��������333E"QO����������4  ������`����c�T� ��g�N�:���L���*++k��Iuuu6l��~b_�"������hQQQS6o����������?/�e�	MUTT�X������d�����}��������H�+�+RII	�F�|���%� ����R���700,]�T$I����@(A����#$$������������L-o��0k���fP�7m���&&&���z���2j�����\. $$����D�/��L���R t��������������������<������3g�|���L&S�������|��'NHs}3���P*�u�b����K___���q�b}}}\\��#����������mll������?���F�-
��M����{���LE�o��i��{��Z�j��m��"%H=��������������db��.����"����8;;��|9B��Wm����F���A�:�u��fTUUI�E��Xh_L=0??���1//��.Z������b�X,;;���gddxzzJh'66������q�\ww��;w���K���t����.]B#u 0����'N����z�J����?�^���������cA(m����g777GGG�D!g���5k*@HT��������/\�;�=y����h�zD�A�d����n���������������;�BP
R'3g�d�X���@�����`�4� "� u�����{��������������	�Aj���>JLL,((�����=;q�D	�!�	� 5��{�
8��������/n���6���P
R3�}���aaa�ud:""BOOo����A(� ��h�"����?�DZ8��9sf���,v,���~�\�����;�.����~^^1�#�t�j�ZZ�|��W���$��3g�>x�`�� T�j�Z�����~�c����v������!22�Fz�j�����o����T���KB�P�i��C����/�����K�������c���������^W���Rc[�lill���`���������!������V�^�w��n����s�����N�8v u������K������jjj�,Y���L�loo[�`��^��t<H��9sf�������L�����������-311�?~AAA�����P�Aj�q�������[��?8p �7�N�������'OF�BHO����0����=zt�������t�-
�BaQQ��i���������O�B�
�,��G|������FFF�bHOO'�7��a\.733��!����>b��m�x=,��A]�����t�jP�����?�������V1	5h����g�Ve0��@5���3gNpp����+++;&�����W�	�����D��l��5k��&D����;v��f/[��x���0t�����������Ac��qG�UA���B5�O����������/^�x��a???�@@��/]�����������`0�������
zG�:/�_�~���7"��a�����_{���������`)�
D�����IDAT����f0V,L�(k612�N7�i��9ef[T��&,��1Pt:QSD��u��h��� D�I,����\��r�/��������>w<���ysm����d�=���G��]���pqq?~|cc����p��i�:�n�r�T*5Dl6[SS��{��{j��� E��?�O�"�V���,��������w�����8��������j5
�k���,+   88����<�d2��C;vL(�l �3�&p���/���� yD�Z�'N�x��j������������������x�#E�O�.
���^�u��V+��[�n]�|���D[0�h��������`�_��f������V>��O#�l��������~��h4���,X���>		<�z0�aJ�R�T��sG*�~��G�����8������=���
�������xA��;�����/���0;r�Hhh( ::���������5�L����f�BQ���+33���g(N�?�A4t��).���/�����|����S�2���W�����{��������,___77�;v��9�A��V���[� ��E3d2yLgggBB 55�����9�^�W��}}}�t��j%���������������@43��$���yA�d2w��A������x3f��|�����^����������������'66v��
eee>������y�A222�f�p�$4��{iN��l���������j�����T�������$''>|����z��l���,//�x���l�={vxxxPP������������������U�P��q�h4���������L�8q@����6m�3g��s�|||F���1��!����o��9MHH`0�1�L�6m��qqq%%%/����`�t�����=<<���6n������(�J>����>d��� ga2�233a2�/^����������O>��������Zm~~���?������X,���?����4iRKK����� g��xjj*����8��u���~�zA���=z4�Y,��}��l����: n�={5}�����A��	� g����d2kjj����bkkkhh���OUU�����!
9���'����������0�N7��Ac� �PYY� ��#G����F__������0�X,�~�)����������y<��5k�|Fh��D]]]</--�Zlll���\�x�^������������?� ��c��o^h�Db�X P�F�T���,Z����������R��7o��x�?����f��:u
A�TJVt:�@ ����/ev���`0n��AV���JJ��4�f�E:�X,|>?::����,��������n�"��<l6�X,V(�o��r�D���S+V�����^{���i���0����LfWWY����?~�;����4i������y������m`�VHH���+���`\�l�C�)//GQ����d���3��a}h����h���6>>����|J������#�)l�H���r��Ub��������8�h4�k��Vqqqtt4@f�y�������
 �W_}%�H�R)������k�?n4��p0��I��WVV�\������/>��y��������((( +���:����
rN0�����k�a���d�����7���e;g������p8'&&���sv7���~����O��S�L������`����WCBB��|�Z��K�RRR�j���K�.�J�:�N��I�������<�[�l��/^$+.����o4�`��T*]�`����`�X/^��������g���w��j�Z�{�n��m�:::�h���EEE]�r���D"�J���#;F�hf
�l������p�r��5�@`�2����f�955533����xgFjj��l...��=�H���@n}655�74���������`�"����Y"�V�ZE-�uuu���R�t:��������T*�
�`�P[[ ((����{�I/���0g�j1,,��e���`�����BV�����!'3��������d���������4
`�KV'L� �zYD'< +���j������f
i�Zwww�����h�Z9�c�"����X�g������j��@0�hH����l�&�Zyq����Hy��	�|�DW6�M���
� b�X���nnnj����|�L&�����]�1�L,���0��	9�A4��p�U�M6����}v�������"�k_{���������h�Z�&�T`����q�A���{zz�*--��d���eee��������������d�Y�����W'�����F3z���F� "
S�Tde���w���c������l@ff&����x��9 ;;;  ����[�YQ�T�=��� 
d0���f���P(�m���B���f��l�PXQQ1����r��	�[Cgg���3��\�4�F`` 5tbbb�92���������8T�I$���r����q�AN^�������R,X��l6��q�q��j�^�vM$����:ooo�G3�������������f��is��=y��c�����������dE"��D"A��@0��I$Y,��S��U�N�>m0����T(��g����z���hf=M�2%66������\��j�9�����WTT�������
���|�rv9� �JMM�p�������������k�����rrr�N�J]�����o���A�3���}�]�E]@>##C�V��7�������h������d���f��u�%����l������>y���{w�����l�Rv��lqqq�]�~E����b�
�B!����N���W��[OO���{NNY�0l���B��b��d'���L&���[dE�P���=zt$��F!�A4�����p�����\.7n���[G����:WW���\j1>>~��9#��(3��C@@��+����RA���F��;w�p����D����?�������:
@�� ����F����Z��o���:�\.�<yrll��h$����<��?����f�S��e����B�������g�
eI�R���h���l����5k���r
�EFF��1��?��������%K�<y2���8����`0���L&�������l�\>��Ac� g���+BCC�j5�~��M�W^y���lH.�d2�H$b�Xyyy��u+���z���g�hf�ikk�8qbTTToo/�����
6�(:o����j��W�Tk��uuu�����d�]8�o��A�c<4� ��T*�O�N�Sp���7o�����:th�����X,UUUIII�����M+,,����`2�RSS �y0��Nww�����\���g������������d2E"��]�.\�p��=��L=��������}�]RR��	�������10�J����`��.\����,�A�H�����{�l��Q��>�F�9q�Dzz:��'�pww���"�8F���^�dI~~�J�����?��rg�����<���U�y1�URR�e������.Y���3J����C��a� �����

����[[[?������u������7nxN���#���M�6������=z�j�~���F�X������o��=�!z�kw85//����?������Y�&,,,;;�������z}YY�X,������*//����;w�����,������>y���������������������f�Y�PH$�+W�������'$$������[p9������j�|�rUU��K���$N�<Y �x<OOO�F�1�J�����j�r���.Z�h���<��g�10�����AM{{��'O�>}�����������#�F���3� G��IC�H0� r$�A9��u������GIEND�B`�
#49Tom Lane
tgl@sss.pgh.pa.us
In reply to: Heikki Linnakangas (#48)
Re: WIP: index support for regexp search

Heikki Linnakangas <hlinnakangas@vmware.com> writes:

I finally got around to look at this. I like this new version, without
the path matrix, much better.

I looked through this version too. I have some notes/issues:

The biggest problem is that I really don't care for the idea of
contrib/pg_trgm being this cozy with the innards of regex_t. Sooner
or later we are going to want to split the regex code off again as a
standalone library, and we *must* have a cleaner division of labor if
that is ever to happen. Not sure what a suitable API would look like
though.

I think the assumption that all MB characters fit in 4 bytes is
unacceptable; someday we'll want to support wider Unicode characters
than we do now, and this code seems utterly unable to handle it. It's
especially bad that the code isn't even bothering to defend itself
against the possibility of wider characters.

Can't just modify pg_trgm--1.0.sql in place, must create a "1.1" version
and an upgrade script.

Comments and documentation still need a lot of copy-editing, also I
think a lot of the comment blocks will not survive pg_indent. It'd be
a good idea to run trgm_regexp.c through pg_indent as soon as you have
that fixed.

New file trgm_regexp.c lacks a copyright notice

Calling RE_compile_and_cache with DEFAULT_COLLATION_OID is not good
enough; need to pass through the actual collation for the regex
operator.

How deep can the recursion in activateState() go? Is this a practical
production approach at all? Do we need a stack depth check there?
addKeys is also recursive, same questions. (But on the other hand, the
check_stack_depth in scanColorMap seems useless, since its recursion
depth is fixed.)

Not too happy with convertPgWchar: aside from hard-wired, unchecked
assumption about maximum length of pg_wchar2mb_with_len result, why is
it that this is doing a lowercase conversion? Surely the regex stuff
dealt with that already?

I'm suspicious of the code in addKeys() that is special-casing bos[1]
and eos[1] but not the other cases (BOL/EOL). My recollection from
working on the fixed-prefix stuff is that it's not always obvious which
of those states gets used.

strnlen() used in fillTrgm() is probably not portable, and is definitely
not used anywhere else in Postgres.

This isn't a complete review, just some stuff I happened to notice in
one quick pass over the code.

regards, tom lane

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#50Alexander Korotkov
aekorotkov@gmail.com
In reply to: Tom Lane (#49)
1 attachment(s)
Re: WIP: index support for regexp search

Hi!

Some quick answers to the part of notes/issues. I will provide rest of
answers soon.

On Wed, Jan 23, 2013 at 6:08 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

The biggest problem is that I really don't care for the idea of
contrib/pg_trgm being this cozy with the innards of regex_t. Sooner
or later we are going to want to split the regex code off again as a
standalone library, and we *must* have a cleaner division of labor if
that is ever to happen. Not sure what a suitable API would look like
though.

The only option I see now is to provide a method like "export_cnfa" which
would export corresponding CNFA in fixed format.

I think the assumption that all MB characters fit in 4 bytes is
unacceptable; someday we'll want to support wider Unicode characters
than we do now, and this code seems utterly unable to handle it. It's
especially bad that the code isn't even bothering to defend itself
against the possibility of wider characters.

In attached patch I introduce MAX_MULTIBYTE_CHARACTER_LENGTH macro and use
it in type definition. Is this way ok?

Can't just modify pg_trgm--1.0.sql in place, must create a "1.1" version
and an upgrade script.

Fixed.

Comments and documentation still need a lot of copy-editing, also I
think a lot of the comment blocks will not survive pg_indent. It'd be
a good idea to run trgm_regexp.c through pg_indent as soon as you have
that fixed.

Fixed.

New file trgm_regexp.c lacks a copyright notice

Fixed.

Calling RE_compile_and_cache with DEFAULT_COLLATION_OID is not good

enough; need to pass through the actual collation for the regex
operator.

We have collation passed to gin_extract_query in ginscan.c. I noticed
that gincost_pattern don't pass collation to gin_extract_query. Is it a
bug? Anyway this is not collation we need. We need collation used in
operator clause. In attached patch I introduce additional argument to
gin_extract_query which represent collation of operator clause. Do you
think it is reasonable change in GIN interface? If so, I will provide it as
separate patch.

Not too happy with convertPgWchar: aside from hard-wired, unchecked
assumption about maximum length of pg_wchar2mb_with_len result, why is
it that this is doing a lowercase conversion? Surely the regex stuff
dealt with that already?

Trigrams are already lowercased. We can simplify our calculations by
excluding uppercased characters from consideration.

------
With best regards,
Alexander Korotkov.

Attachments:

trgm-regexp-0.10.patch.gzapplication/x-gzip; name=trgm-regexp-0.10.patch.gzDownload
����P�<kw�������xn��F�1��9����]������r�ZI�#;���U���c;�g}� �Q]U]�nY7
�T�33 �@s��3��lx���%�c�i12����f���Y8:#j��n�^�����v���]�V������yU�T����Z�n[�����TE���������������E25g���!�^����9��6q��#�f�$�v�0����F��������4T�j�^�?YICh�T��3�����>��F)h��|���C��	���/�c�T�di9��#^�&��"��G
5'rD&o�6A��z]��Z����T�
��6_hs��0����o.L�zf�,����R$�?�b���q�R����T�9�e���a�7��q���>	���J<	`�k��������� E���c�OH"()T����y�2�w;�b�P��K�H ����H@���p�x:��t������R�'�?�'��j�g?y�,\�
�\(��g���$�4b<L��c�KH��5���u�$!Ke�a7b��(���w�j?��>��mK�E��T������c�	�1)�
Ctf<0����g�[!����gGV�f ���:��w���>��Jp����K%���@��l��Z����CX�h��9.������M������]7��CV�@-�����To��owu��n��k��m���
�K�-u�T�<�q�����,\��61
�k�����UrBOc:0��0A!
`cH0�6�l��P�������Cn}F�V{#��G�X������_?�f �����^��q�����3(0+h�a��?�^��h����e�r����]���|��:�����)����1����7\��7,6w��jO[g����U�SA��Zh�
�Ygpyy�u���������l�!H�_t�8�W0��:��i41���l�'�-�N�w��o����z�����E���7<�xQL���7t��O�g��>�e�L:���%OH�M1�/I:�

�/��������o���:��Y����7���_��H�fN���?@0� wl�����.i>�A{�f
�{O6l�X��J� ��5������W����wq��:��TU%�}s��������;y��f�����m-0��qo����~f%��gS����������T?��]6���GdM!:���P��~)����g��`u�N%f���7����|�2S2H�-�
�R�.F��M��?j]�.��<
�/E8�����sF�A$�A���g'b_qz��x�D�|�z��C%����y�7J����Q�'�q��"O��C+3V�I	������Jx�
p#�KY�m�+�	N��:�������f�KE&9��#-�,�H!� n�s����M6�w�D����'����Xb}Bm=��AF� ����A����5B>@t� Kf,
����aA�,���N�(�A!�Yfr����NN�e�fs�R��1+��
�����hQ��1�s��5=��%�;�($�<������3���Z�	��. �H��]�rp��
���������t��)��v�zx+������Z���]4��l�)Pj�_m4��[y�+;��N��� d�u�!�����iO�G�`��Z!Kr�o��RH|
���C�?5�,H�U�(o�T%�1���������5%k~�~���/�U��M[�\��Z���\�&�����UP�������p����m�
m�ly>l�5������-q�{�K��\f�bm��;[j���m�uG�V��wj��U��^��!n-��������)��@�d���b���	)r}N�$d��z�wSP 	>��6G�?�>�� fB����^�4�@���+ \p�xH�-6q!P�1���X�T7���1��M���L�*&������*f��$�2b��0����V;�;T=T7��*�|1[�u��jSQ��(�p�	�v>��'���=n���Kq��l����l+����c���i���������rx�5��vly�/���W��������O�g;�g���?�~������; �xL�U�����n;�%QT���&z6��M�6��LzZ{f������	��csM���[������GF���jz���w����o�eg^�p���8h0m�
�=�i���-��^^���j�1#����p�����00-:Mb|_L���
�"[� <�x�f���F� �'0m��+&��FGi6Un)�VDH�g2�Ad���*\L���S���������-�h����_��!���BdRh��o�t'��z��c��usB��l
8��%nB+n�IW�j+�)�����v��|g����7�W��.�n/���n��+��N���%Z.���S_3���B��f6T�e���L��r�Zv��8��?r{NN�D�r�W��������aI���	Bv��!����t��i|�,�=��z��MC6c�Q�]��%lC>N���e)@�V%��\/(K���Ww�������QF�*?
�?�Oo�u��Z�&"�����*�y�K_����!�I��_����g����}�C4f]�/��0���s����U��v������t����v�������=�������Dx�<�N��m��
�KVf��X��S`�Q�b6w���MK����y`��i�@�P��`!M	��
LT?7�P�	��@@�m�d��<e�|vL]����������������.�0�0���]�����xL!�l�x�S@�5��dv�R���W��	��XEC��hY�%
�9�S������:s����^	�"�L&����d�.�AO�ok������U�eL� �W���hM�xd	l�W�V�qC]��|U�&���������n��Y��j��B^
����On�B��R#�ex�YLp��0�$�^)�f�\���f�Y��O�qx�	D����`��d�� VV�C�zg�����l�q���/q�Nx����_��	/�� \��w���W��3V��q�j!�	o�=�C@��C�������,E��&��;��8�������M[�i���
�'�k�i���d�s=8+���)�T����~�r�u�{!�M�_�����9�C����wq���U|3�������o�f�+z��
S0�w���a����-�A�a��_]���Q�O,0�������P!{�'�N@�����B���^�����Y\����-'$�]�����o�����s;V|�g���iN�G����d����^����X�i��b��+��L~$�����T�����gKFh��
q= �|K0]b�������Ej'�����i��u�e9Z�$&�S&j��=�<'*��~LL�C�jh��/G�J)<���R���,��`���\@���2r����
����(8xN���.HP-E���v=B:kP�W�Q�7<}?��>�Ozh�@�5q�[	��EU�����
��������l`���n[�"y��)qk�`B6�Q��1��+�sx�Sh��������z�a�<NC���N�z���On��d�t��cK?3��l�+�����<D����%�d�#�'@f2Z6��PQ;jl#_�����R��d?AP:�P��T�D=R�f���:�|�����<�m����k��g'��}�{�n'3�q�'2������<���ds�r����)��Gx��%��@��`8��Y��3����`����#�0t�V;R)�67�(��������b�m�vN����LW��7��)_��H�tb��� �t^=�>�'y���k�9��j\y0�{�����Ci�*KK�f��}�Q�R%N|G
B�*0L�N�#uq�[!����r���8L� ��G����!�����q���������Op�ji��'�QY�6�n�������
�����8� �Y�����^|����1�z�p/��e�E��}���b
�R��h���?��5�"�j+�Fd��
����B�?i�@e��N��B�(%����r�R��D�P	���u��}��e���'���
kV�V-���s�n0������q�]���w���^�`"��(����?�0������?�\\���l�/����z�o[�/�.������fYf�M^�����{�U��
X���*j�(�m��F�����5O��'����S�����"q��$��D-���R+]g:^jEV5@t�|+;cA��������it �J���t"��ZA������^�l���X�C��������$x.`�0q��U��V�f�M�sa�4fw;J��J$%��I��I������T��������:o����Y����n�����5m����h{��7[��l�L�&|Hl��W�������Ba���,�J����N}D�d�6�M��LL���K��,�=�����<:\�4HoLk�4�K�������
"�>Z��'c����p�'�D��,/�����j��6�4��g[1�-y^<fE�8�z������b�>x������tX��Yv��.������0�S�9�[AQ`��	�7�'���:�����Q�v��F]m*0�f��9��)����,��wT�='t�Rx�>��Y��m����[N�e�g�4���W����i>�
2���X�����-�^����ad����)��
1uFqMYm��8q ���`�3�,o�
p�H^=j�0o�	�qh��rf�+�������;W���$�dB���^f����HJ����!l5 �N��
"�r>aP�U,+q���O�R���W�!�9q���yx`������:�UX2 xb3�;����(d���Dxo$��{��������	M�r`q�������s�E(����o�{l�|N^�������Sk`���	�
��o�5 7�n- Q�j��\��Mh8�6n.���`��`�$p"����j�d
�1��K���)a j������t*���.2`��LJ���86��Hg�l��z�i
���g���e���}�������b��F�C��9�(�qF��-��qpi����y������m�@��~�'0B�PlAp_�����K����4'��]@\��/��dAaA�1���������D�`4�r<pn(�q�
_wD��HO3�Y&�/.���e.����Y���U.�r,5�HV���PM�%��H��MG>F�<*����B6pH'b��9`�E2
�B;0�R�K����ow��<M^���@jYKE�(V�y};��������!b
"�)f�0<�h��V�U1��]�*W�X�c$�.I�q����>!�hGL-2r�{\�=�`��u�2U#}��/�]U.�$X+������|���R�������M�N��UY�c�^�U������8JH�lri�r��
�Yi��{��.�L{A�[�g�`��%�3P6�����\�d�''f�-��&kT�o�d(Bb��Nz�x�4����X�tT-yq��^F��J$�G)��������d�v�$t ��n�K�h��,�<�0L�M),��R�8k�� 
��7���DB�]����U���:��������v�md�~�~����LQ"%���(�����������"A	6�`dM�����Vu����L���L'�B����|L�	"��Cf
��al�=����`a�4"�4Kh��A?�V����7�A�d5dc���W�x�D�L��59�����X�
f��y�
�[^��B{,�����i���bO'�'�pP��	�L:�QA�S#.����������SL\4�P[n�XN�t8��kZ��"�7A�[�m�Y��Y��qr����k��f��f���V���C��!0���4[����@���L>�3�Y�������k��
�&� {������{�1R
�t��bF�
�8�
��dc����S#��]��)�%��P'p?8��A�S��#�KB����E����\����������Yo*��2���,!�/������
W�}3G����C<�1�b�������Y�� �`Ca]	n���p#,��l��(
��A������q���������F��@�7�#tm���"1;���E���I�D"fhm�Y�n�W�_6�\�G@V
\3{����ZG�����t~��9,YT���4U�qO�F�0�f%s<��P�0� lg����5����$��G�t���31�@=�<�;9��z{r���]N��7C��C��,7A��i�i�a�
��|*�(����_�@�^���-�m
��g]|w���h0���e���*��;����Q�^?�+{/���on�l�&3d�E&D�������#��e)_�!�i&Q�������(p�E�p��	��@�#/�@�^<�,�G'g����3��y��7���o�]<RCc�����0h�'��/���R��8Z7G9H?�T�QH�-O���_s{�,�����2z��i�x:iF��+��46L��PF lD�N��Wp/��������O�Bb;��}G-���;q P�)������d|;�Fa���������2���*Gu{
�K�����?3�����"7�0��aL���FB)����]B�C�w�\�s5+��=���61T_���#�c�-E
��&����9@x�s4$�@������J�':���0���
��lK.M2�:���4v���S�qK`&���[t���X&@m
d�����?������fJk(c|����Z=~4K
�]����J�uU�D�X�.�_%���|
�uF��h�+����G1x���w�F��CR��������Qw{�+�A�.n��2�#*�^e�Y�k�8#-�&��Y) �&��;���f�����U���`�\NsM�=	��7�g��,EPr��|�4�1�n>D�(��GP-�@����U��
 ����sG�7��`:�Z->gV��U�7��~�i��w�E�J�%����y, ��W��	��&vp>8�~�$8:�<F���kv���G�����[3j9��Sm�}N���G�z�����Al��f����<\����E�	/
����z��0b*�c&g���n�����L}���F��9�mD/^�c�[$z�Gr�
g�Q&�W�8���
&�[=����]��}o��_6Q���!�`��:�:X_`iHRD���B�!�-� Af���rM���>s��ok���`�v&A<3BA��5!�v$x���JX6�<���	 ���R�M�6��n./����\S2at�v�(�B�1'����.�f��`t1�����
w^x���+������ !x;��%��m����9�o�<?>9>�G���cp�����8YZD��I���b;���Y8rN�v�u!_�0	P��Kjf�p������}2������7�=edyP�z�OS�����|���W0�iq;����Y�@���U|hh�9�������L��^/�v>b�n{�����������>;�����.+�=WD���V����������_x3@�������	�*����8+�qCh	p�F���p>�is
D�7G�o_�uO���N�-`�=�p��Y:"��:xs���L�M�Q�����]��A1��p@������a��Z{���w���:w��GKg9�w������t�AB�d}���gz����?�0/^�� R�7���NH�����W?�H3����o��s~B�`���
8OP�(�18��H�b9��7����6����}&�L����?���|�/U6���.�6$�7��8���=�sY����yJ����<%�p������q�~�0Q�7��������Ks�������N��g���)�q-��F�]h�X]�-!��w4gr$Ih���;�h��oE�a|���������R���Q���Vc���9k�Vj�������^JGM��HY�����#g�sC���gz�������:��G@�A���C�Sv8��s�^��5�p��T|v0��|	D��o��%_Guv�G��l��U�&M�vv�n/x��I,�3+
��d����$�t�"������?����C��W�5(RA�2vKXv(�����{��I�����~c	��E�hM��.����`���V�����9hC���H�e���}�����4^Y��.�	`bJB3��1�,+�<D��]��V���1�����>���Xk�T�%=Q'��t)"�Av��=b�{��y�,��GV��j?4�)YI�������M��S$C���J��F#�5��-��i��B�5�~R��HW�i��N�H�f�F���t�s�r�c!�AG�>N0�q
�5������uK�`1PN�}����o>�*�U����(��W�Rmc�����=���O�d���~C�����L�JbJ��		:W�$�o��Dt�iOF�F#tZ
#(���(c"����HTh�^Ht��$��"�48��v`�>�����E�%�<���}�]	�Sp�f�J3r�����W��4�h3S#��r��c�������h�@?#H���	k#��_K�1�Bngcu�|(�UPQ� ��q�:��yTn�y3��7�B�@B����nB�0vU�kP�����<K/�d���6HsD��&k����a����@S�g���.���
1��Qr�Q���2�,Ba������{4�|N	��z.?�g�{�$�:��Y�(�S������5��h�7�XJ���#e��}]�
��7���pfd���&F>�;��������5��}^Z��z;|~�%���%�m��$^���]Dnry�A
�x^����?�����?�L=����N@X����v�Y��#��:).,�
�?C�L^�_i���-\��3{d"���@3���O�����e�H?�ww���q�X��Fg��
�p���
<�c��pb.��o�����4����F����Z'�m��"R�a1?�gxP������9��vT��ZK������o�s���:�������P�Q�C�]O���&y�*���}��H��f0!��5�]RB,��t����T�/
�n�h�Hs��i%�an��D\��o�0���eG�����:+���|�wg�P�:����^Y��i)��ND��H��N'�T�+��i{��w�T���A�Z�������>��
�
g&��)�\Fty�#��k�L��H	�.��?��G������f��s��!D`�\c�_fY��������vbD#��>��x�8�:w�|��zJ*���h��vm4�j���L\t�����z���N5�,��)�{�s��".-�2O��q&����X���a�X����Mn�9W8�����"zB�7��P�g�6R���o
[r~����9��)�]I%�E,�d�q�����d#��#P������	vLF�	D��K&<b�P��%���9�N������4�{��F+���5w�|Q���g��+v��qbL����W�'�����/O0������W���Y�9�lC�>�d"��W������J�(n������M������t�?�������e�Q�hbFo����  VN�"e�dP��7e�R�h�%V3zz�����g#��JN��is�.Y��B-=�����Rs����m���R�+�����,�����W��7�6,Z�'QR��	>���R�1�M���8C�1�a���lZ���w�.7�O.��O������V�3R��J	��������S�*�EH�_2��\|up?5��8VX�[�n?I.�^����.�Hv����9H�v��e�<��������W�y=�yj����7�������<�uo�������Opce�[x�����������!��EN��$�����������m���~/�(���	7�����C_��:���/.��+�&�����*K�w����1g5�uY�e��ap('��������}�.vX�X3��2��&���{�$t��w\��*�
Q+`E���H`a�9�7���o����)[�@H��&ZO�����oK�zBQ �CI+��)��Jy%]������eW� |,��Tm��@�Y+�3}�ddZ�q���%Lc3��a"��0���4�y[J��w��M���3�!742���d@�*�����K��6Qu�Z�r�.�6��e�	�|D��T|k8�7���8�hF����z�����<�p/�\�}|� ��s�5
1��8�����B+:��Q�1��Ow�� &����������mSI�[
�k|qr_�7l�,����M���2����
1����hH������N�������B%y9����c�`���s�"����P��������+1�����$��($"�����^�it3"2������n�
��3�3|1�LQsO�_:�����*P�`�n�h�������"��A��s�P%V�"$����iS��������������������rmJ�mGP���Vb�S�9b������d�B��(�"��
[T@��p�SW����� �t~n����V��l�QG��Ox����.�!'E�lt��>�%�6|���<��J�/~�u�Q�^;��ZG���#��hb��a��&`�����
A[�uH|�m5H��M�&X-���{N]���L�����@��k�T�ZB��#��L
U0�N-j7������Z>����Y�
�)7z����L�/��:�bn���4��0�U�Hv�� L���Y��v�m��;��HYu�@�b~�{�i�5�	.>�����V�����"Nsz]���kR/�HO|����&�N���Q�\I���,������Ix6A��^���'����!��-1�>�j�K����{\����nk�H	~�pYa��=N�m�_@
�U����7�����6�-���5���mYi�n+J[������;z�qt$@%
�,1���|���)��u~�������y��!t�Q�9�H'��� wA�@(�e����=�*NW,�#�? E�5���@z�$D_DN�w�s
���������a�]�������L��5u�Z{��������5�&�����O�3g�i3��]����$����1?|���8��,���8
`��e<���)&�L����y�����Q^������p*zs�M��LC�]�1
�]3'��~2�/�
M�	`�D8�h���_�'Fc �6�|�����UB��D4p)}Z��x8)tI/�V�
���EM-;^�Y�k+�/{|@�3�Bm��?�aaj4{�Ub;�88����*�mj����z���s��N�
����4'H���0����2�Z u�b<����W�0�cX���jFn�����������'����2#��k���t'_�G���K=2@zts|S��f��yg,)V}H�vn�e�kwXX�r��)��!OnwJO����)=P;�[��E�����G\���E�qY=+,��bfzR���\��/���)r�b�K�������k��[XOa.�puK�Z�5H��B6{��'�bs��m�j6���
=30>�	G�Y1�e~�����Op
ew4#�]q���������
��\#�Na>��$?���A���dJ�V
b0�6��9(����3��
i��x�9��40@�k�G�����K��ts�Z*�e�����Y����a�&
���"O�!���?����/;��[,��@�`�:���L��Zd�����~u���S��i�O�:?���3���!�����8�ml�(�+�����
��`�=��&���*U$�>���]��c�)�KO;���-��f��Hx� +�]y>^��2�g�d/�]A��V��({g��k�����#:r��������MH������a8�1>k���1�{��IIA���F�n�`���� �"L�[�Op'��y���!K(�1��-r����e1\��WB��sX�u2�����C��7�X�9$C�:��j���gZY&��I���;���6?����~�R������NV�m�Z���4���J����[
 �@��|lug �0�}��{iN��
|��x!.
�����|�T����c�e#�%�.,������^h�����3Q�t?J�nx]�KC�>�_�����(��D\��v���nW��e{�rTtW������K����S�L�s�?XI�qss�&��Ly����������dq���oc��>�
B�lj��(�[Y��~2L��G���0�p%��TVL6�%4U��jQh��ko����.����!,^%�-�]4i����O!+��v�J���A�1�����w�]�Ab�,Ww0��'� ����m��D�_~9C+�{��������&k��P���D�y��S���F-V��������S�����,����:�82gu&�
CJ�!������jF�-9��������I@6g���}>Q;�lfH�u����v��vv��L�}���AG���	E�U��&��F�:)���q��������	�

�J9���_yJ~Sbf���r�Az��E�JH!'�Y�!e��u�:� �d��4��Nb��)eJ<C�$�HJ������?�j�S��2���.���]�ub�=�Yp* �����v��{c�HZ���L�Ct�������6����
Y�M��-�L������d/���I'0����8�d4��]���srM��WFI+"%�e���nXU�����l��-��u�K��������Nd����Y��!�,�m��?u���2��mI������V5j,_�����8��C}�!�S)<k�0f���/vf�/�uQ.5Ri��J����L��#"��/�};�����0]����f�"a+��,�*������x�":vg�3=�|�BP��H��4��pd�
7u���.Q��4�
I��eBg���q�2�MG�|R����y��N��'l��.0�����P?n�o���
���[��N�������A�w��5$�(C�;��F�J<�u�A����s�(��S����8��:e�%_r�Y���+�
?S�r����]�V_�}Z#���0)����Rc��I/E��;Dg����C+_���M7L�H�M�>g��p�uP����!
(Un��T��JE�W���p,��OZJ[E���l��e�W)���BL#D;�5��RQ�M�$�GQN	���e����P�T�q��b���'��
������/8	��_��_y����J����b��_k������[��R�(&=.3>8�Q
�4/-,Q��**�v'�q����)�
�^I|�G��6C��.E��]"T������w�����7f��k�%|�~;���d�$A+������>�prLV�@>�>=����->���}q�Be��7��`?��.���i-��9Z�cy�7������pP|�����#Q=eR�o\D�U���*�U���e:��1Xde
�Zd%�(J1�,)��"9�'�_��l,��%�d@Y���c(���CA��D)`0��w���:���S�j���.�
��h���R,�$��=$�(���`�d:�j	���0��r qp���;`v����} S�|��n���1�BIG�����4�$n�������(YR}��J@����u�i�j���q�+�=����3=��0E^WH>!�	X���E��0�u@�]3&y��x�o��*6���sy�4(��p�Pb����������K����)�V4�[^��L|8���"��`f��]��{G5u�!io4
��K��[���r2���]���������!��</�^F�:|e��������'�g��N�����yq�_=)���b�����*�
�*�oig��}rf��Bh�t/+p�I��Snno^�_M��T��ZQ���Z3990p_�o�\�rx�XLo�-�~eRk��?��n5������$��k(��� O�pe�^h�Ub:��@Emm!��T����{���8�w�*�9��W������#\�gi_/�/�p�iX��Zx!���X+M����;������V{���Q���"F�e[�n�9�b�P��Mf���?$��Og^p���)ZNm.r��i�-R���i������i�����^nT��F4E~������2�Y^" �^�t�f��K;C��`��Y�ED�����1����(^m�����n����.��e���uB�X���`�����~J�R��8���k����KytaY�%�^xH�^�n���\{6�L�]{���d��9����v1�G���CG���va	~��&���2���������q�%!����(�B0+�0�h�D��.U���1���4����U���;w�8����4o����9���*�6(�i_$:{�w�u�O�RjM���f�	����m�C������	��Be�����i���*����?f9��mQ�&z�:���38@O�D�o�8�����R�{����8=���y>�����	IV���K���������J���AL�X6��.���n������7����D��s����oIJeI��)�1��H��VjM�i)+�X0X5)���g��GE��)�3Ahd>�>�bh	/&�TZ�3���PgG���OO�O�+��T��M��k>N�����al4�G�<;������Y��9+:��
�o��l��c�`y�^~Im�<�=6(��}���*�Tn��ux"p��!�0p��
&uy\�J~�,�]d�4q�NM��Z���Csw�@���aL�u��Q��Y��,1
�������*.CA�/�=n�� �_v��!�TWX�p������YS�T�J��:
~��&�t��{�,p���i["���p8�y��^�Cg������Z��7Xs�S��Op��w���#[
�Lj��&AC
�yl&�����4m{���D�ZA�f.f���p���*Z���DJ�vP�&��<�F����U������j���6��$&Zn�FWQ���E���P�������#N�My�.��S����}@�����������B'��TS�!�]��uM����_�>5��F2�=d�.y����X���:*�K���ced���'�EX����5-,�P���B����:����8
&��x���\�BJ�a>HQ�H�3�&�j�
*J�li1i�������IsWbP-��^ZNZ�����#�/�
�����48%����	F�I�x���iu%�����&HK��@VEQ$9��
v;��i�(����s��W*a�<vZ��eR9����n�x%j'�R���?���y�{�R���vd��0D�r�S�%�&`�,#J0�t_C���Wg��L�UC�� ��v�=��)�����[�D��z^��p�3 ��;���l�G�u|��]��X���.�"�y��������/�_�	q�a��G:+H>���_Af�s��7��b�����mA'	��4��+c��>(���(fA����0��� �y��ob������ ����i>�T@���t1��_d���ZRn`�rk�����%����7l
��'��������]S�����:���������bA���h����$Qt�
9p+q�6����3��i�].����7���u���X�Pl�������vA1�����������O���;���u3:<xq����f��q$������3�z���e�;�����vP���j����.���������L�l��, ��zeD���-�"=��T>�W���N�;U'�����(�v���5'Y�R����p�T	�qUN#/]��
��w;����.�
v8	��K��-����;�w�����m96vS	?x�v�#/u����b����wm��k8����w��������_��w��H�o!s�%�I*���Qr0����
k7����U�0���b�T��VI]V����S���a������2�����m�r<��m�C|F
�'�L}e��c���H�U�4����F���jhm�k{Z��2A��L����iK��Q��#���I�HsC@i��x\&Y�K?|��C�;��i8�{�`���>���9�i(�:}�`���?lkn����/�V���h�*0\��^�-kI%�}�����t���z�6:�PN�#���l{)-0��3��������RQ\��Z
���EM�hm��o����a���~�O� B&���.N�����O����-=�(��B�'u��E{E�mX)ZU4�������l�H��uL���e���G.��,P�K�G�o�Z����suB
�yez�\kz0�X�DN�}KS.�K>��x�@��*>�bN��p.0�,��?�X&-R��O]���6��^@@��-�tl@4���"6&H�H���V
e�k�m*���Nl6�nnm2��aS_�i����;�@�h�9�4\!�2	a�k��M����n��z�����'���:�kd��0�k���3�sYHu���!9������#�U���n�y�H��`��e
�2�>�i��l��e���`����',W]��F�������
��e�G���L��kJ��unH ������o���-g���C,1�������u,��S���]�`..QE���l������z�c��[�9������.`����O�����V���j��������+��={C��X���]tM�z#�_o��+��1Q=-�����J.����>wX3p��
��f�^[�)z���/.�	AJ}���ZPv���~�6	��X��r��Y��,���+S���%���>��8:�B����2iY�0����+o����8��:k����x];VGV@0�"c
E�Q�\��=���o�������WS������^�6��mQ��SdT���.�),�?��!-�����u�����z'VL�R9��,&�z��y7��H���������@�c�HM�Y��
��	��jv��Si������;��A3��F6D����:yv��N�f���f���
�������'c�?#�����N3���R�\M�hj!�+$���6�t�F�����|��;���?��N��!�pS���G�mr�^�������l
��n��	[���`'Uq$��Rc������;��Y����uea��(�hj��lX(O��N�)8Y�P�s6��L����&mM��|4�&���GO�'��mO��_��p����X_��}Y�Rg�TePLe���Z���7�
'Yb���3�����-�R������9V�R�Tg���Y�+���)a�S����	T��E:��k�*�g��sZB;*��$��*Z}0J�W=F@��
O��p�����\N��D"���"�_	�����!���VZF���\����K:��)y�.�y���+35���/f(V�(��Q����(=��gu�5���WB�������l����@�>�+}[P|�~5�K4o��BT�sU9)�r���U"�(�O5�$�������m�|}c�0"a&U4���?��^����3�X��oT�2�i��o��X��W�	B�k^�-�b�p~����X�
�m��/�^�F"�����T��{Q�T�(SA�����,���BG(W��R����A�T���Od�J���u���u ]���b��-Xr�<����w�_��:�qi��OV����O����gmm]�yo�'��lf��
��@vZ�wt^�j
�=�9h�����[K��������{�����w�&�������mmm-i��?���w������>#������"��/��z2����H+G4O����5f8��u^t��l:�0&����)��x����
j7B&p��n��-���t:���������u������d�`A�K���bft����1%4����O�)8x��8�����S��><����O�������MG}
�����y<�i�'6���Q_j���bz������U�y�&�Vw����Y���M?���^�z���r�)7�G����������h	P/�A�B ��>����8:<�J�o^�4��A
��Q��wGo��<��n=@D���mvv�����5;�{����6�
W�����?���x�<}=���Yr����[�M8�8�~'�,v��,�N�.��5c�|�l��&g��9�f
4�:r��e{���v}0��z��{4�R�$��-"���>bQB�v����r��`��'q^6�8�rq1�ne��)�0-:u��H�1����P�`���.W���@�����J7Q����O2J��PX�<��� ��\�f4��E�M� �)��Q��.[�$�"���wjhf��A\g)
��f���j Dg�<E�Q��Dm��,��9��c���M���p([���7X��!%<��1���������T����e���06�D��r���r
����=��I~��e}���!�|{|B3��i���p6����O&�b�6�������
���Yo�)^�Dp%?Z��������T�r>:7��M���c�0j�`��|������s<���� *{� �v��3���&���x�$��y�����K���[�%�eK�����9I�N�����::Z��g�&"�4p�]��w�;����!k��{���w�!��?��������y�,���h�ah�����I�z�������}h������l��������2��}��yn��aB�7qPq��2r�^��,�Z<
l���|���^���n���o���V�h����1�����;��3!��1;�@ VX� 3@�]$�8��9�>vQ\[aA/?����%m	�4h�>LV�?���|r1�"�0y�$}0�$�dg����Go���|���{���c z	A$��C������:�`���mj!�'���h%����0����69��C��"�p/~�p��t&�w�J�CI�E�P�(�f�+'t�������M
��%�{}F~�A���g%|�L����$Q�
�$�A��qo��1~H(�>IW=I�9���"Kx���{��p)�Q�pN
c�Kf��d��QmItcf����dM���G0�7G]`��vw
w��A��:�����.TC/�5|�����L�q}������=8�G����={S��Q^�=��_t����Z�re������5Yt��wz���N������/�`��EWL5/�������������6'�f����4
'N��������C�f:�ct�g��������f����i����4��.�K7������&��CN%E)��y��M�,�b�y������pqm:'�w�`��s�Q�7YV	����\�~<���H�o��F?���I�'2V�
h�-���6��9[�+{!?�t�S�;��=��{���E7tT�/��(��!,f����
D�=��j����������o_��~a������/8��9 ����)v�w;���9��F��z��}�����������	��PhF�t:���7TT@*���BdvB'����x�+,v`��p�� &
"�7���X?.���>q�q�������n�~��j�f5���K���
N�9�P��[Ff�3d�J��`��������w���5�0�,\E�T	�7��:!9��;qgC��=�B�G�y��T��B�N��/��|����
R,����������f��&�������X}����[R`H����~�=:�n�u��`��E,�������[������}�,���������:w��;��b~�����fS���Q+�R�c{�(�~�)6�p�9�-w�
\���73�����D}-3*��Wf�t�,���Y_1v~�g)*��SJ������,�D����N���AR#��d����t�G����Ow:;m����%��b�����aG��/�f)Gg'�6dz���Lb�����In����;���������2��(i��I��������h���o �T�f�� o�i�L��Z��������#�������yK�UJ�E�x�]m�����/��[m��6
����a���;~�����7C����e:�)F����ON��{{�f���{�Q��4��[��;��al��V������t>Eu��N����K��6�$��S���*+�(����2��[�*m��uz�Z��I�a� .!�~_E2������QY7�k�
�VT��nfM�D�����w�������'�zC�0�rQ�x�n����l2��wIK���P�&���q2b/H�DRW����{������:�O[<DD��������?��m��<
#51Heikki Linnakangas
hlinnakangas@vmware.com
In reply to: Alexander Korotkov (#50)
Re: WIP: index support for regexp search

On 23.01.2013 09:36, Alexander Korotkov wrote:

Hi!

Some quick answers to the part of notes/issues. I will provide rest of
answers soon.

On Wed, Jan 23, 2013 at 6:08 AM, Tom Lane<tgl@sss.pgh.pa.us> wrote:

The biggest problem is that I really don't care for the idea of
contrib/pg_trgm being this cozy with the innards of regex_t. Sooner
or later we are going to want to split the regex code off again as a
standalone library, and we *must* have a cleaner division of labor if
that is ever to happen. Not sure what a suitable API would look like
though.

The only option I see now is to provide a method like "export_cnfa" which
would export corresponding CNFA in fixed format.

Yeah, I think that makes sense. The transformation code in trgm_regexp.c
would probably be more readable too, if it didn't have to deal with the
regex guts representation of the CNFA. Also, once you have intermediate
representation of the original CNFA, you could do some of the
transformation work on that representation, before building the
"tranformed graph" containing trigrams. You could eliminate any
non-alphanumeric characters, joining states connected by arcs with
non-alphanumeric characters, for example.

- Heikki

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#52Tom Lane
tgl@sss.pgh.pa.us
In reply to: Heikki Linnakangas (#51)
Re: WIP: index support for regexp search

Heikki Linnakangas <hlinnakangas@vmware.com> writes:

On 23.01.2013 09:36, Alexander Korotkov wrote:

On Wed, Jan 23, 2013 at 6:08 AM, Tom Lane<tgl@sss.pgh.pa.us> wrote:

The biggest problem is that I really don't care for the idea of
contrib/pg_trgm being this cozy with the innards of regex_t.

The only option I see now is to provide a method like "export_cnfa" which
would export corresponding CNFA in fixed format.

Yeah, I think that makes sense. The transformation code in trgm_regexp.c
would probably be more readable too, if it didn't have to deal with the
regex guts representation of the CNFA. Also, once you have intermediate
representation of the original CNFA, you could do some of the
transformation work on that representation, before building the
"tranformed graph" containing trigrams. You could eliminate any
non-alphanumeric characters, joining states connected by arcs with
non-alphanumeric characters, for example.

It's not just the CNFA though; the other big API problem is with mapping
colors back to characters. Right now, that not only knows way too much
about a part of the regex internals we have ambitions to change soon,
but it also requires pg_wchar2mb_with_len() and lowerstr(), neither of
which should be known to the regex library IMO. So I'm not sure how we
divvy that up sanely. To be clear: I'm not going to insist that we have
to have a clean API factorization before we commit this at all. But it
worries me if we don't even know how we could get to that, because we
are going to need it eventually.

Anyway, I had another thought in the shower this morning, which is that
solving this problem in terms of color trigrams is really the Wrong
Thing. ISTM it'd be better to think of the CNFA traversal logic as
looking for required sequences of colors of unspecified length, which
we'd then chop into trigrams after the fact. This might produce
slightly better (more complete) trigram sets, but the real reason I'm
suggesting it is that I think the CNFA traversal code might be subject
to Polya's Inventor's Paradox: "the more general problem may be easier
to solve". It seems like casting the goal of that code as being to
find variable-length sequences, rather than exactly trigrams, might
lead to simpler data structures and more readable algorithms. The
still-to-be-designed regex API for this also seems like it would be
better off if decoupled from the notion of trigrams.

It's quite possible that this idea is all wet and no meaningful
improvement can be gotten this way. But I offer it for your
consideration.

regards, tom lane

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#53Erik Rijkers
er@xs4all.nl
In reply to: Alexander Korotkov (#50)
Re: WIP: index support for regexp search

On Wed, January 23, 2013 08:36, Alexander Korotkov wrote:

Hi!

Some quick answers to the part of notes/issues. I will provide rest of
answers soon.

[...]

trgm-regexp-0.10.patch.gz 27 k

Trying to build this I get, after 'make install' in contrib/ :

/usr/bin/install: cannot stat `./pg_trgm--1.1.sql': No such file or directory
/usr/bin/install: cannot stat `./pg_trgm--1.0--1.1.sql': No such file or directory
make[1]: *** [install] Error 1
make: *** [install-pg_trgm-recurse] Error 2

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#54Alexander Korotkov
aekorotkov@gmail.com
In reply to: Erik Rijkers (#53)
1 attachment(s)
Re: WIP: index support for regexp search

On Fri, Jan 25, 2013 at 11:47 AM, Erik Rijkers <er@xs4all.nl> wrote:

On Wed, January 23, 2013 08:36, Alexander Korotkov wrote:

Hi!

Some quick answers to the part of notes/issues. I will provide rest of
answers soon.

[...]

trgm-regexp-0.10.patch.gz 27 k

Trying to build this I get, after 'make install' in contrib/ :

/usr/bin/install: cannot stat `./pg_trgm--1.1.sql': No such file or
directory
/usr/bin/install: cannot stat `./pg_trgm--1.0--1.1.sql': No such file or
directory
make[1]: *** [install] Error 1
make: *** [install-pg_trgm-recurse] Error 2

Forgot to include these files into patch.

Another changes in new version of patch:
1) Get rid of recursion in trigramsMatchGraph and addKeys.
2) Both bos[0] and eos[0] are also included into checks.
3) Get rid of strnlen.
4) I found the way to fix work with collation in previous version of patch
to be wrong. Collation of operator must match collation of indexed column
for index scan. Only thing to fix is passing collation in gincost_pattern.
5) Some tests were added which improves the coverage.

Now I'm working on additional comments.

------
With best regards,
Alexander Korotkov.

Attachments:

trgm-regexp-0.11.patch.gzapplication/x-gzip; name=trgm-regexp-0.11.patch.gzDownload
�sQ�]{w�H���|�Nf3�F�y��9�����|1��lf�#�k-$�Go�����[o$Y�83�r2F��������k�FQ�KR��T�H�����8�����Z\H�t�j�,R�^����:kC�Dl4:��UW�g�i/�NY�7��v�{Q�T2zyQ���z�D?��(�
�~�ImJ����^�����"�����%����+������n���j���^78��?f����d!q:�
���Xo���Zp��7�|+���rz���txu��Ql`pQ{���K�����������%��m�J�B�T��������2I���'*
Y���bc���r��&�MV���1&������I�j���w�]Q(�����X>b|�����%���]���d:��d6�e4$6�l�U����6�~I~���}PD���&EE���^!�[�b��w����F��+��dk�q��jRb��$R��BM��gmj����+����W��	N-���L�\
��x)��bHQ�J�K��C��[
�8��"����x(���&�H�[}�+���mT���n�K�������������>�p�(t	W�j�� \U�L�B����{gV.9M�%��������>��
x�{|^v�71`4�0A���� ���<�K��J�0�}
�C�b��m�4�Kn'�=4w����El|��`e�[�?�L�b�&#9W��B�=�M*�4������,8�������npb�����	���F��h��~l,�G�!Ar�����e�z}!.�~#%H��$�M�hCZz������X�a��qW�@k�Xo4I���$�l��
�����3E6�@ �d�f�F��'U������|c�k��W��l8
��.����9�	)+�W�6�fH
��NQ�u��GG�9{���r8�&S�vpq>�
4B��\_���������>~#�s�~'2�q�X����_��������i����P���{1h��](�z�v�
m�s(]N}KU5�1:W���:8���'���ZX����ze���m��z|2�f`H��pvi	��v�L�������;pcpE�n�t9��.�E�=���gCrB�f����u2��G����n�;����s�B��^x`�j�h�7v�����:��P��!���#��#,��N��=B�N�F�BT�P3�n��X�/��asa�7�I	�z����l0=��Y�L����]N''�����"�W:�0	a������=t�t�(��p��'�c�����C)����������O���M�8�tIB���<@X�qK���b���%�3���Bae;�$ex�c��U���G�1��r��Gd}>O;�F������&
���k�,o�����,\����(-g�1L�,]�UC�l�L��#5����vI�mj����O�_��*�w�QK���<���#�2MfdkA����P�ZV)i���g8��:�+i�T|�o]|'>T���hjH�����a���6����������%�)�<q��k�"��@bl(D�`dM�����+NF���hn��B	3p�F����aO�d��{��~����b-�������BKA�f2�"��f@�T �@+�_�_������	���0��]�$a��K'J�[�I3�t#tP�I�~��\�����p�@q��k�E$]Ipu��@>hR���;}H�	y��A` �rb��D��'?`1��+�0,�
�E�R���>�3-G�t�6<j4�8�5[S��"gE�S���9��%2Rt�2��4�5���J���� )e�Q�� %�����r��--���[���/[o���1�p��LO��_~'��EcBUo���8T������������!��%G��'�{U�S���'Ish�;~Ggb��C��$&�U3��$Z���rj��r���~�O�fs8��Bl�U�a��?�W]�(6y�a
�����6��5:�MT�8��2���V.���rmH(��%��lk�����V��A���p^�6�.A�
Y�/dIz���7�s[@�$md����)�����0l[��R�d�Y��m�;��O���m�{	���l�C?!�-��D��)#��c��F������������OnJ����(�
*m��!�	�mP��V[{H�q���7�>�9l�&I��������m�1�6�LR&`��n����#��H�m��q�6���
�FD����|��K;�����`�j��;	�iu;'����`���q�����	�~R`�j��{����~����I�m5�E3�HK0�{�m�	��m�	��m���m��?�M��l�Ng'�6 ��z��/���W���7���_�6�A��6}�>�M��@Ho��M��'���[z����>��{���Y~�v�l.�6����U���jl��m��ms8���ms8�g�m�]�m�=["l���j����K>�[g������w�F[���MI>i'*�)f"�~���z�����0j
�k�����^�
�"�*C�T���b�08�J�|���B� �`�
��*�xI��
�75��A��i8�o 0�1����i�BQMo$X�����X�Vt��r���q�OG��A�Oh�fD�F�	Fi!�n����Ti�)j���f�Z�;�(����b�szP)����{X/���n]����=����[����v9�F�^��{2��)v��5����>HhX|����������99�]��t��]�a�p�2�a���s�r|����#�t�0���\�w9����z�#y���$8^�������W�u���7ziG�\B���-L
������#U�5x%�2���f��WIE��l�ExOZ������7�B���j�$Oo�*�s�r��@�U���%���
M6,��I��}�q4{B���fWh��h��x��W�2�tu?v�j"�P�`f���V��yb
���S�~���>P��B�B�����
��|#�l{�C��m��@Z�j
X�	�%�+*�tc�vG8���;!_����N�g8���G�
F����`�.��c�iO�
�%�\(��,YUK�Rr �\�9"��2��2��GH-I��uj��_K���-�rHV�W�'���w����s��������
�~����f�=@�6&�3�J:�/�%k#��gI����lzvQ���8��Tr���.O�U�b�JM�:�|\�"�V��|�����kP�/��~�a�FS�n|q�
g�����\��05�>����*��������C��!�G�hJ��u�j���4;���Pc�������[�_�����[�����&|�B��%Sw�=4q�W�V�D���:b.���0��X��+��~�j�,���l�M�Zs&
Y������@CQ �u�UE���qD\l	�����M����*�������n��[���9���sMN�o0
�wnR�\��a��Cx_��Bd*L-�LTX?��Ih�Y'��x�y!��
kS��_���*;7T�-�s��a�c>G����st!zb��9�O��,�,�������;���)63<�K,�+���1p�<�{��|0=�*��{
���|x!�UpY����Ck�H���`!�N����2d"&8ck��_�R��C-/'�9�R�|��~��^���0���\!��$�hs��uG��j��z��C�5�����8a��l5�����N%�Y��g�b�������\�����b
�4M�iR�k��i*���(��]!���1.�c,�Q�����20n`����T���7��b
_������"����	b�O�!xt����O)%{������'�}/���O�Ot����P(,�r���d�+�#�7��K]���x2����a�j��4�N'S���DG7lr#�
XEH�@V7��,D m����W�����
�v0����5�6��7�
G�	}�����K���Rs���ZF��#w�}��5v~2�3��q�\��)�A�������2��4�����A������a����{S������
a/$!�o���+v$=�,�����J7�I��Qrc!��L*�c.D�����{k%�6��J~��nU�e�V)�G���G��2Yy�T��i�E�"#c$d9������g@p�C�n�Cc������Z�����j8����_LN��Z^&��P����V����\-.���/���;�Iec�������\K�k�������Zf���o)����!�0�GG�66���wlSL
dq����c,C���Q�+�����/�+E�{A���V�&���D�!�}�v�!_ F������F�������
b�A���=��#�����(=���S�����V���r $���7��t+�m�����[��G'Y�}�{�m'3a2��J��1��r��V�M3�!c���fG<�`@�sZ��R�y�e-Nj�MzN�e��e]e�T�z�+JR���^��VFF���:��*���d�������	&���nW��|�fR��L]vL"H���'��{l2pU�A��3LE�1s�F55JkCtj^\S��%�&�Ob,U2~l��!����b��k9��#/XM��� k�jX^L�!����b�����P�@W�X1�Z��� ���i�)�}�A�c)3\
f��t������
*P)(�C)&�nN������j�U�7��7���,T����l��������S���ozvlo�P�3�����%+��Nh�DWs���+�,lDx�o�=�`��Je7B�
���+rkV�z-W�<�����Fp�+��t���'�8[��`�A~���������9�������|4y?�B)>�����M�m/��V�C~��V��=[������>.����l[� ���l'�:gM~�M���7�-��Cz����"���C�HI���+��Z)
U��
(�&�n��leW����d��X/{P�4{t��p�k'Jqj6���/��nI�
��"��D��5����5e�[�����f��(g�&r_�=M����j�M�r��E��������d��$
+�eN�e�^��s���!<]�(R'����������	o�E�������G
~�e�'we
k��7�%K�B60X��L���j	�V`r��_ ����4�w�B�{[i���Z�6mk������)���t��u�dN�<gx���"5���xE����z�C6������ubZ��F_��k���P��{�~�CT\xFh�h�������l;1���0z���a��RN��=���G�����
�%@
�^���G�L3�FN�'�����i8��H���`�g,Y�w����[���H��4L]�B�A�8���=?aP6�W �B����+���U�v�,��R�$������0'��|��t���8"�%�+U��BTB���[{����F.���_e�L�+r�3)�OJ~�Hu	<O�_D���
���YB�<���L��)/u<��v���M9,M�s�	���I����(��"z%���p���%0�L��	.'.���L3�h�������2�q���;NN�1c�&]���p.�X�������}��)�vm>�������$���R��J:���qr�=���a��������P���ppoUZQ+�D,��a�X0���;,��k���?�A���X7X��2q[k���I�����[Jo�!E��!���q:P����h�Lf������������a5Y8�h;����9�#T[X8/heT�}z��g��G�=2���,&��Y��d���������M�7=1����������m����_+��)J���,�Qd9���=�<����"A	6I0Yw&�����]�H�Nn����wbhT���]����:Y�0����"�6���H=@��q}�	��O�{�c>�@�l�-8����:�D}l	���9��d�6��+����Y�~$#G�@j(R:H���x�J	���41�<�_^���5��7MFQ0`�I[ N�����E��5aIA17��h@'S�������G�x�sl�g��[���T��#4:������#������E�&�jE�q�`J/b�@2�^���.�8�k8T��8��=^;��F�n\h�5��/�m�ov`���c5�����j���3�xv�E�$���i�O��tl�r<���7��K�^6'�`�S6�]fT2��c�D���������f�F�'�rv�����~b&k0�H��W��G
����-'�<��N�nUD\��'�j��\v RM�(���i#$Ed��Kqb�h"��sb��H���.8�Xa6i����'����6D��e�,�al�= ����Pa35b�4O�@@��+H��k��00�@
��&���3�0�+S�~M.K�d{l�3��{�'}@@^l��V�Dd����d~4A�kF�Wc�YV���eS�����\952�<I���i=:��E���������<�q�����x4�%���%Z�,'��[X;g�76�2.H�zU"���c$������h
�e����.��������(\�T�P�1��c�
��7f��O�"P0��d&�c���{�zM�-�i�11Z<��h��X
_���t�����a����)����$�(��u2��E���
DG6�f���++|���		}Io��\DhV8z���9������n�a��v�LG`w�}��B���y%��B��n���BM
 [b'@��)#���+.c63g��q���[�*R/��� tc���21+���%���I�B"fxm���n��/f�DG��U��,�� � P��:�p���&����eP�yLC5��a�#mV
����B�q~P.nH�8l ��>�p�,-h��Y������}����9bn~�
�l��)����Y1n:��[��/&��* ���.��%f���"�^'=@Z6���/:������`�	��l;��Uz
pw+�9�.=$W�\b�e����0M�(b�N��U�GAYG�'�R��Cj�Tr4�>��9��Q���X�����b����~��%���=a��Lg��i�1��P
RtqK
���^��%#����X�$6sJG�h�l� ��Z
KD!��2i+Z��e�X���P���,kF����pZ��Dj(��������5������}��������@�Cj� Z�d�Bz�;��P������g��3l$v��Y��.Z�*#
��rT���@��|������o�3#������3R��@f:���JA���*��I?�Q�oC�����9��r�pj0�<{buw�b���a������V2<��(���ERX�Td-�`[rh�I��_d�CZ��F���HZ�Hv�E��-���@�0M,�����
v�t�`���3��{�l��G�������
�t>P���B,��Vt��0v���5������o���6��\tQ��Q�wD1H����g�g�g
��7Z��U�$�e
VG4���������qF[�K���R �M��;���f�����Q���`�NsL�=�	h�7�g��<ETr�c�e�0iN>+!�!$���&w(w@��*b{
�mz������y�V�Z-�`Q��M���~�Y��W�e�J�%����y" �����i�����������1	��6(�Q6�D�ZF\����Ez97����D�Z�FG���M��)���(Zo������/7�m���?�jY����/L[�����x����G�
C!&�:fp��=��������/z��=��F�
�U>&�D��{�gAyu6��{E�chn1������@��@z����2�����s-�@���4E������������0=L��X��(��S��,/���(��B9<i��p�l���9�WF>+$t&�����>e���	: �P�S�M0��n�/������raM��v��tB�1��_�Mk�f��`t9
������t^x�~�k����qf��r9�y�6y����r�N_���������1����WD�,-"4�����u��/��<�yF
��,�B��a6�zW����6��wc)We����(oX{�������'yI>���^�//Y�`��v<I#Q�X���8�����k��Q���D��]�����;�,�z������������w������B15v[^�rOL�l��;���=jN����4��4������a`%�af�������5P����{y�=;?<?>��@��� ��t,L<�e+�:|{�AB!�6p�:��SF)(�`6�0�Z����=��Vk�t���n4�Z�����o�t��]����"a9�@�P�]�j����zs��I|��������������O_�t*�\�N�?Q?���B�����#�8�<�]�Q��? [������v��"8�#���&�F�*����#��4\��?��  ���^�q
�9�{����	c��8v;�EJ��2�eG7?�q�~�0P�7��s�	5D���������q~������s����p>��F]�f_�-a�i3g#J�Mh�8<�i(�oE�a|�>����I�[)��q�����PP����k���uu++�f��i6>�l��^S�?2�'Ao�5�����p������2m��;>�b��oP3�xd �G�|<����O�
�Hi��g�C�*�@B@l��tX���q��F!�
|g����9������t+�x�k�W�p���Q��(,#v����4��]�$��n3���;.�(^�7`L���Ma�i�lC7�}�0@#|��~[Q��n6���I��!2$#'�A��7���M��XD�����ex��I�7���4YV���k
`�J�3���J/�<b�^��V���3�����?3��X![��H���.%���P�<�����f��V8������Z2���N;�3)�s�X\�������ti7<4���h�����%V7-��~h�
@FD��83�!���C�������n��.4�1Q`Jd�"������'@`g�����ni��"����\�*��'@\�O��/���E����Q�}�5P��g����e�����o���R�����PI\*5r%p�Trp��������i4*p4�H��U�0�B�}i3f ��*z:������$��N��N�3�-@3�-�|.�$,��!����Jp���~8�U��[������A��F�3p9�x�$��46�S0��+��i��{��o$�VRk	*��p4�����[�e"h�����f&�q�-�T���<��Unj[��	W�q�2��)��u�YzH,��U�A:C"���V&���9�rh�tiy��K���l�e;H�K��������#�zV��B�:"���\����0c�P"w](��S��n� �9���2?����x�������mk
a��Y8�����D:#_'����80:x�_�M5�Q�5��c_[�?���8���X�D�6)n�GN�*�D���� �<�t����5��@A��)�G����A�j�Y�$.I\H�dK�������Cx�&�������at	V4����[T�)����2��xO����;h�h$�2k��k�{E�:�����`k#(\�`����D�;�+v������;�4-��))����C�����j|���n@W��0�g�~��jx�Vk���4���g;-����(�|����3T�����/�V�d��
���,�02=�;L��Q�&�T#,�����5�L#��5�.��R�<����4�r�M��SA����PlBj%e���B��������"y��[��J���O�q��G ���>&��6J
�(	8sOP��[�|���X/"�t%��Cj55u�L��0�\����X'1�)�]��y(:��n�L��D
'*.�����c��T������3�c��!�`q_c:`n%��U�A]�q[�8�A$����^�y�����������#���
�Z4/����-9������]�"��j�\�Xl:�+���Wfh������;V�d8l4+�\����m���tW@����E����������[#�\�0��-��C34%�+e����8�@�g2��0Q�Q��:�����d4� I�"&�3�B=-!<������=E��Pw��Ezc��o����c��r�a�L�_a��.9�Pq�b����Ei���gCI����5����k�Du����Q��g��4
}���������`�8
8�+��;*M���>����FX9����R-�����I�r���d���qz�������V����i+�.���BM�/�a��Sn�T�f�W�t-��hH4'���QP/��nEo�DX,��*@�<!��	��PwR�0�M�u�����0���1����;������pN�m�+0G�
[�[m�����T*�h���R���-0�3#���Fr@2��\�u"?5dP�$�)c�_*�t����q��#���u{��'u�l�0t�������y�/�y�Ae�o�����AI^�IZ�V�AS�z6M��V����� ���zF�/��\�m,��m�=�P�8���h����{1E��d�
�{V�t��x�y"�{qYV�LX9=4�
���G�V��=�������1���)[���B57���.�����lq��'L���1'7�U;�{"9S%R)�B�M!n�Z�*�k�^��������x�����jF"W`Q�p�x]�z���{`e@�M0���&�ew)�D?u����R8�����I���1��z>+����m3OZ$�V�zgF�����8���H��h�z6��\�h2��#d���Z�������a�^�
Xy�`��Y��d�G[�:��]9fWe������w7�|D���T�l��7���}2=}��AE=�C�ws�]8����?}XP��^�
��<9g�3�B+:��Q�)�H|��� ��t��L��� "����T���*5���/�_&�,��FU����Q���o���Ap�Ii��"��i���3�m�C��
��k!���gp�����H�g��F%o��5���_f���dR����QT&��`-l�h���Ajd��aq?����;����D���iG0|6�@����2#�/.G������2@A����o��Y\XU�*J��g���-��)����_�L���m
?-9�}PZ������)�� ��l~aN�a<V�N����'�'��-�R���+I�3F��@��P��8��<��Eo.�u�g�2�c�%���X�qY��d�r
��-,��	_:�8�e1�P����-\��)TO����F����Et�Q���dg��Q���=�\.�`dp�-�d`�L��cF��.�0���v���J�����1���'�d��ZRa��5��CN(.5���V�-�9
��h6u������F��k�\�#�?b=�2��9��3����e�
)%(�HO`����	w�dKH���?�YYir���j�����������z�>C:����S�$��0��5/}�|"�`��5�$����"W�������m8����(��
��Mz� ��>i���K��q����e����(m��q�^	V�Mz�i'����7���a�� �O�����.pV��R���=�=�,)�>{�,H��������
������G �@]��tL,:��HI<�0��"$t/L	�\G��R���a7���^V���"���&pot8��XIQ*��f�j��	s`�����U�cjJ�hy����k*{��M�^*�L�gp�_���|�b���������g��z��J,���.�n6��d�I�;k�LX�4���-��)B�XcA�n>=?��(�+a�������A=�<!�������X����0����a�p���
��'�,:f�
�5,�.���
9�L���a����3#�NfST��h���$$������5���b����=��Y`�t�!t��\�M���C3�O��O�GPy4en��%�����v�>���j�Kc@ctc|C��f��3:�Q���(������������b�]S�CA����KF_��;$�E������\�_���S��tH0Jj��a�3�����<a�!�k/ ���9L���q8,D�@��2Wwg�U�\��&�~�7*��(yV���"����h�����3�p�"KT��h��(�GQ:�dB��Zw7��~S����l}��i�������A������
U�T�XM{��01����c�����{.����w��r�>����vIS7���RF�N�L�m9j��a0iF��<Z	�@�rC����DQ1��N�mO�rC�u� e��L�
Q��>��1���d��!$�6|�uZ������a�!���<N�!Je��H��<���
#d�SyV|�.6���#L�%�`���b��O#��[��.��{)L���b�!M'����c�C_!��N�1�����%��?.3��QL��"6�DEoP2T.��`P��r
$�z��J���Z��*>��*�c�DA},�/�d����)�y����S�c^�����gh�\9zf�,��(��>~�E�W����u���!4�k�)i.��zfC7��O��i��-B��
��M�paQe�p\�C�[�%%�Q���fc���JA�
)
j��'�j������ fZ�n�����!�I�3���`~��U��NX	�6�6�w�x�YmL�����,_��������A$���g�+�uvg��
����2���|�����������b/J��g�������m=�����~�}w��@�K��?�_��g�TKH���G|AVG9����U+:�������vN��[�tl��1���86���3<767n����X���5Q#u fc�*����7���sB"gg&`���T����a2K�����������:b�t0^BS�^����rn�!?/o@��G�UPnL||���@2����9��OSRh��Z ��krv5E���{9�6�����^jT���fD�q��U���>�9h~�������ggj��y����%�u�!G�����M�[�����m�A���a�IdK� ��p��J�6����~>�	�r�3'_����m�%m�x�j�d��S_rp<J�A#<��%O�/yR������s��W��7(
��dM�|���ISKP�e�����	ZW�Z�l4���[Jt���C@O��
�R��A��+��C��"7,�����aQ�����'��v"M���D�T�;�W�#�{n��C��NK�Z��mN��<~����!R�����66�]��X�V�A1��p������i-�E���W�FP`���dv��0�O�k*�x+Ztj��.��mP�r��\��������dO�����G�����Ye1��c�UE<�C��LJ*��TQ)_��T�����v}e�b�� ��S�Q$F�RK���������"*uF��XeN(���c����*�J\�H��(�����l\M�Dx��#�cW��%���*$N���wy�'W{S�`$\�t��1������U���U�4	��:��`4�����
u����e	�*��:J���y�\�Z�	��Q)�&�q�Y2�<D)Dy�6��89�:�.������PV���|��L����VnS��E��6a��1����_r�Yi�U�a)�����M�w��|��g���#[�1�W*��We��f\]7Xk�_t�V>H��5�(�]��`��2��<gW�!Fu�"[
[�3*6�\�*��U)ui�V�VQu��<�;#x�r�w����SV�q�#�
P�5��2����'��J/��Co�yk�d�r�D�����d��o)��R|_&o~��x2�
B����P�^Y���f�P�yep6+������P�[1`����Ct:Ig��HT���C���n������D���e���1o��P�K���'Dd�W���������o�J#h�|�~;v����"�	����6|�}	������7|0�p�R[|nKaqaB�B�7\�� ��!����i��[�_*�l������Ce7����p��������r��o\$�UB��*�U���������+�
^5�3����`�A����q[%�TK4�ze]4�M������!TNZ|EAA�E�x:�U;@w"�E]��qF��
��[���I�P9q{0�M��$� �V��`�
�0($/����I������#M���C����~�@e,Y"e�G�
�A�e�	V�K�nJS�����?Q.�!x1IY=1�2c�xLw��#���!�4�"��^�[�u�Q��s��2����\G�P��7@
�K7����%�n�(��o�I�}t��V�~4�8�X�	KDyl�H����ht6��s�4*��%�q��>�/���jU��)&W4�[^��c}4��
B��`d����]��{G�	�m��$�:O�O�Y�IQ_?W��Mg����wa~y�*�1����#��\~�xwzt~����~������LE��A����2^,�`k�j%�ai�
EE�Z����Z���Zn������e��[v��.��)�1��d���w�^�h��IB
�U������0��Q�M��XdO�\bn]��R~���d����J��\2�����r($�D��t������AugH?c���+��oe���
��KP�Q����<�����|�0>����,$��F���J�� �7|t'�gX�����k��e%=����{k�n�F;�`mT��������^���o�L�^����)z�mr4��G�IMR���I�.��]\)=>�_G��6���W�hB��v}��b-�I��&��cG��1��Q��p!����������,B���
�������j�	�
�8�Oq��o���c-������/v��)i�����[�/��tw�T	�P@��T��%���O��w?���4�h��n����4��_���J�QI?a�e�E�I�:��.F�	��j����$qGr���!*S�>]�J�����~�Qj����{  z
�,�Np�������7"��2SiXUd��@�]?�u�u�w���M���V�	K��;������QoC@.�k)�>o�(��<V�8��2��:��	�W��N�;����S��0:�ds;���zh ��"�a���	qV< ����'!B�R���A���Se�B���^,�^��M%��+���V���CMz3������T����X���D���-���.�)�1��'�j�5��v����B��3�J��y�H[M��%��h]i�
5�OlX}������G=�8�����35����4���T�vc��<�������7o��
�U��>�KN@}C-gS�����W/?���5�F5�w/�jSE����0�q���=$���B>`�S]��_8�.b�V�����������\���m&�(��y���v�a4J��(��S�=���%��a��Ur&���D�{
��A�����C.!���r�)^Y7^�9��\�T�������b�n�M�aq��6���3��%A��ge��=dt6m����	k|�I�?�R�d�oP~'�2O:�� z��6Y�]�]�>4�0��fm>>�I��W�I��
�4c1��-���~2�"0~s6C
nY�[j&z5�*hW9���v��`�E������/Io�����`?���P!zq��W�O��9�������Gxe�W���l��A8o���RSr=�B��sZ�k��=�Rm��9���C�&��kP$��ZEp�Q��Z��a:V���
������tM+�)�[��_���[�s�i��fc/X�$��������� E�#]-�6������-�q�����}�+����o/�s[�H���-�/��8�l~�S��`��"����x���yu���L��3��7r{X��Q�7��V�/���qQ��;��j��T"`y��H���j<��c���������V�dN�^�{���S���Z�H�TFi	�	��������������C�(�|�a0(I�X�g�o����4�/����$-���������8[Q�n���hWA�)^y�|����w'�������_�<�����Lz�uV�|��R��3X3q0"��`G_E@��l��W��eCw�2�$,�>����47���M����~b8((h>�x�@��$& �oN����/r�7��a��=�$�"�*�DveQI�Uo��T,��/lQ)z�.E����t
��h_����bG���T.(��Nt��*��J�K7�P
�ZGi0
��a�:��++�x����?��{B}a)+��->4s����_p[�At��������g����"ph���_}���Y����j ~|nZ��<_v��'R��Y%������[p����������a���w�`��+K]fo�&����:"���.��^]c�G�q�� �/���<�4����H��#��U�����mF�6����|(0��`588%l�>������;�]
�c�H"�q8K����c��	�.��E��R���I%�k9'���Ow]��u
Ns��gH�B��	�������{���vx�Ep�������](1�BF���%���ew���vf-����/�	yM9��\����9g��i��>� �e�R_S�4,�O�O"5Ve�a�W8�'n��W>��q��W��s�{/���=��G���<o<'�$�	��z�I��Q/�����������E����-���FW�����E���-��������p�l�I-`�w����W��e-�D���|V��r�k��O��Z�	8�������;"&�w�^��J��g�dyl�Bd���U]Z{�u�\d��p���`�
��� TC�@#��I�#k�S�xA�z����$��AKO9
����N����[�m�.zV2�;���:��l�t����YK�5�mYi�\d�Y`����p���T9Y�������������$�b��-���*��|���tV��Vs��������P�2�h�	�~�.�Z��m�	�����]�����Jb3�������l��P~j�80��[�����5�F6��M�Qrn�:i��8�g��
�%'����d�Qn��+LKc=��	�R~�-C[�c������N]�7�%1�k���ok�k4��^qC�D
&$w������������oF��\����>��T�%�N�:,)8�6�����U_�v+��jK������>~�
>fL��kK����w�BT��]#�i9�j�MK�D{��X������u"�s�[���`,�H���h\�gT�����
7���v�VL�|�u�>�������}�W>�/z�8��U1Y[��� w�@��:�������C��)W?�������?�/��t\��B��%K�v��uP����{��������'��K{����V�7-��%��|��N*n:�+�����y���,	���
_�MY��aT>|�<����|�H�'��I���if�������h��q?��^;���?��u(wd�C�r�wP�%����#U~
<�����������_����n+������N�>��'0�~6�0*a:�
����]���^���T!2�����?���E�q^������H��9�\FP��X�b���/v�tq��}�z;�jr>h�8��&nz '��Q	���4�=�y:��� ���n"�ll�gdXM:>�iF��O��9*
-d���E6��9��%�]�^L��!���������m���J
�TA�h*�X�5Le	�G�K�����_�}]m���
uRW�� 
�nF{�+���i���;w��Z1�o�u����/�dj���P�(�>��N�)<Y�P�s�P�fO��'�'me��l4�&���GO�'��=]/N^�Ir��Afz��m���_+�3@�2�&�lf\-�%����Y�����L�$�{m������u��?�p��������+����|�S�'�/q�:����|�O��U���y���w�_�2�
�zc�������[��T����b��r9s��������JX|��s
�����iz�����v�=������������qxd ���)t�j�bE�bB�����z}%yV[�h�x%B|�_M���Wn���
��d]Y�|� w����%v�@o��� ���|=�V�*�[���zj(z�'!e%_�Z8�H�IM���_D�W$�OM�$y"i(7*RJ�L4�#�������L�ie�"$����2m���'�U���E����@���"�"�J%�"����Z=|/Z�*���������_�U�[�����S��p�>�B�U�������������:���I�X1���?,�u�Z���;�/_�i�4c�'+�D���g�|3��� ���LgQ���z�����r4��\�i���E��5��=�|T����`oo-E���Nr���V��������677��������M��!����f��n�@���rNcH���8��F��n�9��Me��qD�����q��F�8������,��TX*oC-�t��i:���Tp�'�V�B��(�O&�t�����-H���P������<}�����;�J�;���S'>{y�����g�><����y5����j�P����(�ea���&�H=��f�g��P�+��6��-�b�W)�Z
\�����3�7��_���{���g�+w�Y��&����]@�o��%H@PV���H@������<>:�+���~e�5��1������G�V ���	Egg���yD�p�����t8�*����]b���|l^L���7�����,�]N�����E|��m���A���"�E{Y�CuY4�l��'����hr��Wa��@C�p&�l������_����G�* �o�u6��iK	��Q��J�����;�2	�6�8���o��<�-�oam{��L�>�����d0H�;8g���@��Q�cD��(�F�����XT�"���`��TMoT�5�~����*��Q2K!A�8HH~6�����
��
���S����0ms�@���M#qN7�3�Hti����I��Zl����;���D���b�2���(���&I\#���&��t�
���g�1d43�����'���L��������S��^�"]��!�%(<�n}�Y��=L���*U����9��5���"��p�t>���W���!�n@�}�=��5�����:K)�b>��/{.@����t�o���6�P[=#-n�H{?z<�/Z���8y������$�-i�e6�<�g�U�R�n>1$�K�������f{w�
p������L@���%�^eP����>��I��� ��K����{
{/��)1"����^2E��#�H$�u���"4���9a��������]8�f��y�=������&��w������}�bZ�����IN}�b�)N����{������{#��8�k&�������������!C���k���=��:���Vk�q��Eo�S 1�,<dF ���;���c�����""��@�4~�p�A����m'����`h��������+�PE��fOL�!P��<@e�^���w[e����/o��d����Q��5\�
��4��9=z,��]P9���.�ku��,��,�C�X��a=wpt/80����u�2��1��M���d�4��1�2�
����x�~`���1�hC���?~�6�6�w��Ck�&�/�N:��_c��\��Q������3}���������|��::��}�_��=�����C��{����C(��}}���md6�������Q��������b[e���r��E�������w��V���Q�a_Q�rX�l��/3�t�7ww�d~�l�<��8O/��n�,�'��V��?�#��
��a
CW���|��i���$��HR��T��7�[��xI��=��A>���5�(�8��X���1�,���N���Q��
����!�V�fQ'�������N��
���eA	���f�[�9����������i�
���������F�5����'�:�����L�rAGD����L0I����t������������ ��S3�t��w��x������i<6������������}��%g��[D���w����:>���_����������iS���/�������oN�L{��}�]3ZR6����K������~��k�<�����n�?�Do�~�D������+?��OQR|�ivv,���7�$��S���m��d��-�l�{�P�m?0R��V�a�~�<�K����F��!?0�YF�5\���[;�V�iw ����l?��8.=�6G��
�5
x����3n�L��"�%=]uOA�M�@��~r*�+6�}}�z��T7���Qy��.���,���M
#55Alexander Korotkov
aekorotkov@gmail.com
In reply to: Alexander Korotkov (#54)
1 attachment(s)
Re: WIP: index support for regexp search

On Sun, Jan 27, 2013 at 10:40 PM, Alexander Korotkov
<aekorotkov@gmail.com>wrote:

Now I'm working on additional comments.

Some comments were added for addKey and addArc(s). I hope they clarify
something.

------
With best regards,
Alexander Korotkov.

Attachments:

trgm-regexp-0.12.patch.gzapplication/x-gzip; name=trgm-regexp-0.12.patch.gzDownload
#56Alexander Korotkov
aekorotkov@gmail.com
In reply to: Tom Lane (#52)
Re: WIP: index support for regexp search

On Wed, Jan 23, 2013 at 7:29 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Heikki Linnakangas <hlinnakangas@vmware.com> writes:

On 23.01.2013 09:36, Alexander Korotkov wrote:

On Wed, Jan 23, 2013 at 6:08 AM, Tom Lane<tgl@sss.pgh.pa.us> wrote:

The biggest problem is that I really don't care for the idea of
contrib/pg_trgm being this cozy with the innards of regex_t.

The only option I see now is to provide a method like "export_cnfa"

which

would export corresponding CNFA in fixed format.

Yeah, I think that makes sense. The transformation code in trgm_regexp.c
would probably be more readable too, if it didn't have to deal with the
regex guts representation of the CNFA. Also, once you have intermediate
representation of the original CNFA, you could do some of the
transformation work on that representation, before building the
"tranformed graph" containing trigrams. You could eliminate any
non-alphanumeric characters, joining states connected by arcs with
non-alphanumeric characters, for example.

It's not just the CNFA though; the other big API problem is with mapping
colors back to characters. Right now, that not only knows way too much
about a part of the regex internals we have ambitions to change soon,
but it also requires pg_wchar2mb_with_len() and lowerstr(), neither of
which should be known to the regex library IMO. So I'm not sure how we
divvy that up sanely. To be clear: I'm not going to insist that we have
to have a clean API factorization before we commit this at all. But it
worries me if we don't even know how we could get to that, because we
are going to need it eventually.

Now, we probably don't have enough of time before 9.3 to solve an API
problem :(. It's likely we have to choose either commit to 9.3 without
clean API factorization or postpone it to 9.4.

------
With best regards,
Alexander Korotkov.

#57Stephen Frost
sfrost@snowman.net
In reply to: Alexander Korotkov (#56)
Re: WIP: index support for regexp search

* Alexander Korotkov (aekorotkov@gmail.com) wrote:

Now, we probably don't have enough of time before 9.3 to solve an API
problem :(. It's likely we have to choose either commit to 9.3 without
clean API factorization or postpone it to 9.4.

As much as I'd like this to get in, I don't think there's a question
here- it should be punted to 9.4. These don't look like small issues to
me.

Thanks,

Stephen

#58Alexander Korotkov
aekorotkov@gmail.com
In reply to: Tom Lane (#52)
Re: WIP: index support for regexp search

On Wed, Jan 23, 2013 at 7:29 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Heikki Linnakangas <hlinnakangas@vmware.com> writes:

On 23.01.2013 09:36, Alexander Korotkov wrote:

On Wed, Jan 23, 2013 at 6:08 AM, Tom Lane<tgl@sss.pgh.pa.us> wrote:

The biggest problem is that I really don't care for the idea of
contrib/pg_trgm being this cozy with the innards of regex_t.

The only option I see now is to provide a method like "export_cnfa"

which

would export corresponding CNFA in fixed format.

Yeah, I think that makes sense. The transformation code in trgm_regexp.c
would probably be more readable too, if it didn't have to deal with the
regex guts representation of the CNFA. Also, once you have intermediate
representation of the original CNFA, you could do some of the
transformation work on that representation, before building the
"tranformed graph" containing trigrams. You could eliminate any
non-alphanumeric characters, joining states connected by arcs with
non-alphanumeric characters, for example.

It's not just the CNFA though; the other big API problem is with mapping
colors back to characters. Right now, that not only knows way too much
about a part of the regex internals we have ambitions to change soon,
but it also requires pg_wchar2mb_with_len() and lowerstr(), neither of
which should be known to the regex library IMO. So I'm not sure how we
divvy that up sanely. To be clear: I'm not going to insist that we have
to have a clean API factorization before we commit this at all. But it
worries me if we don't even know how we could get to that, because we
are going to need it eventually.

Now I have following idea about API.
Put code of stage 2 (transform the original CNFA into an automaton-like
graph) into regex engine. It would use API which describes what exactly are
we going to extract from CNFA. This API could look like this.

typedef char *Prefix;
typedef char *ArcLabel;

typedef struct
{
Prefix newPrefix;
ArcLabel label;
} ArcInfo;

typedef struct
{
Prefix (*getInitialPrefix) ();
bool (*prefixContains) (Prefix prefix1, Prefix prefix2);
Prefix * (*getPrefixes) (Prefix prefix, color c, int *n);
ArcInfo * (*getArcs) (Prefix prefix, color c, int *n);
void (*freePrefix) (Prefix prefix);
void (*freeArcLabel) (ArcLabel arcLabel);
} CFNATransformAPI;

getInitialPrefix returns initial prefix value like now this code does:

initkey.prefix.colors[0] = UNKNOWN_COLOR;
initkey.prefix.colors[1] = UNKNOWN_COLOR;

prefixContains are exactly same as function with this name.
getPrefixes and getArcs cycle step work of addKeys an addArcs.
freePrefix and freeArcLabel frees used memory of Prefix and ArcLabel
strutures.

Additionally regex engine should provide correct way to examine colormap.
int getColorCharsCount(colormap *cm, color c);
pg_wchar *getColorChars(colormap *cm, color c);
getColorCharsCount would return -1 if this color should be considered as
unexpandable.

Any thoughts?

------
With best regards,
Alexander Korotkov.

#59Alexander Korotkov
aekorotkov@gmail.com
In reply to: Alexander Korotkov (#58)
1 attachment(s)
Re: WIP: index support for regexp search

On Thu, Mar 14, 2013 at 9:40 PM, Alexander Korotkov <aekorotkov@gmail.com>wrote:

On Wed, Jan 23, 2013 at 7:29 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Heikki Linnakangas <hlinnakangas@vmware.com> writes:

On 23.01.2013 09:36, Alexander Korotkov wrote:

On Wed, Jan 23, 2013 at 6:08 AM, Tom Lane<tgl@sss.pgh.pa.us> wrote:

The biggest problem is that I really don't care for the idea of
contrib/pg_trgm being this cozy with the innards of regex_t.

The only option I see now is to provide a method like "export_cnfa"

which

would export corresponding CNFA in fixed format.

Yeah, I think that makes sense. The transformation code in trgm_regexp.c
would probably be more readable too, if it didn't have to deal with the
regex guts representation of the CNFA. Also, once you have intermediate
representation of the original CNFA, you could do some of the
transformation work on that representation, before building the
"tranformed graph" containing trigrams. You could eliminate any
non-alphanumeric characters, joining states connected by arcs with
non-alphanumeric characters, for example.

It's not just the CNFA though; the other big API problem is with mapping
colors back to characters. Right now, that not only knows way too much
about a part of the regex internals we have ambitions to change soon,
but it also requires pg_wchar2mb_with_len() and lowerstr(), neither of
which should be known to the regex library IMO. So I'm not sure how we
divvy that up sanely. To be clear: I'm not going to insist that we have
to have a clean API factorization before we commit this at all. But it
worries me if we don't even know how we could get to that, because we
are going to need it eventually.

Now I have following idea about API.
Put code of stage 2 (transform the original CNFA into an automaton-like
graph) into regex engine. It would use API which describes what exactly are
we going to extract from CNFA. This API could look like this.

typedef char *Prefix;
typedef char *ArcLabel;

typedef struct
{
Prefix newPrefix;
ArcLabel label;
} ArcInfo;

typedef struct
{
Prefix (*getInitialPrefix) ();
bool (*prefixContains) (Prefix prefix1, Prefix prefix2);
Prefix * (*getPrefixes) (Prefix prefix, color c, int *n);
ArcInfo * (*getArcs) (Prefix prefix, color c, int *n);
void (*freePrefix) (Prefix prefix);
void (*freeArcLabel) (ArcLabel arcLabel);
} CFNATransformAPI;

getInitialPrefix returns initial prefix value like now this code does:

initkey.prefix.colors[0] = UNKNOWN_COLOR;
initkey.prefix.colors[1] = UNKNOWN_COLOR;

prefixContains are exactly same as function with this name.
getPrefixes and getArcs cycle step work of addKeys an addArcs.
freePrefix and freeArcLabel frees used memory of Prefix and ArcLabel
strutures.

Additionally regex engine should provide correct way to examine colormap.
int getColorCharsCount(colormap *cm, color c);
pg_wchar *getColorChars(colormap *cm, color c);
getColorCharsCount would return -1 if this color should be considered as
unexpandable.

Now I have working implemetation of this API. Comments still need rework.
Could you give me any feedback?

------
With best regards,
Alexander Korotkov.

Attachments:

trgm-regexp-0.13.patch.gzapplication/x-gzip; name=trgm-regexp-0.13.patch.gzDownload
��!KQ�]{w�H���|�Nf3�����9������b<���Y������I�I������I1�����uwuUuu=~R3��\�Zm�9D>PL�����f5w����B��KM�d�����	��6UJ��F��y�*�Dz���,��������*�J�,�j�Z�L���QkJ�a����%�]\���G���"�Dty��\���k������n�O+�v��F��4F���&�������l\����F�~�\c#+w���~#�7�MG��!jp����'����~��*f3*&��pu7��,���P��P7]'�d��e*�;jw)��T����b��d��6�k���Mu�Dlm����9��"P+J����c����kH��g��&���e����h8������8�v�l%>r`�s��bn��&���5)��#0���8R�G*��H-��m�e"��^��D@��-�(q�K�NLK�Y��1*��8G09�������S���G�e��'�@���R,������t��/�������m5%�#,	U*.
��Z	t�����fN�_R|'/�?>�����'|�����E�K���� ,��Uu�t+�x:z�wf����t9���vN���>�T�^��������i�`�`y�N���ih�����A�}*�C�b��m�4�Kn'�3�v��������e��*���2-��27��LFr���0�@�XTvhB���,��f�����"?��G��:��B�s����86����� 9��������z��P�u�H��)&��}���F����!K~P���[�1-�"w��[�V��F�5�hKb+������t-���Rd$b�Xqne�|�d/��I ��*�&��)y1�F�P�(� 7W�,_�"�R|A����]�5\'��w5����\^�������^���0|� 7���3�D���|+��?H���8Q �����_0/�������������/��%�\]��a��_�=HC{��9�.�����^fY[X�p`]5�P�i]��u�[=��0'����fr2�a�H�:�pNi	��N�LG������+paxM��x���N��"\'g7��9!�������r9�������n��b���s�R��Yxb�f�h�v�����&s�P��!>������~�����A��N���BT�]03�n���,.��aka�w/I	�z����l8=��Y�L����4]M/OF�7��E�w:�d�)�I�e1B{$D:fb{�������oS3���Y������k����'�#���I�����>��}�vV�4�����UX)�m��,��t���AL��s�~�q�]�O �N���hr6{:�5�H��
Z�'{���fndxGX������C���8�i�c6-��T��Lmh��S��Z��3����dj��]�����a�E@��
�&3��!���P��v)Ih��N������:_�[��rgot-d���r��]J�{���S�N���w�����{����SD^BH�
�L����v���c��xx}�
��ha��_�<�	��X~��/cA0��PlD�_���pR�)��@�Y�[����	dh�8�{8�+sp'28p9�w#��F&	�'�,�(=oC&Q�����A�&i�&s
&��K�����o�6�
5!�AE��E	VsP��'�W�.M� ���a�"������&/t����K���H��0]�)��������lOI~z��mN�r�~�(HQ�e��e�.Vk���J�����(e���� %����9�:W[ZEf5����O���^a�ch�2?p9=��~�-\���sHT�
.��PA��N��Jn�r$���{������5ct,Yq�d��A���]���.����`�ZI$��|�S3U����[�~l6�#��b+��U�����A�)�
3x��N���h�$n��h�Y�I�h�����q�}XWVhCBi�-)�e{�T|�O��G�K�ks�%�s�@�EN{d`���Xm���^���,��Io
|l��y���Q�j���f�����a���������`�j��a���<U"l�����m��h��2���a�"�mp�'7-[pc�����a���6hM�m���=��8l���m�F��M�$�m}�a�m�l���l�_')��V�`�o�#��H�m��q�6t�s���2�M�|����v������8l�w���vM���`��1q�����	�~R`�j�������~��n��$����"��e����=����s���r����s�����
�M��l�Ng'�6 ��z��/���W���7���_�6�A��6}�>�M��@H��M��G���[F����>q�{
���Y~
�v�l.�6=��U���jl�#l��ms���ms�'�m�C�m�#["l���j����K>�[g��������FG=��[��m�^6T�S�D��^��v�3���� 5�5
|T�\����I����!k*��EY�������b���m�;�A�������.eW��M-��B����@�N�H�����o��P5��{YT7q����.(w78����|��fY����7#b=��l�jw�_�7���_,S�,N1�������b�+���5�8��r�Y����R�Z�6������3�	����������H~6��BQ���nG��l������ �Q����3ZGt�2_�|r��3;�)2�]Nb�p�2�y��G st����;�H���a�����r������UO�1�s�[xCV(k����@���^o�8L;}'%G0�����f�O�4C�]`���(����#��Hj�wo��x��,�����jvM��Q��~��`�wP�d�#������ %���Ph1��S����hJ�v��Z}���&A�T��P59tu?q�j!����f���v��yb���S�}���t�q~YX��u���
��D��-v��]��m��Be�n
���K,VT6�%r�NO�����K�^(���-q����.'������EX������E����iI.JD�e[����\�>W$��e���L~��A[�
w���������"�X����������iI���9R����
��wU�M����T�������L����sd���
�Y2�7$�4��]��)�()��|NY���������X����Q��*?��~�\q�f#�4-����7��h6�NK�����!�I����(������?G�o �����J`�e�z���;���Ps��9�>�6�4�d���g���
f)a�e��B�M�����V��������R`�V[���?j����*��OsH�h�D���r�R#�������"���8�.�jS����!U���TN[u�3��
�c��p���\<`�`�����a@��-*��6��`�+�]��@��U�-�K
����2:z6�'�8/dG�ecJ��+|�Xg`��*we�V|[?�sdy�v>��`$f�����I������r�?��{����leDdA,=*�����9_��=Tn>��]����
���E�B4���`_���l���o�C4{�����������q-��k�R���d�b���#T�s6��d �L�1=��
	��H��I�f7\]��+���hq0G4.p��$�n%O�c�Ne�]��W���������\���}w��t���4��5U�8?��,���]!H���1.�c<�Q�����r0�`���?j�F%ou1�>?��fW�\C��Pjv�4��Qh���*%G����c����Q�A���&��W�PX���c��+�3�W��hKC����r::^�����Ui4�^N%�
�t��l���]�$^��t��_0/2F��p<&����ng����X��7
��f,����.���Z���#||��-v~r9��`/'�r���Ac#&O~*���5i�y����AE|����e����	��8��L���+�~�� �5�[0�����B������)��nd]7�FI�B��L*�2"�x���ZI��#����R��j���*��(����R&+/���_=��i\edb��lWw^������x(N��h��zHv#�
���':;���G��������h>D�;�B����k��QV���"��W|�D��5,��+��N��VJ^�/$������2�����t��4�t�"�]�:(l�W���Mq)P�5�~��s�=�G��4�c6�������������vc�P��Y��|�1{BPJ��f"�[�������>�d���*���~��B��2�E�}��n�blB��<q�U��"|+��O���Lqx�q��#��~"psxc���!��]�u��2�eF9���5�����h~Jo�\��8�����E��I�i�-������B��i�+/�nVI�heT4�=n��������%��J�?1H��d��������,��P�+�I���DF�}e�
�\�|PA�?����Z9P��@��F������8z��	����1��?�'������d#<@|��I|4d�X���%:��0B^�_���PPU2
�;�Q����4�������vle�kA��0��Q�-~�E*�x.�����c�<����a���aU�;�����pt�)^�9���I����X��'b�Q�[Vj6z�;��'
�9&����Tp �9T �?`[�`��NeQ���a�������Y��*/������q�\���������{���_�-
�us=��z�����h:_�:�B+>��)���V�^~��f��9>&���=�������>�����n�M�����-�\q��
�Q���_��sy��
����E�&%Y����Ci��T��p@U��t[�d/��NP�od�I�z��"�uI� H��u��G��fC����V/ZR}h$)��$����L~>��%���K6�Z���E�8Kw����q�J�F'��('<]$^�J�D����!J5L+�eN�y�^�����!�\�R/��o����N�=j�������\��c����?�������������}����
�wC�&��n��v;p���/P�^�{��{����v�7��nM���5u��o	z`"�~l�<��=/�����R�Vy^�����
��g���LYu��'fE�n����������>����Qu�1����
�w</�����1�9�~�����D�L�?�rbn����!X?6�^��h�%�a;+�^������B��)�@us��=�Lw����P���%��n�=s����Y���ehr�3�'��7�'�f�
$[	��3<}��1�DS�����;�cB����#W�sr�W-��a����q�,�\i
��z��N��8����4L +[|Q�2]���kR������*xP��� �.��:����iy��W��S~4�p����o�ak�KN0`v��lLXD	�1(�W�u��Dn��`���	vBAp"(&O�f��D�L�\3dq����ny���3`16;a���!8'��zl�e}d��5.�
����X5�{P�S���{[c�+Dv���e��LFnL�E��>:�0�R���t�����v�H��!b�Bn�*�aAk]#e���T*>�}�-�m1Z�,�D�C>R~kbC�;���2��?W�"NF#N�a���d�~�{�\X?�[B�x�v�����������_�p;B������^F3�#�0�=�l<Z��$�o�����5�"L��'���o�o��%���#����iA<C��)<�m���}�rG��o�)��	�@����6h���#KZ����`4���h�2g�����{�{��������}�]~VeUw� e�x��36��UY_Y�Y�Uv��[��S�> ���m�)�qo�y�c��H�\����	�:_$*���Z�Q�C��k�����fh�h��P�3�E��9|[��9PJG���������N5��ht�E6���������X;���P\U�:��W�\nU>J���c�	�K�)�aP�����H�W"��NX��#����q���}y��^�n��/%4XWL$�k42����=�;
�&��_���:��]y�h���'�!����g��
�Y�������f�����Y����*�#��qc]kr3�d�D��b~6��)����'R��!5F�$�y;O�	�s����@o0�H��X�J���6��������]�L�nUD�C9�����H����I����HJ����/��C����3/��"�������c=������Y���.�`lH��c�"2�Q
���wS�0�A?/�V�J,�����*S�:n�{�����6f��}��Q&�����_[2S�z��UP���l�(�
(�dIBv����Z����Nx�Z�=�����A�P&6�9F
W����3�Rt�}>X���N	s�4�L9��9����(.<j����
��lI�u���1+��i,��������P�-��������Q�FO�������l���Z���2���A�0�M��
dj���=&�!�=e�@~{���K��.]ds�#�F�G�4�����1y�N�d��y�R�}�!�D��z;�:����hH���0bX���8�%��[�5�Nl8��z�WN����e,�e��s1�Ya�u��tl����!���{�h�tv{6pK�D>�PWF��t>nK9��@��z�4��2�|v��4N��w<W/�e�tD�O#$�(]���e03�n}�-4��m$$�a�kS��7�C|�����=�~�l�Z�[�pj���\���w1YHeu�T�M�rW����9B����Z�x�����A	�0-�"��>�:�����\����O��C�j��������c����d�Q�4l
+����b�TGc�����@t*�B4�
��<��D��<����2LkD������G�����Ew@kk�5������B����\�}I���1�Q��H��3!�W�ti�r�
;|l�i���(����>��x1�C��b|��2H����@��>�|����>�/Lgh���	�bW
>������^G�%�~�]8�$�1���i�K9��S�HD1�v2i'Y!�u��X��=��,E<���w��{���6v���B@&T��-�n����x�1x�{�2r>�����N�%k���#���Pk:R��n��`2�9�B�a�������GeB�PTN�n2H���g7�A78��aY<y��!�d�8%%@��
���PQ_a$�����I��W4j����c�Q��a��g����L��j�,��t����l�S�����(O��-
Y�%��n�l��0�k��7@�Q��k���22����}�'�	fj0_�%����Ig��M�X8-p���u�F�z�j���vr���F�?����
���h���L�G���e��������?�o��$E����<']"�	� %���7�����o�������jIa �Q�7��#�p����M�����#�m3D��E>����vr��R�����9a���H��bB�*y	H���2M�4�;_FD ,��h��
wD��b�1Z�����X�b�F#=Q����M6O���d������EK�-�w�E@�;E�OpN'�~�=�q��P/*�pIxa���a�������J�O���[;3�x�3�.�>�o�'�z[��V��@�
�{��q_6=��$��C�����Y��@!��:�9(�v;`w�W]���i����}��J�B|�����H�v��Y�a]�F��^=�	��W��v}G��w�����n\G���q������ }Q���"IH�V����M����@@3b-N�t>A�S�}��������C��4�M8J6�gL���k�6+�tg��I��6�<�4� F��S�Mt0���~>�T�F*�3L�HD9	������-�i��o+����������������x�Tq����
tWfx~6����E?�l_�@V��H��O�	�0�:�d�#q��l���D�n���=9|vx���8���-��3�K_K$���I��f��p��q�s>.��'�Gj��8��[.������Wc���I�����!R|�8IZ���5X�@Ogg"���8��s=��x�6AQ�j�u���OIg0�����t�In��E{D�"��t�}y���^�<>���:.w�{bX�E���?f�3�9� i�h��)m���������B��Fns�4���f����7��.�C��������WO�O������M<>���(C#�|�"B)W���r?�D"�U�e��PHw=D�����*���������n4�[�����M���sW�8�}>����h��Z�X��"nd��7�	���_�8�#F<>��Fl6h%�]������={��3-�K�Z�����"a��qL�@�D��q�Q3��.���59Nn����s&r�($;�)�������g;�>~����/��=���dcCGd
���?�������lqhS��v/9��r�e� �^�`��s�00���(^���q���N�'so�}��b^��������^���U���xJ�\��:�N&`�M����B�2���NHB�0!vNJ^*���-
�u�����z�U~i`�1�H�����+ �9�'�� ��������t���d+Zv>��b>$�����9/Pcu=��5t�P��)%��X�q�)�hb�B�_�CX���}�D�-�8!�R]��a�a<���0BN��6
f9���V�>��U>@bm��
���2�"T@�>S���Ai�CA������;}C�e���%SD�i��b�~��f}�����.Wn+?��3��m�����x��`�$|4*����CH���&K$-9'-��,��3�a>�s��-����3�q���d8J��R�'n\�A����5)R�`����
I�P�d*���qO4�}	+��
=s��v:�o�/��/����r!�c"����Z�%�����=r=������J�FAQ�6����9vLF���e�<�����U���.Y�R%j��2I��H�7�Q=�
Cq ����=Z����Xn��Q����%M�oLr����
!�A�R�7W�b���L?�(�,��C�K
�B	+p��]��i0�
�;��2
��[��Bg�������y"F����d�����2�#B#�����/"�P\��n�Q5}�Lz��NW��w�T��sT
��h`e���U)s8:��)]��?��$����~�T3,��c��nC�& �A�����2�c'�;>S|o����� ������[�}���R"��u��a�F�:�!��;|aGq�����]&!�l:�C@%��J���]V?�l 1�<�B�(���~e��!H�!��RN�Y��=�5�E�
��-��6Y,��9�
:��b�7���Y��UBhu��&T59�1�d��n��c>p;T���v+MrA�K@L��:��O�'N	��*7�3Z(�nh�(^gY~�0L�����Zl��	��
�U�4�JZh|��-���Tia��5�7����xIg6o;�%;��`+:H���"on����������7p�i���EN?jR��
�H�D�y!9+��M�k�����T�-a�/_�S��7V&b��D�7��s���Z�S���}"'4�"���H�w�5��>�e!��6�O�1�;�Z�Hk27����
�.��	1�K�����5�o�k�5T4�z'�>����nE��S�����8��JYL*3�����5
�/'�,����W���Cy}MM�;����-j���)*U��uV���������M�f������q��Q�1�������7X8�U��I���t��������>���&�	�)xK�n�#b�l�u%�L`>��7	&�CVR���x1����@�kW���rz!�"n����k�l���i�V|c����d�b�Z�%0�c���7������t�q>l��,.�J)�����M�j����n7(���/��#�,�A9�69�����{�����a�@``���w2��R$�*M�����I}J;�V�};����T��|�,�]�b�X	U<��jR���bx�]�)���h:6F�)�����jn_|��k�m+�i��\I�n@^���Aj�O)�Fo���*:E# �M��������E��VgA_�.sP�{��c���Tf�z3I�<�eY�
5�������r �-����Y��#�z��=]�~�F��e�������Zc��R_$�i'^|T�2�������%�.��%���0�:��&��_p����I�t-2� ���6�aK-�+��;�K����{��"���(Ci��"&g�P�r�>-����(���{<B��3d����0=��f��h�����;���A���3�o.�i��,(����r��a�Ns�����v7f]�����n>��a�2�p��Q�[�e�����lY��\L�\	����p�C���8����w*�%���O{�UEc�43���C��\P@I\�|�Z��yY%�0yyp"��'��O� �eM��@\N��~������Gz<D�(�o4q����Ai�_L��p��C�|4�N�
��br��������#��0r�����'p���T�$����Nn�m9n��������j��%�������L���X;�q?���������`G��<�Z�gI.�3�c�&���F�V��fB�-��v��m��U8O��&����s��Yr���.8=@��T�����6����yUC�5�
Kk��T���[����J�r$HN��k��b���z�%���L�p��pr����
R���=���\d���a-������[����
����x�����e�:�yp6d�,-���g�P�I��|Tql'[�2�Y����mi��Jtl�D�!h{�D�5����e�#�f�U���3�m��������%��S�����������&+*���u��e���0����;h�����M7.y�q��R�~�fI��'t�8:V����Z����N�����]>U����2"k&�&�-`��WvE5�p=pn������8�:x|!{��0)^o�q%8>j��.��d�Z��C�p�X�2��e�
J�7���f�����Z�I
���@_I�*0��1sHe��N&S�y��D�"F��EQE�H;J����
Ld:i��aZB��B?�����(�FP~/�Z;!�oq�~	zA����xc`e*a���v���;�
���JaPY�����Xe�2�m�q���	��-\��j����\h�/���'�0�%��G�S���x�z-�c��U"�.�/w��0�}I�����>�<+��r�c:��dK/���M���Q���E����J��iU�Xd�2�J��t��S�l�A
Y(���e�������������{X�Jj�sv����[�������H�=�����
A��N@�j:�=�z$�`��}(��6�����u6F7��t�����*v�|/�0�����9��3�'
�=���)WR������M_�:�|EZ��|��`��"������ER�P���%��5;�w"�-����Wry����73^��W�8
�vw�K���j���gZ�A����$��m~bX���E����zF�"L��[���r�B�fAPM�K����~o(:��-#�
���@m����:�/A^��*��(u�sR��(S|F�����DI��p�����q\�,�vx&�����:Hb����$E�y*����
z��`�I.������T�*�B�Z��3�(�pB�*������@�,��A�|d��z��`��|���i����pM���,o�/>�6�0�h1���F��%����T
LWD�
�K���
!�@(`��H����iCl�������R��>S[��UJ
':J��Ii��w��~]?(o�w�U�b"h-��i������>\SJs*-�t��E�4J��F���$�����B�ClH��qW�t�s��Y����[��$�����p�r��������R=�*��j�3��t���;\k������\�Lt���Y����u�;n2F��.=S�,��b>a���T���6Gd�R����[�/D�u}�s�u�+���.�+�9AS���0��1\o�[��-��dQh���������5�$���q�.����OT@�6�p�l�z�}�4K�R'J�6�������VO���y+T:������OE0�=��8�����-%�tu����������
�D���^v/�@N{D��_��Fr
D,�a���������Tm�R�q��X�mg�:�oNW�;//>�r������J��@Gx�7\�W%�
��fM��
L��c0��K�y@E�J>���83�
��.#+��?2��K�^0�
$��O�����[�`��uE�5E?�Nr�������o������HVY�Hh��E[�WEo)�:2P�������I��{$�D^�&���Q���e�e����j�/����f:}��9
��N�����X^����������y�"�����$�����
^$Z���EK$��~5�)�@���F��XZ��s�
�# ����G���
�j������p��p��p���d��m����������h��a��o?�������`np���+�s�
"�8y�H�G��_��}w�M'�X
��#���6����������X���0�_����@�������.����
��'���4~-�]1��2���hx0x�V ��/�]�^��o�S��hz������N,���H���X�9]���!t-\�GV������Q�]e��������!6��O��E����/jV�����i�����m#�;�Wf�����o	��}�<���J�k'K>w����r%�
����������os>�L	bQ����]6����.�������������V�t�@2<�����}[��(G��V"4��boY��
�!Q���n>B�1�y����rl@Y6��y��N��e(��1�k�����lq�������&�O:r���{�;8�q;N����X]c���o7��+�Nf���R����{u~-�P�%�iO=�n������������X���
����n)y�; ��H���+�!Mn��~�c��x<E�1������v��]�^�o�)=��a��`M�M��_�u�r���c�i~z��;�xRR�H������1�;��P���
r� u�3w���q��4�L�W�}o���f�|�C��|=BS<{�*�����CL���F
i�>+���i_��-��x�|�A����=)���W���p��8K���^�7����� ��5q<�D�k&<��.���?�����	�H��9�c4������8��V�G�q�����7|�������'S�"��O�..��Mx���y��y���N�N��M��%7Y�5�O�_M
�1��"����L�_,�������_�K�N>�zHG[�����?��4*�h�IpE�Q����.6j�d�J?^vkX5��N��{G_�����:"���(</�	M��H=����o��{���,x���� Wx�B��d��0U���
	��CB��
)w�R�]YR��^�
\�A�w�v������fJ���c��}�e:� r|c��B���J���� �U���}8n����6|���~��"E�
?:����
��H����Z���F�"L�H }Pp�/���2o�iG�����O%�0�5���#�}�i��*iV��)�e�Y}���M���,���n�r����,�1�98�*`{�J��Q��s��]!{�%]���$L2�(�����#J���@=�y�0����CM���o��g��v�0�^]��fpK5��^��_���J���3`�s8=N��p��@�8�[N{N��*vkC�OKB�
�*"
�kT��IBH�n���:�W���+�
� C��20a��k��c�+���0��O$ua�����t��
9E*�Dlc��&��D+�g�.�1�K���:�L�iq�IM���i{�WQ}K�����v~�a<|�����S�}���Cxb|��x-n��f��`S_I����U2#e�P��u��z�T+E�aB��D
�3O�P�L:EM�jj����e^�e2��j���,�.Wn����[g�P!��:�aI�R������h�]zM�@����j��(n����K/���*�%o.�	��hF��(Z%����
}hh�t,�eyw�PG���	��M�^��[��z����<�x^#m�}_�V��*�0w�W�)>0FbUK	s���/��%���D������K�3����3��Tq$�Y<�Sm��(Z�����C�E�H��E�>&��U�q�vbC��
#�%�����$bf^����$^�S�
W{�(%��O�i�����o��{�����Mc�a����������(��bD�����-�(�@2J����/i	�;�I��_���~}iN}J��rL�+�g�7P�C�8�K�c���j4U$I�����~�����\"�U�D���7NL�%XSct2���P�p�����6�������Hi�>������ 7��(h�E�3�IL�k��U���;��N��,B�h���� ��s��s����/���ArKO8��D������~�������/w�G����~��c�v���t��cz�b��v4N ~qp��G�/��zTI���8�6�� �r���X��?{����&�_�A=������B,m2�������z�O5q����C����hz^���L�9QKp����/#����fob���.]A�.�^_o�)y`��hn��).�:w�N�'�{�[	��L�*r�gTT�u�s�T~[�o�^%�moiT�
�������]
g��GsNT��W�|(�~��0��v]%}J��yS��fU������S3/���c������� �e^g�����b>����5�E��?a)H'&���2��(�Jizy#��?KL_�JQE�#�T�a1�]�]+���"�]+�0Q���#� �Y���R��R�R�jA3H�!�24o�S��U-������s����-���Y��)�fYc�����V�����p�K7����6y�����;��N�u���d���lt~��S�c-��6@D�Jss$_�fAW^��M�wa>���<9q�A#y��Mp����D|Rf�8��+�- g�.�=�y��*�:d���t�e$���q�@�U��J������*:U��RVp���\l�K�����������9%�6��n�_���R������K��������^��3`u<�4F�����TK5v�1���\��N��� ���o:�	>L*��V�2V5[S/pZ.�/�J���h��lm�U��e
'�hom�qD|�6��5Hl�tL)����H�������\�k��j9�XQ�8��U]q�Sd���]��1�
8����o����N{-�"�d��������g?(�3��M�C����>%�|��%Wr����F[��@�>6]z|�R�fc)������m�Uil?�b$��t
��oId��
��J0a��t�t�4l���II}�L����^I���T��~B$I��o����3������P�
�m���[uh!%b:��|��)�1���n�9E?Ct����"��
=��5��j]����%���s4�4t��yK��:���+�B!;{��!���"����V���+��I����"W�`u�����z-�j��)��&���(�y�W��Q����}8��6
��k��A�
|e�����[�����d�k���g���3r_��mk+���]��s(s�p>>�c�Dn��YT�����?��@k�����5��.�=]cc?�U
.N�s�_�b��al��9+$
��������?~�-@�
����@�������	@���`TC�-���Qu�+0�.��R��)��<�J��up����t�CL�p��g�Q�f]��U��3����}�'R�?=8:
C�����`��G�����~����7�o�!��xL0p�����s�,*ymm��� ���K ��*������=���R��$@�N������Y:�;�|�n�N��)�@��1��9��|�p�����0�rT�Z�Rs�����MRb|�]��n?"��o�%����a.��yj!�W�/���:���r+%+��%�Z�����-���>�A�n';��Q��Ai��7[7���fL��+�#?�K��!����<z�:}0x���-��`M6����6'�����6��z���bE{r�����C��'�bs=*�W��7gH\e�Nu��_6�,������{8=�����YY]}T���#_�Y�nK���t!'d����)~<#4�������������:*j_��$�s�s{�������zm�^�\L��r�&ys�*���[��Z���������������v��`��~>���+1�����,�|���A5]Uu�Un3�"�>v�s�2;��\�o���3���������������C�����y#�GW�\�i9�g���y�,;�7+�C_��g�ro�;L67��y��L����{v>�==#'����~Zg�1�}��
t�������d8����l�����w�[w�������V�����8�9B���iw�l'�m.	L�,�`T��An��Cr1Y��}_.9���������x�8'�	�&��N\���y�������Q:��	������d�/�.��d6���ShoS�(X@�w�*g0��SLv�p>!8�P��i/H��`���������<����������}��f9��i��� -'�w�t��O\X��+aXf����<�
�����|sX��4�tZ4;�g�#�����H���������r�*��K�fP�������7��%H�PV���H����	��O����u</��Z`������/^$�g ���!���v��u�	�Tok�����8U��-�M����(��|��g����8��v����rp�~YY�l-�V�Y})t�w
B�ZmI~�JH��"�;��9���fs8��x��Zt��Y)Ih���*��>��"��d��������F��:�x��^�Hm��F33��l�<������a�UWm�D6f�o����a#0�Wc:�	��N�ucXRE��#�<��Q6�o���[h��6�����kpg�g�C�����8s�7{���(rnT�
�6l54)�L���%`���$���Y����i���P���|.���b4�)B`���
�C$^���0��AAK�-hi�M5�qLT�"��Rh$��mw���m(h���a������E~tL����3���V�~�3������Hg`%��t��}r���&�p�����J'��Y�a�{t�b�q����H��.r�����5�B�X�����<��P�9Ep<�M���_��2��N�|\&���Iw�[�N'le;�U[���%b:\,N9�KuXD����U@�O�'��|4���m�����h��OM[�E��;g��i:B�I����=�n���d��d&?���E`����:��a���kO��a?���
$��X�e�:���i__s`������D[`*v:�{������Z$@�!bP��P���|�}�SY04����O�m���rr��>F��F�4��?�������O�)�+�I�������>;<�#�^�����s2���	���K�H��Y�
/���.�J�}1�G0 �Cn�����l����{q�l�3LQ�7�M���
�K����f.(g�&�\������q202�����5wYU�+�IK��P����0��2�3�QY��c�!g��w�`{�Hr��M|�m�f5i��.�CA���6��q}@5S}"�0{h��)��4����������l�&�������Sy�.y��.Yo��vsk�(`km�$�����`���s�-�����(���|��� �E���E�/>*�:[����_��k���z����V�R��\K��[�'kc3J�Q������o��4mH2��>���L�*9��n�tb��s�b�����\��D#�Y&�o�2Fx�/�����)������6:XW�g{���kI���X:��G�ZRz�����w�;b�z�����4���e�KbbPmv3(J���Y�
�.���[�^	��\�^��*-�Z�������'��������c�I% �����O�.@�������_�;���V���?���Z�R�x���ar	��G��0��6�Y&��:��Q2C���~�q���5�~�~���e\��S���+�����`"��@2����9g������/�tK�Vn�����a�J���v��=~:�&��(�	����g
�g���(K�db^f���������7T�k�m���A�5��z�<W�C�A����%t�T��@J6C�4I(��h�RkFc����]4�v�6�d/fHz��N!��K��"�`T>���E!��
b�8����#2Qc����>�����vb�%�����. 	�!-�!R�*���}��	5BM7��ql� ���&2�z���qk;�$ziv��1fe) [�W`h�/(j�F�?�����ie4���z��c��:�H7�"�Hq��V�v@X�w�z�s�[��b�M�c���a�Wm>�O���9��s�����\�{�
�.��U��)���D;m0@l�����v���6�����~+��Y��n���Vk?L��^i�K�HA� ��k�:=B�5Y����)��[�cvZ�;*��7"�m�u?��_�Fx+J������I�nO���GC�v���tm�I�A�`,��*��K��W�aR6��;-i7��|C���	��%�m�1U��|���<��w��
C��v|���A
F�Z�H$����7nF�J��E����b]P�.B��x�=��ZTs����%�+�<�9d�-��S�$v7�'90���]K�>0����e�sl��I�gP1���M�;������T-
����;����������A
��7�����]F���t;��m��#��Q ��_�����P2^W���c*��l7c_A��om>b��[v�����O'�$�����JB�m��M��������<=Y��d1=F�Q$���k���a�
U1t��b����X�����C*Ld)���������������@�#8�\���A�3&C�txJ���dP��q�2�Es��R��/��p�$���C;�ooC���j1M�q0I��_m��`�H;��0Pw16�I�e*����KY���pdV����l4V8���������P�D@0g�-� ��R�[,�hO.A^�U`�.��UhU4����i�\*a0N�g��m��Y��y�Y0�m@�gEV�F������X��X!�F"i���Zi�$'��|���~`�|�{�P����t&���
�������~�KN���o>J�9���E����b��C����v�9��"�LIw��7���Y|�h�i�>���G���;q
�����+
#�q��V������������6�=�1����� �v�����A�~n��&�����b�N�q���yv�bq%�@<�����g�������r����{h�3�%����SJV<p�#����.D�h�|�Z��Eo���
�hV9i<�L�0�����-��,	��F���{��Dhl�����\�����`�������8ix�`V8�m��;�a����3 ���������3��&��Fn�H�5�W��1ss��B�_�W���O���`>w����<twp;�v_F�#�k4hgQ2X]W��0��v��Rol��0y)�{�PB�$I^� ^����#�NU$����<�e���d������+0r
��9�X�EQ��9����6�\�^��d�\$��n����@0�C�;DUY�Az��Q�C�Y|X����r�a��X���^�.Qz�����D�*�����@I�_7n0�]�+����������V��K��Xz��0���(��Si�\�)���t}�lgY����c����>/�hWZ2��8�n��7\���(��f������� �A$��.���
f���r\����q��G11�"����>	8�A�R�;������S`q��\�Q����Bq�p���?��$b�#fQL�9�v}�~�%8vz�����+������6L�y��ev��"-���V���z��@��|U�Rn��
3��D��
m�K��o��B���L#f[����d��$|-
��{&iWehX�3�x��
��
��
oA:G�������";`�Vr=�����i�a��M��,�d��4f������GJOy����%,5��
V~�[��3 ��3��Dg�`���R���3w`�_�m����@�/��V���KL�K������w,�����e����1<OH��V�bJz��(p�V�;+��%R�N�hkj��N&��)������#���/���V��|�r5����p_k����|��3�a��
�����M��g<I�k� B���/�D�9�Br�;m�h6���:�
(��)�VWP.��^$H�L��;�lQ�e����rI�������Fw?���0u��8Y��������#�1Mm�3���XdL�C���x_�����aV��@^b�&�X8f5��q����$�c�~�h)^6��|-�H�|Z7�Q�kx���G�]e��u�o�^�������y��O/[����wC�h��M�h]#�hw.YH2yh��P3���0��P��6`5���0L�@��I� ��F��=�Mp�4!��z)�0W&��f�jx��Z�{,��T"��PN��<�p������M�[��kZ��+�����U���.�_���H��uwdR1@��W��s&>�d��eN2��	R�4�����������j�yO�4�^z��Oda�M�z�O��h��S���Se�9U�,��x��cS_�-o�_��+%��*��L��?�,����Yp�d*$�[��[^�6��Y��i��l2��o�)�+L`��`�����`������oBp�c��K����<c�+��k.9�a�1B��a�P��,�oY��1� �k��s�y9YM�%��r��-��^~=��(��h��<�Q�v�1�AwtJ
��=�
����2(�m�Ml4I;	� �*D�+txd��y������qO�����<7������l��[��?m���G�p�x*D�8p$�}�e�TIP$���=��)�����e�f*��exw<L|�O�^��9f�;L�y_���b�.��qE�,�F�B�uN'����b�����)�Th����`�gU�Ro��1��$�
�a����;mq�����IT�C"�$8q������"�- ~X�s��Vo�=������zz�U�#k���?;>���>>y�l����3���{/��y���(3c9H�6d7y[C��y�a�\�[D�*�.���mf��Z�����
j8��SsU/
���D�*�K�%h<����=r5��Ut:��)�����b�v�D4�U����jm�wFSTu?GI6��}��8kUzA{yi���2mQ���;��T6��q����27A5�����	�>N8�$iorT@~�;�����k��H����kA�/�Q".��+X���Y���|��1��Gn�����xq~��,���j�a����a?li���p������t=�bv%�:���)8vv��OK)���@����t��v:Y�����NE"�
��D�JY9X�@�/&'\������	��7g���~���������M�h��"�xPxFG���t��$x�)E�L7����4��0�����wv����ct����lF�1�����7�J�x����	�����	����>I���>�Qa�������_�	����/�F$gc��?��zW8e������g<9����_6�;���9�R��9��O�
���Fh�.�l/_di��^�����t�>�?�/�`��-f����,��3��o�m8��s���4?�-��w���m��w�������b�M_����BD�@�t��f��!W���xd�D���[�]�T t�;�8�Lw=�N�
���,?{K/v?v���aL�?Uj��d"�lt�I��T��3�xpJ��S*��qa���q��U���dR�������5o��c�|4t��"fb�/��������\���*���%����tCV�O���wx�{������ h��*^���V+��&qqy�]�ARE\�����WO�����{(��<?|���c*���]��[�-�,7���<��+�-���t�i�s���O�������F����D�;�m�����R�1�Y��+�]��������s��@���tV�8f
t7�������@������o(�Pv����S���>���Ea2q����}a@��|t�K�~����9�����|8OzI�o��z[]�%��K��$����]��Bs����'0����g']��W_=�N�����fs���M����zi�.�oEG�o�D� ��#�F^=;��������xAy�����W���x'��0G5p�W�zw��_������IG�Rm���
oc���5|��
?y��
c�;�5���f{;�i������/��<4y�n7���'�0q�e���������
�p�����QB/7��~�K^�R(�]_u�������UIR����m9�7�J��W���XY�FM.�
�-=�v��~���mwv�Sn5�2
�W���{m��Gs�m�)���1h2������\o1�1���2_�h�0k��8,�d�!R�_i8f^ -��Dq`Y.s��� �V���������������9)��������`�4*�P�|2�b�M�+S��<�������$c'�5��!A��;g���	�����1;��dU��D��X%.�W�i�u'���rVPK�XU�r���~W�U��w��|"��7��)�?�^�Y0i�[Iokk{���v�s]'_P���1���L�1@���0`.�W��#��R�M��c�_O�4n�z�&��K����w�
�-}�1���Y��F"�_B��n�d�8��S$���P�
��A�xV��47bH�X=�9���t-cs#�R�
�����v�.���p8n_c� ���bc���Zbpd��&(�x�
��n:<��������~�{�Sv.�!N��
��b�8�������zH��[Lm7�
��'�����|(e�]���Im�9?4�A��=���m��At�&�u����y�3lX-�����Y�!�8���c-�V�D���Rt�����<�����-&�l�~�����@�q!�I4.�I�U/I�[%s
��s������Z-w�)~y&W���j��]K]Zd��^�o���G�����o?��_��O��������?��O���L~�����/������	��s�������������ZA��$�u�]&Xe�lg�����s��w��R�J�m��VR�J��{c����W$�d2F����Q*J����=�'x�I�}:����`:��g��D
>>3i�0�&�Q����,�t ��R�1��8w�s)�\�Cv F��lr>A���k����Sk47�-�����B���
��-A����	{�
#60Tom Lane
tgl@sss.pgh.pa.us
In reply to: Alexander Korotkov (#59)
Re: WIP: index support for regexp search

Alexander Korotkov <aekorotkov@gmail.com> writes:

Now I have working implemetation of this API. Comments still need rework.
Could you give me any feedback?

I looked at this a little bit, but it's not very far along at all
towards resolving my API worries. The basic point that I'm concerned
about is that we would like to split off the regex library (ie,
backend/regex/) as a standalone project someday. There are already
some problems to be resolved to make that possible, and I don't want
this patch to introduce new ones. From that standpoint, the proposed
regextract.c file is a disaster, because it depends on a boatload of
Postgres-specific stuff (at least StringInfo, List, HTAB, and pg_wchar;
to say nothing of palloc). We can't consider that to be on the regex
side of the fence.

Similarly, pushing PG-specific declarations like RE_compile_and_cache()
into regex/regex.h is completely not the right thing for preserving a
clear library boundary (even positing that we want to expose that
function outside adt/regexp.c, which I'd rather we didn't).

Given that you've already got a notion of callbacks provided by
contrib/pg_trgm, perhaps this can be fixed by pushing more of the work
into those callbacks, so that the heavy-duty data structures like the
hash table live over there and the API exposed by backend/regex/ is at
a much simpler level than what you have here. But right now I don't
see any usable library API here.

Perhaps we could avoid these issues by defining a library API that
provides accessors like these for the opaque regex_t struct:

* get the number of states in the CNFA

* get the numbers of the initial and final states

* get the number of out-arcs for the N'th state

* get the out-arcs for the N'th state into a caller-provided array
(sized using the previous function), where each out-arc is represented
by a color and an end-state

* get the number of character codes represented by color C

* get the wchar codes for color C into a caller-provided array

(The reason for letting the caller allocate the result arrays is so we
can use palloc for that; if we allocate it in backend/regex/ we must
use malloc, which will greatly increase the risk of leakages. Also,
as far as the color API goes, the above lets the caller decide how
many characters is "too many" to bother with.)

regards, tom lane

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#61Alexander Korotkov
aekorotkov@gmail.com
In reply to: Tom Lane (#60)
Re: WIP: index support for regexp search

On Mon, Mar 25, 2013 at 1:50 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Alexander Korotkov <aekorotkov@gmail.com> writes:

Now I have working implemetation of this API. Comments still need rework.
Could you give me any feedback?

I looked at this a little bit, but it's not very far along at all
towards resolving my API worries. The basic point that I'm concerned
about is that we would like to split off the regex library (ie,
backend/regex/) as a standalone project someday. There are already
some problems to be resolved to make that possible, and I don't want
this patch to introduce new ones. From that standpoint, the proposed
regextract.c file is a disaster, because it depends on a boatload of
Postgres-specific stuff (at least StringInfo, List, HTAB, and pg_wchar;
to say nothing of palloc). We can't consider that to be on the regex
side of the fence.

Now I can see your position about API much more clearly. Previously I
thought only about algorithmic side of things.

Similarly, pushing PG-specific declarations like RE_compile_and_cache()

into regex/regex.h is completely not the right thing for preserving a
clear library boundary (even positing that we want to expose that
function outside adt/regexp.c, which I'd rather we didn't).

Given that you've already got a notion of callbacks provided by
contrib/pg_trgm, perhaps this can be fixed by pushing more of the work
into those callbacks, so that the heavy-duty data structures like the
hash table live over there and the API exposed by backend/regex/ is at
a much simpler level than what you have here. But right now I don't
see any usable library API here.

Perhaps we could avoid these issues by defining a library API that
provides accessors like these for the opaque regex_t struct:

* get the number of states in the CNFA

* get the numbers of the initial and final states

* get the number of out-arcs for the N'th state

* get the out-arcs for the N'th state into a caller-provided array
(sized using the previous function), where each out-arc is represented
by a color and an end-state

* get the number of character codes represented by color C

* get the wchar codes for color C into a caller-provided array

(The reason for letting the caller allocate the result arrays is so we
can use palloc for that; if we allocate it in backend/regex/ we must
use malloc, which will greatly increase the risk of leakages. Also,
as far as the color API goes, the above lets the caller decide how
many characters is "too many" to bother with.)

I like the this idea. Seems like clear and not over-engineered API. I can
implement it. Could you propose something particular to do with
RE_compile_and_cache in this patch? With this API we still need a way to
get regex_t or equivalent from string.

------
With best regards,
Alexander Korotkov.

#62Tom Lane
tgl@sss.pgh.pa.us
In reply to: Alexander Korotkov (#61)
Re: WIP: index support for regexp search

Alexander Korotkov <aekorotkov@gmail.com> writes:

On Mon, Mar 25, 2013 at 1:50 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Similarly, pushing PG-specific declarations like RE_compile_and_cache()
into regex/regex.h is completely not the right thing for preserving a
clear library boundary (even positing that we want to expose that
function outside adt/regexp.c, which I'd rather we didn't).

Perhaps we could avoid these issues by defining a library API that
provides accessors like these for the opaque regex_t struct:

* get the number of states in the CNFA

* get the numbers of the initial and final states

* get the number of out-arcs for the N'th state

* get the out-arcs for the N'th state into a caller-provided array
(sized using the previous function), where each out-arc is represented
by a color and an end-state

* get the number of character codes represented by color C

* get the wchar codes for color C into a caller-provided array

(The reason for letting the caller allocate the result arrays is so we
can use palloc for that; if we allocate it in backend/regex/ we must
use malloc, which will greatly increase the risk of leakages. Also,
as far as the color API goes, the above lets the caller decide how
many characters is "too many" to bother with.)

I like the this idea. Seems like clear and not over-engineered API. I can
implement it. Could you propose something particular to do with
RE_compile_and_cache in this patch? With this API we still need a way to
get regex_t or equivalent from string.

Well, the brute force answer is for pg_trgm to not go through
RE_compile_and_cache at all, but just call the regex library for itself.
That would lose the ability to cache regex compilations, but I'm not
sure we care. The motivation for RE_compile_and_cache is mainly to
prevent having to compile the regex again for *every row*, which is what
would otherwise happen in a simple SELECT using a regex function.
Unless I'm misunderstanding something, pg_trgm would only need to
compile the regex once per indexscan, which is probably tolerable.

Another approach we could take is for adt/regexp.c to expose a function
that collects the deconstructed CNFA data into a palloc'd structure
using the above-proposed functions. This'd be a reasonable way to go if
we decide the caching behavior is actually needed for this purpose; but
otherwise it seems like it's just involving one more module than
necessary.

BTW, one reason I don't like exposing RE_compile_and_cache directly is
that then you have the question of how long is the regex_t it hands back
good for. The caller doesn't own that struct, and at some point
regexp.c is likely to recycle it, so it's a bit risky to just assume
it'll stay around "long enough" without any further interaction with
regexp.c.

regards, tom lane

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#63Alexander Korotkov
aekorotkov@gmail.com
In reply to: Tom Lane (#62)
1 attachment(s)
Re: WIP: index support for regexp search

On Mon, Mar 25, 2013 at 2:38 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Alexander Korotkov <aekorotkov@gmail.com> writes:

On Mon, Mar 25, 2013 at 1:50 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Similarly, pushing PG-specific declarations like RE_compile_and_cache()
into regex/regex.h is completely not the right thing for preserving a
clear library boundary (even positing that we want to expose that
function outside adt/regexp.c, which I'd rather we didn't).

Perhaps we could avoid these issues by defining a library API that
provides accessors like these for the opaque regex_t struct:

* get the number of states in the CNFA

* get the numbers of the initial and final states

* get the number of out-arcs for the N'th state

* get the out-arcs for the N'th state into a caller-provided array
(sized using the previous function), where each out-arc is represented
by a color and an end-state

* get the number of character codes represented by color C

* get the wchar codes for color C into a caller-provided array

(The reason for letting the caller allocate the result arrays is so we
can use palloc for that; if we allocate it in backend/regex/ we must
use malloc, which will greatly increase the risk of leakages. Also,
as far as the color API goes, the above lets the caller decide how
many characters is "too many" to bother with.)

I like the this idea. Seems like clear and not over-engineered API. I can
implement it. Could you propose something particular to do with
RE_compile_and_cache in this patch? With this API we still need a way to
get regex_t or equivalent from string.

Well, the brute force answer is for pg_trgm to not go through
RE_compile_and_cache at all, but just call the regex library for itself.
That would lose the ability to cache regex compilations, but I'm not
sure we care. The motivation for RE_compile_and_cache is mainly to
prevent having to compile the regex again for *every row*, which is what
would otherwise happen in a simple SELECT using a regex function.
Unless I'm misunderstanding something, pg_trgm would only need to
compile the regex once per indexscan, which is probably tolerable.

For me it makes sense.
Patch with proposed API implementation is attached.

------
With best regards,
Alexander Korotkov.

Attachments:

trgm-regexp-0.14.patch.gzapplication/x-gzip; name=trgm-regexp-0.14.patch.gzDownload
���YQ�]{w�H���|�Nf3��m��9������b<���Y������I�I������I1�����uwuUuu=~R3��\�Zm�9D>PL�����f5w����B��KM�d�����	��6UJ��F��y�*�Dz���,�������g�J%c�g�Z-k�J���5�f��o��@R��..Oo���B[�c"�<{N.��5\�ossS7���f;�g�nr��F����I���p6.�j�z�n�������;yEU����������5��z`������?ZtE?mv�DK����j�A�Tq��]����`2I��������u*���RN1�D��F��5f���:t"���t����R�%R�^��|�X�5�^�3�R�X��2W��t4���l��xDj;l���?90�9�]17�AYZ��U��c�		^)��#���s�6�~�Ld��k��(~��%yI"��i��"�{6F��"���/��}����0qj�W5����� ��h���WC�U^Z>���Q���_������%�J�����V����~�������������#���}��*tQ�>y��9���pU�3�
)�����Yu��4A�7p�����3������(��0�@�'X �A^��k�y��}!e�{�J��P�Xw�3����I���]l�$n6�~Y��
�-��L&D��
�1���k�'�"��)���j;�4��+���{����O������������mE6����(;+H�?��rb����^�/��B4R2�d��)Ar����8���'b�*~xk;�ES��p�������fmIl��6 v���PV�l`�D,�� ��l����S?	b�S��$76%/���h������KRV�/�c��U����������p�8����t8���7����o`�o���|r������o���WW�'
�q�\����_���1��0�����0���s�7z��iho��� �����TS�2��,kaK���>����x�g^������LNf8�\��)-a��)C��hv3�\~.�IQOW�����bT������fx6"'�z6=?��_.����xt�2���Q���y�Y
�5Ol�,C���.��_\�dN�~q#�'�]��3��O�ta��7(�ib;S��*�f��
5T��%�6l�"��n�%)�U�5��
�gXV#���������������f:�����N'�LC8�1)�,Fh��H�l�Bl����|"Z�mj�Bc�a=�}�xy}-�T{�dzD9�5	3C�[`���O���Y�f����
+�������S��Sb��3�I�y��oW#N?���	D��p<M�foA'��i��A��d�]�������v7�r��5G3
p����*9��
��pJ��P��uf|�LM������};��h8���dF�6D�`��m�����=���O����CP����;��)w�F�B6H�/�����w��<5���.x�ymyM����x{*�1E�5!$���P��;(�l'�	?V�������z����p������������M��2V#|
�F��	'�����
t�E�!�,�l�@�v�3���2w"��sx72\ld��r�����6d�L:�:h�$���d��D�zIxx`�CU�-�&��&�:�h��(�j�����
��I@�_91�X$�S������n�6}��"�c)CZs���k`9��5�0��)�Oo����)@����)
�,��L��jMu1�A��YY2�7��dS�y3�\�jK������������+,qm\�.��0�����v�q)������~*H�I]��W�QAbIH�w��oI�^3�@��g�A�]���1���x�R�>�	����A��w`95S���w����f�9k� ����pX5�.�.T���0�������M��+�&�e���v�+�n��ue�6$���bX�7O�g�D�{� P��D^�6�]�<7y�P��G��=����-��%���m����7�����a�j��&;�j&l�<Y�}�<l�>K���`��	�l�S%����,��1���v�+3?lf,�7}�pc��7M�m�i�
�N�m�������Cz���O��1��i��a�4M2�6�G����6l[����u��[�mu���9"�m��D�6��mC�8�a��*3`�4�w�m�a�o'���l[���{� =�n�$�<	����m������ ���`����	��W�|��v�H�m���-r��XFZ���3l�N8'l�N l�>8l�>��`�tz����tv�m2)��g���m�{�m�{�m���m3���m���c`�t�y����`�tK}l�P�e$��|�����m�����m�����m����pX5�.����9�f^�6G}�6G�}2�6=�q�69�%���~���z���3�uv��@��Y �a�����z�%+�&�eC�>�L�����Po78�=�
RS�]��G���M����P����Z�5�,�Al*[�-�����pdk���9Q�Rvu�����.$x�
���t�����Z��kU�<I��Eu
�><��R�rw�#���G��if����|3"�#���vW�����Q�3�SL6�x�o>���J��g�9��A��g��y���V�M�zx*f�Lm�������_��r8���|�PTq8������|=ly������������C�/>9�������.'1w8\���d�#�9:~���O$�t�0���\w9������������M�-�!+�5z���@���^o�������#�hL���f�O�4C�]`���(����#��Hj�wo��x��,�����jvM��Q��~��`�wP�d�#������ %���Ph1��S����h��v;�Y�C���&A�T��P59tu?q�j!����f���v��yb���S�}���t�q~YX��u���
��D��-v��]��m��Be�n
���K,VT6�%r�NO����9���P,�A[�$�3]]N��
�������W��	��'o���\.��f���i%R)��}�H��J�I���#�����:���/�-��E��������������;s�������������n�=�����%���������d�oH�i6=�(9�S�QR*�����)�K���S��+����U~>��2:��4H�F(h6ZR�y�\g��p:-}*@f�0'����oO����	��0j2�.`(���!��_k$2����C�%#.�����Pb@����;��Y��6����L�!=7q�w�V�Z����o�J�	ZAl�,lw����"[�>�!i�9��b8s��JH�T``S"����h���82�M�/���T�SS9mQ�	��7�K�-���9�r��9�!'�7C��;��D.����O�!���w)��
V��D.5�?������$�L�������)E���Mb���[����Z�mEX��������C��������'ycVDn6;��a�^�.�f+#"b�QYt�o����l��r��������7����8�hT�m��B
��&=����h�J-O��!S1�[�Z@��z�yu��(��G���l���@<0�
cz��
$�D����n���F�W�t��<�`�h\��3H��J���/����f#)��9'7�1/;�Z����j
�4M�iZ�k��q&���,���]!H���1.�c<�Q�����r0�`���?j�F%ou1�>?��fW�\C��/5;��A�(��D����	�E�������(�� N�W����P(,�s�1i
����+Ld���!��lr9��Gl`����4�N/�y��a:�V6T��P���n	��B:���/�����f8����
7��W|WG,}��KE3�f��R��|�`���>>��;?��c���R���S� ���'?��e��4���gA��">@mz��Bh����^�X&^���a�IB���-W��F@!��u������H7���J�$r!�R&�m�y<yx{������OQ��R�Z�h�B|��i�x)���XA�����4�221AC��;��z�HL|��{H4�V=$�����t���O����������t4���a��MJ�5	j�(�b��nP�+�u"V�U���V�op+%/����z�j�����Q�aO�C:a���F6���o������]�l�9X
����HT���1�_aT�x��qG��HOPW��1�C���,�C�@���!(%��
`3�-q�y���}~2��w�|�b?�P�P�A�`����j�C��!�[���*gX����'��r�8<�8�
����m?�	�9���m���.�:mU�2�r��`u�K
4?���.ep�GY��������4��U�z���P�u�����U�0Z
k���kh�;��e����O,:�t��R���4�:.T��kAA�v<�Qg_���&W5T�����*�V��&P���1D���55�^�/EBr��a��fA����I�,�D�,6���z�n
� ���:`�9&�����p(T����:��q��lu?M-i���3�[��ZPp3��c��s�o��JA+�K�`ws��D=��wc@�"X����z�B��<�F|���b�2/z���)�7�(��X�r�����^�2���r��?+�,Dx����>X7�SY@�`X~�#�f%o�r����A8n���r,�~8~��@�m��,"�Wn��y�\����C�zsu5�����������j
C����6����y���!�F��I�,j�6s���������6/a��vSj�}�N�8t����X
_����Z���<�P�e��"�l���CtW���RU��O8��Z`��A��]Q'��7��$c��Y��C�5�un��!� ��P�c>����T�E
>?���� ����5e	�����
�V��(g�.r_�=N����ntK�r��E���DHt>>=�T�$�2X���G��];q�����5h�!������-���$����iJ�N�5(<��?���n�H<)��Q(��Z���l�K��ay7t8`���v[j���(������)�7�����N��F���i�R�����-AL�w�7��t���p�'���U�����4������E|`��:���"F7���f7����^_����o>D����V�6���>��n� ����F��2-�X������[�`��z�V�������,z��cr��Y'����
{���2��C�:CA��3����14���s�WNd][����!� g������0(�]+�l%�F������M�2N#�l�	%g��J�\Y<;��i�^�d��qk&G���Lts�)0S�J�I�:yc��z�3�H0Y��l�EQ�t�"��I	�R�#d�K��Ay*~�$�\�w������7_ejLI����mk<�)��I|.9���;��1au% xG���^��=s�5?�X�&�	����<��Y
�2ar���]�:�w�����b������E����0��������un��D`6���<c�@\�AqNI��m��l�uL`���3-�1qL�����J2K��{����!c �2l���A�x��u�����oP��D,�
���M�h][X�hY��H���
�w��"�_�\��8�8mh�5�*�Y���%c�1ra��n	I��F�M��.���B�{l~������z���,�����h�S�8���c��� �0!_��k�_�a�M���[���b���M�G��`(J��}�rG��o�)���H D��,��6(�����G��3'�M�A��a4`�;�����=�=��El��^�<������*��%kf�b��6�]�]Y�]����E�n��w�}��-����K$��=���I"�����>�������cK������r9�<X)����
���u���H� ����Yf)%\G���e����\Oo�	�d8�l1��M�q�gF� J�P���H
��m.�@:��/�z0���|��;�n|��3N�I%<?Bc�#YO�l�b`��X^Fo���9Hz�o�"v$��K�9_��s���k���bm��Y
��-��,���8�@M9Cl���xn��2�]�������=M������*'C���pcCz�f{�-�:���YNYSpx=6O$|~Cj�Hf�m��e.�����-���v�������L�R���CD�,�CK�i>/����[�`�!�6��uv R�p�(���i#$Ed��Kq��h"����v
�@y�]"p��l�����H��6�$l0��c�,�ab�= ����Pa;5b��H��X  A��$����	���a��mLS����L����Y�g�B�=���hV�_��}@@^l��N�Ddw����e~4A�kN�Wc�Q^���US�����5\9�2�<I��OY�:��E�������������������%���#Z��'��[Z7g�7�p2.H�zU�"���c$������h
�e����O�n����KQ�v�. 1�b,����o/���o�"P0��t&�c���{�[��,�K`��<bb�xt��:�������	��6��uB���pJh��0�X���8J=�V�k�p8������=;��$���9�s�Y�����9������n�a��v�LG`��}��B���y���B���Xe)��@��N ��SF�OW\�|f��G���#�,U�^>	A�����YjW����ok?O�6�0�k��7�S�x�0� :B���Z�f�!���@��������;K�E:�	
�"|�S4�I2��U+�ST,,:$�9@9�$u��X��$W����n���}�v����S����W��s��|he3�LI�)���q�3�����X����t*�B���n����G
��z�H�i�.kD�?���S�`�=&�.���V�5��q���L����\�s���}{b��,���-:!�W}dq��K���MS������PPz�n@���� 1>�d(v�J:����0_�����{�����8]� &\�A�.n��1���d�o�K'�$vN�hb6�V�w���D3j'������^K@1��9A�8M���y;�/����aH��2���[8��\���H	<��}p	N8��
�8�v�m�&��s���!���(�	����~>�>�F�a���������2�p(*��;������O,��}g��YA�w�
<F���D2�qLJ )$�;��������e.16_��]���G��(�{Nw�D&���1Za�]
��
�l������j�'�uKE�b	�-�&��.��"����0"T}G�xF���M:G~Q�����ib��mV�k�lfNk9cr����V=~4MK�+]�pH����*��zlE�)c'��_S[�1��|��n��&����5�m:H�
� �m��{�g�{
���Z��U�AJ���h0�s(��{�H�U���p�$`�ge@p[�w��;-��2��(�p�i�=&���4�[��bB�!*y	����2IfxiN>+9!�%$���&�'w@��*b{�m����[�'$�`a�����E����+\lZ��f[�����DK�-����D@8;E/rX���O�7�e?cl	mP�l4������%���ln��e�D���FG�	B�N�W��l��{�i���$��}n��A�����&��-��-xQj��tg�#k��A;8���v���Xeg�=�����y�*�	o����Y�a��F��^Q���+t�~�}?��2�/��n�@�g�q��9�A$��HC�"JHlV��w�u����@�/L��8��(��S��,/���(��B9i��p�l���y�WN>+$t&���J�>e<�4�): ���S�M0��]]?^*E��	&�$����_Q���cN��Vw����6���4~6��^���y��m/�
����%B�v���K�����V��7$��i�����[���5
���l8�fn���O��j,��,��y��[�1�;��G�����A��������X<`I��h<#��X�[*�_���S�����g"��*��l�f�u��F�������{�����'2/�h=V�����%���������X����i�rj^��|��W�3�?�}\�^���6�,v
4��G�����M��;��,/����`��� ��p8J+�
	����oR�6�4��N�n�{��Zg�����Y[�������x��%�:yz���������.�����ds��R$gc��)%�
�s;����o��p������7�fG��x����/�{.�|�n3<s�Y�iA����� �8��"Z�#�=���Q����/���n\6��>��X2�#y���F��C�Y�kO:� ����^����=�;���&	c?�x���4#
r����?�x��](��\�7�`�k��gG����� ���!�+	�|~Y��@�]E6��CH���	(���%Ub������i���=9���ie� ���b'f�_�4�����V�j�����x��T~5��#�w���A�3�[���?�������C+&A�&5C��R����3^���p��
u�b�"��7�{%q^�U����w�}�,�l��]77K��'���"�Y�E��/�O�<-@�~H����`�o�����W���%XM��2�SXv�Z������p�����6	��A����!2$#��A��o�=K���S0},���a�r['��D
����i<��9��N�g�K2;�1#/[�b�^��v�:t(��=��?;��X!���
H�������C}�V�\��h2�B���{���.&5��z@�tT�_����A�����fG��i��F�)^w��!��e�0f5��{���cF��R����~0��k�u�yR�����lG����<W�����J��
��,����a�Hz��iRG0�1$��cal)d��T�Ju(4
%T_���AS�K����=C�����<
����a�v�/J����V*�4m�5�v������=k����y:O�K�P3�S�/s�1���u�����g��m�����K�����Q��Nc�`��B�}j9^��=U�~9�/X��l���+�M�^����n��1��AX�C�_�'\��<E�}o���i��m�={��N�57f����:)�H
��R4��������=������%hL�P��8C;o�vVTM�������5;��o���J�������Y���V(����A�H���9�<$2�cEr����r����4��Q%���jATA�I���l��CH�+<,%�������#�zN.��a%"���\����Xg��"w}<��t����!B���K������&��=V�B,�h=�o��=�����r����E���M��Q����p[}PA��<H���\����M<:�	������Bx�v�H�1
NB�E2dD��C�{FpI�S�vcZ
�H��Ud�G���tD���L��!.�V	{i	�h
�[�(�fn�D�=�f>K��s������~ t�Etdu�P�~��[[A�\G��d,/
����|����V���4��(H����� �-�W!
����n@W��0�g�~��jx�Vk���*4�������5�*JG,7�B�L��$ <�'T�Mg-�u�(@c#�)�����8�zrI	�0����A|^K�4r�Y��K� �q����!�t2��>�o/0����u[z�,�������9�����K�{�T����C���G����ku]:����#�~�S���Z���*�yT8Nz����Q[>%|.@y5����H�0����3Z5�Xb�SH��S�P�����Ew=� �`�_�g�������oK'��D;C���y�7'���1��:�#"/������7�����R���>��n������D�2��K�0&g<�85T���8$UC�����n��\>h�����j�����p��W�x����!>����B�EH4P2
�����������eN/X��}X�����*��f�� �>���x��Y��:��~�	��t4��u`�&f#��_Bx\r�`��z-�4���7��#��hz��Eg{�)�f2�~����w8��.�;v�`v���e��Q�f��q�}%j�F��L`2�:
��x/-X��Q|��^�e�(S5��W��l}�v�5��50��/N�F[����=�+X���0�4��N��q��*����sd0�i�^�[+
�E�������dm}��a�<�}B7=$�8�A�|�����D����K�"��X;�8�u��7��u(Ax����6u8�D�I�d��N~����
~O	C]Z1��������B���Dq`�a
�S�?9�0���S:!��v-�N�g�;[[hI��(��}��-�z�R�i�	�Aiw�4��]~�FC/�Mb�a8������jJ�����O��j����P��z������56)�f����s���sn��4b~F-�P*F���3��'���� ��?�o�����o���%��������dd7�qN��)8h8+x��������8�4�XKL.�U-�O�)��S+�������@�^�O��>$�=|���������z����o_�x��>��Qq����v�3���g~���^�	RT^n�;LW�0��H��� t�	E��`r��ud[��_����<.� �3D!��%	\�����@)=d"�&Tp\�e�2��C�a��WnB/���`e��;�2D���B��
XM���L)k��m����mK�������������3�PC�� �8�L;��.�&�A�2p���n����#�3�<�~�Hn�\�d�
�@����T�'U����\�(�H;�Rh�\�����Z,���k9����%��c�$�w���S'U��e^����H�������#���4/g��|`5E����h�Q#\2~���R}E9���g�G!Z��gUR���_a;��jm�e���t'���
1��W�!%��2 ,8����5�v�

i	[*�`���*V�*��k��s��]�g�N���%��U�q��U��P��DB�A�x�"�����x1�����R���~�]H�Bo�(��
���
%�e�������m���Nh��
Ak����,�,���)�#B��/$�m��F��UC��7����r���6.,\��Z�3	��J����]��~��	��[�A��h�V�~�fA���vT}��y��X���f?����l"��fI@dn:�%������J��z<���3���a�e��J;����[o�F1N��-j�|����W��M#3�����roR+�e�����k�=4V��#46��xF��:k/O�|��N���^����(*�����{t���Ajdu�f0\xy���+f��k�h����p1d�����{q6�t�����;�����vqI'L��({�Gs��U����_�Lo��m��V��>H`��B���]�Yp��h~jO�e<�f�n�H%�9�,������@�]D�p��E�W��������g����;x��%=����#��j6�I:��,4�����(&aHd$��)��r������Mh�w�jt!�X���O"��-����e�����|O?o����l	�d`�&K���sV�k=�nH�rV����l��I:�a��8\���@�\j��/��_({�G1�6�����9��&
��xG��b=�N���E����S�5��	,}h��A���"��jV��H�a&�5P���}$u&��zJ�	5O�wt$���O�e�5-PcY�Y x�U>�H�T�]�m&w�Ae��{er
e�F�`JQ�%���H��"h���
��������M%�2��,_|&����S� ��d%�@
�,��a.�����j�d|n*�5@4�X�*��-5N^���H$��}%5���;��T��}���F6!��j]?/���5��j����m������7���V���^p���|@y�/8B�'��7��C�0�|x'�&2
z�?L��(]H��m
��������hi7���r�}�D^R�������I��!=<�����^��F�,��G��j"���e��d���D��m}]�� �vu�f,.����b�$�_>P�t�?D� me���?�!�K���gr'��P	1�Q������fj�+}1J����U4��DM6���Kr4 d��E^~�)1U����}L�_��4.���k���-;I��aBZ����1�)���!@�������2CA����L���5"�o������@�=�
C��LP�w�1"���3�!�����jW@
���S=��OW��X��K,��B�(��$G�as�C���}z�������K,���'<�"�x���9E�R��RLzY�L��o���U���f����@�$�����x�~�tFE�B>�T���^`q���$����x�t�����\gp�n��>����R:��`��9d%Z���������LS>j����k����aT8/w�	�NU���2-���o>����R�1J$�F]*/Uw�������&��q�=�Ux+��&�~��U<%�z6���9��{!�
�c,v��w����&3N���X��)%q��uI�A����R$G�#�����a8�������f<w7-��O��������y���]U3MR?����'+#����g_�h�|�X[���ul9��
8$6G�����`f�1��n'�!l���Mm�����+�������LQ��p�0�������s�*������%s~$\@���������J����nC�L%U�z �l�����<'6O��U�W��Y5����*FZ�a(�&�����3��&w�g-��� �T6�����SVB�xLr�����G����2U�&�>�t����J�EV�����f��-x	M�^�[�0���$v�hd�g�I,)�gQ�:�Y~"�U�0.��V=�"��:�s���B���
��)b1Cp��
T�����J5-d��!C�?~1P�����
���@�C�HjP��|�P����+��������Igdy���R��`U��3T��!��FH�j�V�����#��9�q��!��i��f���E��dX_(Mf�$����Q^<z�UB��x61�dkB��f$m�d���n��HJ5����b��RPI�:I�������nD�$P���.�P�|^�fS������<�}
I���&f���V����c��E:�%34vtp$��In�)�~}<��^@��F>��JOP��*G�b2�z���3S���������r�
8����a�� ]��SjuCg(�oExdH�gY��,%St����BK�W-��`-v���l����M��5�#G��hx1[t
U�|d}���^���B\e���/��]�������kf%\+����f������OC��XF�B�[
(]�s&��.H�sP��zJ���kD����BO=#��4^�a��m�Z��j$�*D9h^u�����N�)#Rl�`�2��K�a��SL	�Y%o2f����<�^�^ia+�u�%������J��R(^U��4��a�����a_��~��
����x'_F�&g3x���!�h��@Yt���8?��%���L�VZ������8���k!5QXS����S��g�%����P��9�^&�G�24�YCn�A��Z��A��(,�a��O��>9��m�|�r�5EnA������!	��A6E�D��p������%fV�^^�!��l��o�/-����<�8O�	�V-��#��%���e1<�=�@����C>� ;�6@y}�d���lh�%�jE��=Sa��*S���i��j��#2����([�{@'��h�=�)�23� ,�A�v��D��RZ&Z& ��2 �2.���Zv�8���~V'�����!���;	�FO������.B����	�
�*-��;��.��J
��P���$�B��S\|�b�\y��2W�b���a�)�W5�9���Ry/�Ls>E��l��y�s����~����V�`	AYb�Z[`����X�*����1�KR��F�F��34byhO�|�\�f�4Td:uEI�Tr�� K����
Gbl�Ms5i��+���CW�1��G�/i�`���$FI�	x��e�e!0������!iv3�+�R3���"\��k���O��� )0��8��=��x�
a+�m1����	G\�<b#����D�>��Bq[utj�U
W�,�a?)��
v��{�5���\�m
����<������"ba�+/�b�U,�����^�W�##E�*��Cv��0Na��c|�!P��>�����M�_�7���������!�V'�w��C���@���Z�e�z�������/��#h���������p�=I�Y���aL����������c�F����s�"��/�y������������kW�_�kC�~�p!%��=ns"T��������V[H�����6��Qq�*���Q���R:��x�$�r�Q�3�	&��������29c^�'����������!��Y<�e�y�R�`&1a�h����|�����XZ��IX��j^0�K�:�"�5�pMT�h���,(/�3���Y+��pZ	X����JVSW:S�I��Qr�I^g�d��pS��)�@A)-�|���ieW��%$�R<�|����N�1���
��+�Ik��DI�UAO
��.��xT�9K���g	>n��NQ��K��pdI��g���B�09�@������i��
C>�
F#f����k�&Q&kr�+L ����3\jT�!Y��7D�g	y�m8u��~�Y`W7��5����=��b7K�w%l#��>9;�?�wT��>T���&��y*���!���/��c%Ol8�+�������������_X~��c�����������g���<n�SZ�0�!���`/�`���j���5j�4v���K�c�dzq���21?�P�p|��wyE����PYz�ia�� �s+e�T�?���f�0�����+�dA
���Q1�*i�%�������G��*E%UU�:xfW])B�%��
��!i��n�n��9�$��W�H�Y5Ao:�O�Ju�N���������t�A\]� ��|b�� fYZ���f������'��Y��u�oT��D=S�c�7�p�|4�D�l��/9��,g�=������,1��q\�P��G�f����7&��	~��7�x_�67z8Q���fB�'�;vu�
R�J@|��������+�+��Y�^���U�l��X�a��R��u�_P��Z�{_m�����c�����!�9E�M�w���������:Y�)�����x-�����0L��]KB��X��~����z��
y
Z�w�d--�����������b�|cC�Q&@xX����Ga�t�����������{���g.~.�V����u=tm����M���L�����us="������LdUU��G$�&��~������i\��8���*v�0�T�"X�	�X��������y�������t��eG�($^������+O!G���z���D�*�\l���x[��������?�I}'����K���P���_���T�B�%^�D���X�Z0��]���l*������f��������b2���/$��K���*
V��._�]5��R�O�~�B��#SX5�@��WZk���(aY�A5.�`Yu�U]���G=����|�%bj���i�+��T�}����_�?^Wx�3������8�kj9[j�XL���F�!u���!6����z�U�:�T��G�&�Q�X�����yII�!�KK�/|�b�|8g�}o��o]X�
��6~3�EI�
��Q�6�4F���+�\��[�����~�� �:9������{Q�A��|��?�J�d��:���pVC,����Je�o�

~)����J�c��i�4���c�u\n���6�/�!�����;����U?��'N��,��-�oE1����`�
z���Q���c;�����k��g+����.V����w��	��(4lp��#�~4���.�c����;���k,��Dv&�7�	��*�\�]NX)����m�+��^�/������
��|�G}�~<o�j(����N�B�`���%�����_�
>��TW�C�&��kP&��ZGp��Zw-��1�b�� 9>�"gN�^�
uEZaSA�������nj`��>	+�_w(f��v�W��\ �G���Z��3VV�jn�O����GO��6b)�8��_��2���Is��|:���3�$&j�:��8�%���S��b8��u!���I�E[�XHPqlD�� �%��U7:W�kR0<3ji^]+�xS��y���J�)�){S��~����$KJ����$\-��*�@�)���T�JN�����GS_�2/��w��1�����hR.�QZ�oB&i�:�4�l�6Ja�NhV�F��VI���>icMh=��]��.3������v�����3b�J:����l�7��r��]%��\���.�+0���?�~C���J_F	q�q���u��|2��&[9M�22��Sv�q�U+��7�&�|!HM�]g��D���.aJ|`Is+�<tM��Tc1��]A$�G)�"�
 [Li���t��DY�R��\F�j������,*���`�QU���������Ou<~�M��h6���/L�Tp�d�*�6������$����p�uT6�4�ch���,����GX�����������U:�����_P����{����?�����.��[f����c�M�Z���<����c� |��r[>�J��������"���Y����n;F[�{f��u����eM�
M2 -KuDxU�^"q�*7�����~���;�e'+��Z��*9:go���A��n��[oJq��.Z
U����\3��2�.��T��:/�Hm�wx�u]�4��f���[	~�;���]\�����}�s
N,�1�oH*�E�X�YT��*����[�)�����_)*��"]@�A����	I�����*��v�,�W,@���n8fr�g���-s<��k��}A
@.�-����^H�g�X�YS��#	��p�O�Pc�|y���+��	H�Z^X9M{��N��N�7��j�����R=	$M��Wv|��c��������c�����>�"}J=Y�1�����-�mU�p���a�p�I-aSP������b��DY�*Q�������x�k��O�Z�	8�������z)��P�x
T�����,��R
t��z�D���q%g\��;	�����)�U4��:9{�������]:�K�����riG1��Wk2�&���V�U������^6�yP�ew�������^����6�EV�F�>�W����J-?�.�0�g����oMO"a�G���ik��W)���KP�(�XM��4����#�,����Uj�"�����-��6�"^Pwl����4�0�	A�A��$*F���S����6U�s__'0u�P:Bi��?��c���n��(�� Zr�m���<�-y���cGW��!.������g�1}\%7*�+����sX��2�=���x���dFI�dB�K������}�o7��^d~[0^��T���,^(��a��	u����\}��+�W[�?�/9���)��0�'^���H)X!W��n)Duh!�m1�[m�i��h�1����n�s�~��z���9�F�k4�=�I�~�y4�S��h>*������e
��v�VB�B�u�d!���"�����V���+��q����"W�de����46	�8��J�.&LTP����~�����}8����p�w�W}P��^����E�-�����bh�K�R������=H�����M����0_q������6:;�^T���nd�U���k��|�����KA�����N�F�C�G�,1��A�=���#�*M�1���<��5���(��m�l|?�g|!�������F�$[�K�
6����A@��SLa���S��+~��.�S�� m:-P���Yj!���y2��P��^6�
�7ra����^��RG1v���N�+���_���P��e��������4���o�����X�z�A`�j��v�?�|,�Q3����9*��fWN���zBh*8���U���E_�#�;��4�d���l�v��(����������l|�ep��U:�Z���-MV������}aKO�W��[��M�������0��"�RD#�����wxJ���+%�%�8o��ONmI�����J��8wL�z����o]w�z��~Sl(G����'�+��y�ft�E������O��{�y<��x37�f��-bmx�U�����������<��Q[�.�t����,�W.���
z��H��py�dmK	/�����y�U��@�IWlW1�/n�a�f��O�yIu��,]]t/������HY/L*���%�y�%\o�2��#���R*	v�a���$�Oaz]��'�/'����Bh�c�)������A��=v�]y[�W<�T?���b��
��(���������	�n�~,�����YlM����u��/M���Ym������d]�5C�(�8�M���F�X�V�
>�f�aU�aJ�S
�<����k��,��2E@�rY�c����+�m���4����;�=�D4��Nl][N+��$	����YK��#�<��
���������s��
�+du�(A��[iv
��l�����G��3��?H�:v��Ue��s������}��Ot�Z���������nL����������T���_Q�h�H��#?Y�'����~�����fs�,���V?��*����F�[�3`;m�����Z����G@:[[wvv�3�Y��Joo���n�v:[�����7|e}sss��n�� ����V���� }���r��IQ����`9s���:e[3���8)��p�p>�P<����t���SH����a2�f���+-�jZb�\1�P�w2��3-9����������y@2vpT��Fm	�8�!�@(���(���0�8������|u��s�)�q�B2);������w�e��8O�0�q�n]�E��fP�������������3���Jy�n��|e��<��O�HA��c� ���\������{�%d���h	��0a!�����������V�~���3��d�9���>xy`fV�\��	Ewk����K�p�����v�x����M����}1����l�������l���),�����~�	����E����n��h�;�V
������l	����
�,/Lf��������������G�*% O@0	����kIbw�:���uSp���y.1�v�)^����G9Vu�1L9O�����������t0H�-:�g���@_�Q�cD��(�F����B,�y��a:�mBFY�5�ek�������1Jg�L.�*f�x��vTn	�e��Gy�,��G
���WeL���]�q�)cV�������W�M��W�D�=������.�(($O�����Dn����\��0�1��r�n�r���e=����"��z�#�<9|N#����Ax6�$����uqy@��#�[��|?+zsL�.����M�
�f�!��?��N-)����A�?,�C#�XF!h��Y(��s
2��}B��%oS��N�\$�}�����z�����Nwp�e��H
[� �����������D�n�sW�Y>9�l�������[���������4q ����0?M�@�?3/���a?�����4������"0���fs����w��d�����[�����Y����`�� �������,?��D���"�l��_��Ig��chuH����<����;_���	����i�I��Y�p��'-}y����h��R���1�DR�7������g��mW��J�p��~���T���89�:.�����.Cy���2o$�����$b&X4�2|�R����6Te�2a�����|��>[
m�+�a��B�R���O.-�;��F�i:_~yg��������<|�����|2��{hPYj�E�R�0���^��RM�f���v��Y�Fv���������=���� �k)2�%}0���s�
��g�Y�>��~���M�������NZNF�&	����X�Nw�?n�l��P���S��+����aB�?m2��c��|~�xw�2,�y����)R? �?����K[B����X��.�i�l�t�%t@���'4���	�2���"��'�"!�}���/��]ZQ]��Kt�����[��$)E��dA��W��
������-U>�d7����hsw	x�LP����Y�%�,V��Im��K�-���`���=�qOM4�=.����-;���*k6B��q�]�p@��e`U{���g8g,��>���m��Uwv+���s�oy�����}�+����Z[[����+���X��(+���}�]:��4���JM�w������+{���W�+������HL:>�p>���'}���&��;��*���a��T���Y����?\��ak>����:���V�8��|�#�/gi@��I�4������N�'�]�J�m��G��	~��������"��A��"4�H^�E��19�}������!]�gBDhYQ�^�)�F�%�>�h�#�D	"����cLRg�l5�c@&������8>z�2��
3��C����Y���F)�P�2���P����-g��+�_�l�Vk��?x���z���y*���P�O�J�ft�snu���P��WL%��'�6��md**(:�G���-ni�������`6�M_gX��=�$_/���0o,}TNI����4Qz����+�h��"p Z�����#��_����\�U�Pt�(*}S}�A����'2q���V���u8(c0���{a8�g���l-����q���l��V�n��l�����+7����2��.�#�o��^	7KrF� �Vf�?��$��=`kG0�����Up$�uJ��Z����v1�U_0A�*���"�G9��DL�1d�`n��>Y
���PdO+�@��������:G7�t����9�q�7Z$o��%��'Z��������A��	0!T0�&i�PZ������������
��g��A�q�j��`��s��9�]����gJ������|�m������QR����t��8l��8d��Q+j[��v,lK���)��!5� �H���������U��(e?E��������oW�]�H^/��C�:��1u�h��a*)����O�Q�{�f���^X�?�����h�Sx��k�v�z��]�����-6`a�[P�9X��-,I���Q�e�=q�4<BSh��9�^�h�b
P���lW�O-.X�zM*�4�����2��B���B�q�~�)��vZ�� ��mQ�f�������D
�U�P�2{���u���2&���3���V��jO�e���`�
����c�?X��u#�����u��X� ���+�����lS(y��J�]�xA����S8���+�5K4]��+�x���v�1��`6��77�'�!s�[YX�NQ�����CQW�����Wu�d��v��
u���i��������<|Fw��r<|�t�;2�?�r���4W����1]�X]����������pW����^W]F�;���>����sU������Qs.
�A���������*F^�����=�V�?���,q|����7/��;�����x�7��L��v�e�|�;R]����3UWn�WF"�)g	�J�|3�FA�WR��A�[}������Q`��yw�
����T�"�8rY����,fA��*�j��n�R��O����0B|��w��?���U��K}���*����?�U�C�n����&����no{��������S�R	r��R�,����]���I2�r���Y�^Lf$�rMh|���;�;_����y���#��=����'�}�tCo r����E�_o,��};�{�.6��i�J�.4�� ��>�<�'��/�s����@x������m�t�K	
�7T6�����m`�k�c�V �J����k���_4���p�(������C��Z�b>j\s��o��p<��qM���F�!ww����Bm�U�MnCw��B���~���l�����DC;���w�0��p������4������o�u��(A�=<��j��<������y�fX1nX���xu�O�G%Z�-�F��&g' ����(W�[H=������v�����_��*�Q
�����U�j���m�?o��CV����lL�#�v)��U�M�e������kl����i���yQ���C�!��gp�*�s�Y�s-�P`vS�`�S2��ya�sFAU ���������Q�l����W
S�M(����tM�����[�&t����e�0��_�:��2���>�?�S98�{~������#8�N��U~:�|2/��]������t\#�_C��I��pf�#����xtpr��!�?����t�#��Y�,4�`s2>K�����[�_������q[�R�g�?�
�^��[����?������>����vw>���_���p��������g�Y>�z����k��Q�sgg�.���>��Gnv���k�&��v}���Em��
G��e���r<��[��+a�_/�cce-��X\e�%��������+j5�2c�n�4 |g�/�QG��~�B�)rC��b9yD�'�@���W�������^���*bz0�s>��s��������Q��;=-�
��v�]��H����lt����ku�]�E����i�{J�q�m��E��0*�� V�dg�d�����F��������u�&��=�bY�3��`�_�E�7x��!�m��|�"I�g	D\W;�}tyQ��j8�.��y\�f��w����kMDU��L����H5_��p�[j�w������(��,���k������Y��v���Um�z?�v����7���y���������?������x�O�����}�O������?��y�o��������1����?���z��������eP 
#64Erikjan Rijkers
er@xs4all.nl
In reply to: Alexander Korotkov (#63)
1 attachment(s)
Re: WIP: index support for regexp search

On Mon, April 1, 2013 23:15, Alexander Korotkov wrote:

[trgm-regexp-0.14.patch.gz]

Hi Alexander,

Something went wrong in this version of the patch: many (most) queries that were earlier
spectacularly fast have become slow, often slower than a seqscan or only marginally faster. See
the attached numbers; it compares head(seqscan) with trgm-regex patch versions 13 and 14.

I did not even complete the test-run because version 14 is so clearly inferior to 13 (and earlier,
as far as I can remember).

(let me know if you want the whole result, I can run it overnight)

Thanks,

Erik Rijkers

Attachments:

re-head-13-14-20130402-2219.txt.bz2application/x-bzip2; name=re-head-13-14-20130402-2219.txt.bz2Download
#65Alexander Korotkov
aekorotkov@gmail.com
In reply to: Erikjan Rijkers (#64)
1 attachment(s)
Re: WIP: index support for regexp search

On Wed, Apr 3, 2013 at 12:36 AM, Erikjan Rijkers <er@xs4all.nl> wrote:

On Mon, April 1, 2013 23:15, Alexander Korotkov wrote:

[trgm-regexp-0.14.patch.gz]

Hi Alexander,

Hi Erik!

Something went wrong in this version of the patch: many (most) queries
that were earlier
spectacularly fast have become slow, often slower than a seqscan or only
marginally faster. See
the attached numbers; it compares head(seqscan) with trgm-regex patch
versions 13 and 14.

I did not even complete the test-run because version 14 is so clearly
inferior to 13 (and earlier,
as far as I can remember).

(let me know if you want the whole result, I can run it overnight)

Yes, there was bug in new color map scan implementation. It was fixed in
attached version. Could you re-run tests please?
Attached version of patch also addresses problem that we now using API it's
not correct to use special values of color number. It introduces additional
structure ExtendedColor which contain ExtendedColorClass field for handling
additional "virtual" colors introduced by analysis.

------
With best regards,
Alexander Korotkov.

Attachments:

trgm-regexp-0.15.patch.gzapplication/x-gzip; name=trgm-regexp-0.15.patch.gzDownload
�`R[Q�]{w�H���|�Nf3��e�8�06q�c_�gv63�R���#�7�~�[��z"����9��1��������OjF�R�-5��{�i8�6�[/g��\����t����S�^���>+S���ht;�������Y����^o�������R�d���V�e�T�����l���H�PB������h8�kKrDD�/������mf��&���l'�l�MNc���p|uv1��8L��Z�Yo���zp�5��r+/��7rz���dxu��QL0�P{v��G�.����b6�b�h	W�^�2H`�*U�u�uL&�[��R���/�z��r���S5�l��&v�0������4]�4��TjE��~,2V�
������$�yW�*<��!�~
�Cm��Vr��gF�$�+��>h"�\��*;�c?!��#��q���;j9�n����D����9����
�(q�k�NLK����1*��8�09��+�����S���G�e��'�A���R,������t��/��������jJ�GX�T\�xj%�������9�I��<W����V<���L��g�B�.��G�����W����������U�N��p|��9����0SOx����bz��y���������]��WR�w����u����-��T�����J��f���9����2���`BT�\3���~�,��bQ��	��CLC�����$��g|����.2��j�s��l��Vd��\,�����c3('������\����FJF�L19%H����6��zD,�^�Ool��h���=n0Z1Wk]��-��X���.����J�5��%;`���
�I��p�'�@�w��������`4NB���\_�� |A��J�qL���
taR�p������'sq9���np~6�
,��
�\_��O������^� �����q\7����yA��x e�&�DFoa}9/�����z���\�B������at9�-�����2�Z��R���A��K����+���W�91~��w���)G2�!�sJ�t��g2�^O�W�_��+R���`�~<8��h0>���1��N�������`z6�Lvc����6�Ka�f��-�eh�^�f�������B�/n����K�F�����MS�21�&��1���"�`f*]SC�Y\Bo��.���&^�\�^����`r�e5�j����Oi��\O�'Ch���t|�4�S���b��P�t�6(��p��/������f@+4���
�������O����G�#]�0s1���}����,�5hFI��
��RX�:IY>��:%�)<����sL�r�]��!����p|:}:�5�H��5Z�'{���zndxGX���^��C��8�i�c6-��T��Lmh��S��Z��3����dj��]}����0�"����B�����s�!���]J�����?ib���A�W���������k]� ���l�����r���s��������G"��������sM!������'�Xq<\]EkC��Z���=��6O{�.+��7���XE��5�W$d,�z
�>+�a�V�0��aY�1������\@�����b#����S�n���!�(f�9��A�&i�&s&��K�����o�6�
5!�AE��E	VsP���'�W�.M� ���a�"�������"�t���+����H�47]�)��������lOI~z��mN�r�~�(HQ�e��e�.Vk���J�����(e�Q�� %����9�:W[ZEf5����O���^a�ch�2?p19��~�-\���sHT�
.��PA��N��Jn���
KB��K�|�H���1:��8�O����v���.��G�Z�IL�O�$��U����������������!������a�x��:wPm�j�����/l&4�[t��h�qR[�e���i\d����PZdK�a��<����!�@��y��w	�� P��\��� � V���@��tc �}����m?���8*UMv��L�6y�0l��y<�6}�l[���[�B���J�m�"Y�c�m5��Wf~�6�X�
n�����en�2`���&l����	�m�����m�ayc�������i�d�m��0l���M���m��$e6`��l��9"�m��D�6��mC�87a��*3`�4���m��7��Ex���a��s���V7k����~��������L��{p��Vc������mw+x>�v3V$���t�9�x,#��F��M'��M'��M��M�8�6��v�m:��`��L
l���`��Na���`��na���2`��m��6�j!}t.�6�R��>�oI�>l����9`��g�9`��e��`���j<V����i�m�����@���|�
�Mm�M�l�������^�/�Lo�]73Pb�GH|��4:j�^o��~�v��b�b&R��J~�w?8�=�
RS�]��G���
M����P����Z�5�,�Al*[�
�s����pd+���%Q�Bvu�����.$x�
���t�����Z��ksU�<I��Eu
�><��R�r�G �49�O�#�� �4�fD�G���[�}E>���jG9�/R�,N1����}t��/���5�8��r�Y����R�Zn7������3�	����������H~6��\Q�������n�������	
�����:|��8���������	N�	lss���y�K�<������/ny"q�C����:��1��������c.�&!����P��,Z}�^W��~��v�NJ�`�1)?:��m?A�Ew��W��P��c��p�*�Is�u�	O��K�7wkx��Z��u4��FM�������^�y�T��X�fP2�����B���N�J�������g��v�O���S\A������]����C�������g�=��zL�r�y���@��c��
]�����)t'��l�;��l�u*�v�P�-�\b���v,�st��~H/�i���?h����������h|}��rr6f����`R����l�V4�D*%����#rY)C;)��z��u�]����5����H �C�:���brr�~RR`rg���72|C"�]�`��w<���m�4{m�:���s�Y���B}��
�<M'��%y�3JJ%1�S<ev�6�tj1�a��v����g�_������}����FKj6���t8L&���H���$b��U��������C��7F����9%0��2`��k�D������`��U�sJ��rK�SK^��?������2����&�n��
P+W��@xA��\)0C+��S�����w��*���q���6�3Q((�3�����H6%�n�����=���#�����>}H�|25��E���w�����{8��j �Sr<~7`�P��3�J���L����
�"+P�`�hK�B��c�����M���+�s�Qn��Rd��$�����mY��V����Y����0�<��o�()q�7fE�f��������|�j�2"� ��E��vL��/Og*7LN��l�^C����S�F��+��0�m���5x�f���tY2\���/q�W�����Q�R�|��~��^����0�gX\!�@It8�������tyi?���?�G@��s\�#I�[�Sw����qWl$���8��z4�e'W��r�]�!��)5M�M�>��{R?���W?�+)80�RbL��;u���B����^���kT�VCL���Xo6 q��5?{R����$�B�L|P)9�@\�+}B�����
�$|�0�O�
��<�-���@^��q��DF[B�N�����j��n.K���b"�WP��CndC�e��� ��� ��}�>����x��0Z`������\�'p38{��pu���'�i�P4ca��.t�n�V
�y����/n����>{1.��\="1y�S�^&oI���|��*���W.+��N�����e�����$��1��q���l�m]�/��O��t-���4J"-eR����������J�m���.U�e�V)�G���G��2Yz�t��Y�M�*#c4d��������@q��D�m�C���hxLG=���xv5L����/N��z�����]��V��*v�u��['b��aQ�\�l5p��R�Z}%�W�����9=.�-�k��9���j�Aa��J��m�K�*�����8K���1�J��?��K�J�^0n���	�j�0qu��ey���� �D Pl&��%�=��f����M�@�m%���O0��n)X�y ���P���@H��'n��V�o����47�)�8N�D�`�b�On�bo,y[?�����NUF��(�����X�R����-8��a��x��1��5
�e�4�n����z�������U�0Z
k���kh�;g�e����O,:�tR���4�:.T��kAA�v<�Qg����&W5T��;�R�+jT�Q���S���G/��"!���0�B������$^"\������O�`7���l�a{�D�F���]8
�J�B�C�a�8jz����������U�����q�)��������4�R���R,���<&Q/�����Ve�s����P//G��������K����oJ����{&���\�e�f���y���#���<K�C��6����T*������Y���\��"���!�y������:l��������p^�W���g��^_^'�����	������<�i�	�e�w�n`v����#�.�����\/�g�������K�������_���K��!?*������`�!=P�A{����"��$���{(�T������n���e��	���l9�X/{V��z�t��t�['jqHj����/h��%��Fr��O�O"��:��'�sEY+���d}���,��Y���gOSv�'���R���t�x�*��N�(� I��9��zy�N��z`��r�`H�p���e���[���ow�R�r
�!���:���.O
bg
+�R��%[�R6pX�
��#`�������>��@�;��i������~l�Ay�����i)�Rw����&�=���'s���x���_��*�k�g�;�f�3�QJu��'fE�n���^��?�P���|��������������;���Y����?^b��q����K96���|����~��j4�����E��wDNus.���~���f���Z��~�TGb(V}��U}�����u�����k�249��������ce�k�����)��b�t��T�i����1��LRZ��+�g�99����l�0n�d��8\��n.5f
Q	=i\'�L�A^�u	&����*j�.���-)�WJ~�Lu<(O�o�D������Y������L��)	?x�m��g�7��5��'0;e�U�&�����+��g�C"7���&`��P�����e ��/&�Y�e��}�89)�X���@Xte~
�	��[}Y_Y�f�Kf�:|�3V
����d��������]��qq�)=���ka�����.L� �0]��*/�2�,��a�X��k��wX�ZWH8����O�b�`�z�D�����&����;�oM�)�e��X����J\���h�iC;��V�L#��/c���'tKH�5�n�=�pu�v��c�knGh��p]��h�xf��g��GK����Mv�Y�	�b��]���
�m���x�`}S7-�gh�>:�CQ�
��Jj�����]n���
>E���
���e�R��(��>|E*�we-k���,3�N�����IR[��M��g�}����}�g)�:���k3�g�����s��S�}��-����K$��=���I"�����>������`K������r9�<X)��L�

��u���H�0���yf)%\G���e����ROo��d4�j3��M�q�gF� J�P�
��H
��m.�@:��/�{0���|��;�n|��3N�I%<?Bc�#Y_�l�&b`��X^Fo���9J��o�"v$��K�9_���s���k���bm��E
��m��-���8�@M9Cl���xn��2���M1M��E{����M,UNF4��!�������$[t���������l�H���� �����8y�\�mA�Xz3H�d-����+��\��c���FXn��L�|Q��~!R�."���c�m����@����Q���FH�������!�"D�����"��*�D�(b=�����+����mzE�`�o�Y$x��R{@0��M��vj��Y���@@��+H�����10��@-������3�0�+S�~m�L�d{b�3���#N������,����=�]��h�4�������v��2�I�1j�rf5dXy������"t����j�-�)�Eq�Qc%E+heK<�3G4��Y!6Nci��n�o"l�d\�l��~
24D��HF�%�'���

X���~j?ig�M��/-D���z�!�c�=f�~{e�={k��!]�s�������da_���S���+��)M$����N�~p��%�SR�� �SB{�����O��)Q��Z��Atd��`6�J�r���r������E�f���1�-Pm��G�ws��\�e:�;��"-(�+��:�*K���%v4��2�|���2�s{v<Wo�eq�"���H0BW�\�.R�2�n�}[�y�����Y^�`>����;�W��wDG��U��,�� � P��z�p���*_pg	���B�<��Z�O���0I���k���b���E!`���(�W��:�6����\��������Azv�
�>|���)bnq���l��)	?�Y1n{�X8�����x�N�\P���S�^�H�^�� -�e�����?� �6�c��2�po�^��Jh��K���;�k9�'f6�����"}��Q�A����T����4�;l����Q���X��SH��b����x��%=?=y�L���P���	b�E�����Z#��	!KV@�2�rrIb��!�&f�n�0�����bF�d�������b	(&��/'���)�I�6o'�;���m��L@rlD�7<��\�K	<��}p	N8��
�8�v�c� ��s���!����(�	����A>�=�F�aW��������2�p(*��;���w���Y�M�l1��0��,x�>#%�d����@R6H�w�C�c�3d}�\,bl��Y��5/;�O
P����L@y�c�,�b����*�'6�S�0O
�����lGM:5=��E;��
aD����%�����t���8!@-
�����?��`��'����r���u���z�h��T;V�����j�MPU�E���.�����0:|-mu� l�������������t�|rl�]�����
���Z��U�"�eVG4�����s���qV[�M���2 �m��;�����k�{t��t4�����I�a��-�Y1������Xn�&s�4'����
�QT�;�;�?�u�}�m����[�'$�`a�F#9gQ������~����+�4�m%��p���"��C�w9�i��������r��1	��6(�U6�D�:V\����yv����6�Co�����K��+��Mc6��=�����
��>����:N��m�s�e�6�(5�c�3����R�����m�N���p��3���������^�<|�����H�t��,���F�Bx�(q��kt�~�?�{2�������@���q�9�A$��HC�"JHlV����m����@�/���8��8��S��,/���(��B9i��p�l���y�WN>+$t&���J�>e<�4�): F��S�M0��]_?^)E��	��$����_Q���cN��Vw����6���,~6��~2��y��m��_MrK�����1�����w��U2L,���R�9)�w��dk�q��pI��:l��v��DOY,�;�d[�:c�w�����I�X�z���`��%EG��@�E[b9@�ol�@B|A7������ ��LZ�����1�ip�9����G������G���\���'�7�����d���a�:��s�����^N�P��e��������eWh�����-�!�m���������������
rz`��*�&���+i%X/H(+\�����B�!"!����
*������~�n4�;����M�����z{������������S+nP������b����X@�
�ZV���.zE����k�(�I�,b,�������mg����W������@��x
�|f����?��A����)�c��7p��������+��#V����T�1�T�o��m���m�}A�i��2���S1������a6�\��l��K��6�<������f�=����D_�^��,,w����)�V!��1N�C��E����T�������?Ck&���E�F� /�����
�:IZ��/�� x+��k_1K�J����������	ox����v�@������� O����>�|d;��[�y���f��]rFA0L�V��5����Fh�o2��h+���M�&|����oH��&r<����,�r�m�J�A�_m�!��e&N�#���C��xdY1<�L�V��@�Mc�Y6@�{����/�~����=������u�/�zs�'v��B�)��H�9�8M���*�&y>������=��{��e�H�A= A:*��	&K�^u�8qa3��e�L��/i��_�|v����:�����BG��s��!2�R5���7�����E�~v��_[���L�v�O�M�P9{��%{������H�L2�/w{��	a�����j������=fn��X4��/�rX���<p�W�t4*=O������lc���4��?<4G��h��
��B-��Nk{�'�'h�D�Y� ���@�#X�\�����y���X!��D�,��S`�shJI��nii�r,U#�s��l4�]�����������"��	�L�����l��,��n�.���>��~�����PI�@
rp��p��4'd^���V�jp�8���*Xh�c�Z���&aO�B�D��B.C���)0�^�oc; �f�-�t�g�K�q�������������.���6�s�i�fknR�#^F�n��������>X���$L<0�<QV��u`���
�k�������aE���~�<j�	R�����g�<�1W��<�m���Jp����N��m����@"x�?�;���,��:�S�;TP�9�=�
!D�$�HA��F�jt�$��!S�
9�XX:2����\-0�\["?y����8���m������Z>��H�vtE&������?�_�j�3�-�c ��|�/�8�g\nE��(�6iS-d�^,m�x�V������A����6�z���hOXE�6Q�fI�3��cG�l?0P��E�!�`��[�4�1�+��K�R63�j�Fr�z c��c���c�e4r7���,L�KK(�E
@o�����-�&�'���m�t�?��5��������^��7hO��.uZI�����'h�qu��N#M�b�DJ������q�D0���\�Q�7
�+M�3o?QG5�h����c04�������-U��X>n��D��$ <�'�M�m����A�#c#;+�������zrI��0*���A8Y����5�[��*bG�mXBHgs��c��`*�8�V@o�%S|�W?4='�W2�i)�/���8=�����(qy����!�����z�w����mT-�	���H�x'=�l��K��-�>���Z��^b$`Jj�����-1�*�^��y(X����L���!^�\0�/�3`��T��\���c��!��N�<����WK�-u	v~�����B�8������T�}D���P����t���\/'�������19������]5�!��?<wA���AE&x�
�W����tN����rI�k��&�&��X��/z@Z��
P'�G�Na��o�,s~��"���(�����T��6��Py�w�,��������QG��KO��h��i��(�:1)e��r��}������}N�q�@o��I��,:�CNQ9�Y�=����qpVf.f���_���2���ee�e�]�X�Y�6P�������/�~u�5�l����K0�>:Vn�������1C^��}��w�d���[�n���z%@d�;�0��7��-z����{�	%�����i���,���-`]�Xcyg��5�Y"SpAv���=�s�Gyy��1k
BwV��*�nUM�:�"��R��H:�Pt�L�,�D�SN�����]�[�~��w�u=�tJ���=@�X9����7�.h0���fiY�KU>R�t��������Y^�#,y���Q�Q�6H�Pj7�&���~�L]U�"!"���R�I�c����#�f����[��x�J���m�`\&~�|1\�L#�va�L���nzI�v���-��I���B/)�D���3fH^����� �>���p�pF�x8�����?�����/��������{+<a/��
����5�<�U�>?9n���S:#K��l#�����;;�����%�6���A�u��H�	�>e�k��C����/�l�E�A�[�SNKk�(��$i�z��������.`>P��z����[�56)uf����s���sn��4b~F-�P*F���3��'����=�A�������g/�<�#�(9�]�u��<�
Fv���dJE!
g�\�H�
zc�R��cm��V�e?���O���������m�� ����p����<=~4�������|����������������f6����[�>���;0��h?�jMQ4�����t���tv�
�A��P��	&7�S'�
������1��?��4KH9~E�E��R�S�!��M���
���\����7�s\n����wI�A��2���2D���@��
\M�tC�Y=ik�R4�mIw>!����|��X�Bn���M��Aq6�_2�k"��x�����{������C�v��}(I��V ed;��F*�\h\�8	H;��[��
$��Q#�������qP�L�BZ�����@�S$Ui
d^*�C[
"q���s#���KJ����u��0�(*P���@������Sn�����(�-��s��B`V�c��J����
���@��W���l�K���(��NC�fRB
.���%ny
b}��Q���������bu�����L:W�)���{��������������I��]����������M���	��b1/Q{�3�P�W[�()M
���tl[6q��*�vm�C_���e mKuB�V4��}��2Q�,��8����x!�y�0���J\��v���V6Zc���Nd�~�I0W��������K�ZM�p�J��D����7Kj�<��`d%O��Q����c�����r�p�A�D���\R<M@��������*h����_&��T��h |���m�t����}����\�}��?�42�X����� �&���m{�
��fp�CcEA|*�*a�
�w`�n���4���@Np��q�Ea"V\q�� ���FV�iS@���JA;1�� !���)��`�\P��-@�%�eG�^\������r
B��������]\�	<4�����v�6��x���!�E�;w`[��'������asrg�x�$�8Y���k�s����r���L�\
t�jC[��."F�����T�3]�A��c#v�n��J�(�O|LI�g�����DQ	C"�����4���@���n��v,����FOp�+���I��>����EV�;���Zvx������P�S�-��,� �d�{vt��t�o��
�P�
548��@��b:Mg}�X��x�	� �.5s��V�/�=
�����\G��������o�\�#�_c=�N���E����S�-��	�}h��A���f�m�>N�%���Lz9j�t?�;=�L6�u/�j>O����#�>��LX�nh��2��[L��E��2��e��� �A�,�s�LN�L���L)L��d=Z)�x�A5�s���w�_���Y�W����|T��>��hJV���,����[���M���2�
D��Ea���m����p����E� ����S��\���~�nF=���A������V��yaU������U;u��n�8cs9?o��.��T���Z�}���*�_p��O;o&��)|a6��0'Me��&�S.�����fC�]�����n�����kL����Y�S5]�;�|]��@��n��}�k�~�'�`5��BL�*Fx��oE�h�����l�
���:c3
�T]��J1S�O7�(���!H[�k+]P����N����.=���[JL�m,7��n�T�k������--Ex2v�b��������TE+,e��-	�����f|�����('x�'.��0�����V/v�wZlO)�j�+�� d{�����[�K��Le��|(�n���x�}��V�����'�
A���\Tt)� ��sI2��V����Tcg�aU���������F��&#���Vsz�RJg��*�a����z(4-^	EuJ��V)X�#�iQ�BDBH(s���N��-
�����o�
�Q�Zi�|� !�o��cCQ��W�t��,���-�������kP>D��E$^��-g���!��#N��h�eB�*`2������@Wy�q1a����02���\�a,��)���lN/���k��6�������f%�L(�?����4���a�iw�H�oH�
���SB%��}��g�����qMr9�l����D��S����N�W��L�����V%8���|A
����Y�Da���%��D��~��9�-E8��uI�NqC2
��6��,��xXD�_\z\^���R���8�_�U���NT"�_��`��,�^����O�^��)��� �Yr�6H!?`J9���u/*��HEu�
c��h��]Z�h�A���]*��\�%��e�bF����6��`������;xV/�����,yL"�V�^Z"�����v�h��#J�'�,���yG��yN\0�um���^5����*FZ�a(e1����B`�t
���gm��� ��7�'�5��C9�#5���G���2U�&�>�t���3�J�EV�����V�6��
^BS�������8�)4��`@��G�Y�T9���h�i��DA��w�OY���(��B��om>����1P�!��bT�R����Je�d��![U�1T��������@�C�HjP�Z|c[�%����&QG�[�y�����UC�D��p���x�gP������m�n�V@����d��]G�(��_[#�-��a	�4�sJ���D�G�-b�����}k,�����t������c i\�X0�u����r���B���/�����F'9Y%�@��Ec�����4Q��=�H�o��d�3���_�0+�D�B^.��f�(��b$�����#q������8���Tp����%21���*�S��`���?2E��S���O��V#[�����S��� ��R��:5$0+�{ #J�6��0�at
@(��9��������^%�W��x����i�����t��^�W�c�o�4�OD������1P�h����W8��%o�2MnY�m+1�Z8*f]��A���%��)��,���P��z*dI�V��R���)B��2/c�5%��P_�6��G`|BV��v:�� �M��Ix���(4���Np*#X�Eydv�hM���Y��b�i�<��m����\��k�����Z���-�����7d���6�J��Rd^U��1�c�����u��KQ��h�]�p2n��?�dI�C�(����DdU�RX��.�����u-1���d�kZA�1��%�d7����(����R�����Yl�c$�4Q��'�@34��C��a��[�oH��8��b��O��G�����.�����hcw����F2�R��l*Za�g����!���
�^��:��K.1���nl�;��DX�b_�X�
`����~
�
�0,1���",���@�dPv;N��V�'�d��v2�v������a�=mo����RV�z�����$���H��-9-6�L�>�{j�b���q��������;���>��!4��M@%�5$����|�S��.���eZn��>�B`�#x��`��p�r���U�"��o�S�x(�Eu�`����*�3	%��Os��K|��z-'�������oT������a�������5~7n`�����/�(�>TN�9u���>�k��_����������M��
+[c���k�70�U���]f���#����D����1�����V�%���Q,Jr����LO�E�F'U���W��Db��(��^em��*����UR��$�~��:�`��S4F^t}xJr���: �v��8����
L(+m(^�\nEq�\{e�@wX�W���5���Yow��@���S���4�o���U^%�8����O��<4�wTG�e���q3��j�y5��w�6��(������9�{>��2��� �*��c����f���Anh���� �A8���k�_m��lU�G��C�s���}X�/��+{��U(wC q*ir���vZ����t�0�B2���]p�Q{F��_��X��_�|qv�����]d���|@���g9�s)��@rBA�`m�C��1�C����0�<p���l�eX\#@Ev�N��lw2�+���=�~����������\������P�+���j&?�7m������)47�V&�U�&+�!D�Cz�M2��1U ?@������k�2Q�M0�U}������� ��B��%P��+���I(^��(��hJ��IN��,����Y���u�Ej���sS�p	��FcndA�x�e��.3N�L��K� ?Du\p���AD���8��|��|:���)i�R����\��XUk�+B��)x1����g��
�j�������J������K
�=�w�����=���pBwK�/|�
�����������<�w��rN�\�>m4���G!��@��[6Ih�&Q&kr�+,:�����1kT�!	��7D��	y�8u��a�Ac_7�\5����}�c�T�Q(l#��>�8�?�wT��!�H�����y*��!���F��S%Ol:�*�������G�����_X~��S�����������g_�<
r=P��0;/���/����::lu��
�tq"��c���d���M�2I?�P�p<��w�s���Q�A��Ya��&�+qT���BG?	_V����9�gA���N1�*ni|*�z��S~�x\���$�
�g	�����s���Z�L�q��;U�t�C�����v�fGYb%�&�P�Q*���w�){�
�T��z�f>�k��8
����$z�-K����
P����XC��$�m���F6������J����5'��X��
���"�������lY����o��f���a��<W+=>������W-3�+�{�:��X= ���`G�x����F��%�l!��I�S�U�d�5���~EA���[�5������ �Mj�i�^<+��g��>����z���Z�v�r�x�;����%�d�52o��� ����Z#{G�B�^���/�[��5�C�yE������olJ@�KX�;������C����w�\x�]�nn����#@�T �}�.A7[�;w@vx2Y���������7"�2��V�&-��S����u�w�R[N��q���$jX���M�I�)�B�AnA���������iv��B�U��W�������r������\O��r-� ����|X.~�����%t�I���Tk)i.H�u���V(TY��Od��������� Z���f�
+��i��jjBI%(����)�DR������pX��v����7�Z|vr�{�^�����gr��Z����D!����q� ���^j���=��%��{��S�� �jHS\e?�*�3.�J��/x����9-�
����	h�R��V+�b�6�5�����h
��B���S��������k�E�Ea91���
�t��5�������\ v���3�>�f_����� n�7X��y'o�n�a�*��*�Ab��|+lK�����3�0H�
����g ���������[�@��U)����d*����)4�������)���]�x&��yh�q���^c�^�CFg�i[wR����,�O�?]"�[���"�=���
0�-z����Q���c;�.����k��	g+����.V�����
��	c�t�6�f�,I�PTS���v\�)L]�����+���_Mx�4�
������@>��?<;z��������;K�=�++�v\���#���x�Q����S#�D[������.��/�F�@����n�I��(����#8jS�������U�c_O��!q�N�W7�b�A�q�\�g0�3�w�k0�1�O���WF�%
^�	]�����b����Tt���/k�~ls���y{�c��Z+�g�B�J�v~]�E��9�m>���9C�5p	�[[�c���Y18��$��e���~�-o.��@6#l~�S����kR�{�����yv���M��s��WR������M���k��R�)	������Zf���Z�Htr�3(yIKP^�b^M}��0�0�������r�Z�!H�TGi	�	�����|�q�4�
:}_m�hJ�&�Z"�m�5��?w�����?�&�S�[xJ��s��y*)]{ZB����D���[�v�D�rZ������t�#�S���Vr�*J����=�����	�41��y*w��\��C���c$F�6��Aj��b{8'��$,�^qsIS�K\9��k�&�m��PR�Bt	,�$�<�� �Li����t���Y�T�����*������,+���`n]�����%����Ou<�6����l��M�_�T����S��U�p�gwP���Iy�K�N��lFiRs,=��5�9w������#������w�m�O��F	|����/�(������K�A��9<xz��)��f���HVn���S� ���r[��J����Q���Z���Y�����:F[�{f��u���eM��
�2 -k���A]�~(	BV��Dt�<��G
�uYy��J�T��9KE��]p���yS
��w��pHu��u�"�	v�a�v�v�y�Dz+��]��u�s��~���"�^%�]����=�@/���wN���e>^z�
K��i�:�*�\��B�+��RIQ���kE	���K(2�A��&a �E�2rY�{�N���
�QM����	+������Y�x��GK����t��_P��rK���f�e?0j���)B���0�p�_���F��W���w�/���=�a�^}��;�J5I{B����'y�+;>Z�1���}��^�1����Na]��>��,����hi���v*d9X~��H�����)���xu����t"�c��|���p���W���-�������K����]�W��NF\|LI�GN�)���^6����\G�W��+�N��7�qa��!�&�N�.��m���r������e�$EZR�y�����f��x���U.Gd,t��-u���]�GD���v���(7f�mr�uf�qFD�_����R�t��7�)L��1�}�[��HX�K���o:�s�U
�7����>V�E�;�r������
��h)c�z�������+��-=���[�����8L�AlGB�vX-��������y`�Mu��7�9e]R+��P�q��#�|���fd�d4����Z��*#�rG^b�����t��m�-c���c����
BK	t�e��l��i�+����{��Q)����I���������"��������������j>���2uX2pFm�����/�y-;�zK��������1%o�����o+���rm
���BT�rG�q��������V��$\�����S����~,���1X����A���YR���F�Q�F��D\p,S�ou���jr��&���q���t���f\I��{�U5��j&+�W\�T �I0�1n]P�x9a����T�x�sU�]u��9�����5�U�^�A�O{=��?Q��kw�Kn��K=N�� ��6��7-������|��N*nc������s0S�.��]U���Z�q�Aos�r���R�~#4c��s����q2O��bXr������J������;�y��t�(�8z�6��L_vs4�f��-����
#<.~P��lZX1��fD����
6���Ti7�dOK��f�Z��uq�La&����������\&����d��X�z�����	��W�#�U�j�f����(9O�l�7��|���D�j����]R����p�L�A�w�������6����
��t��!h��H�������,�@��"��]cDD7
?�I>��7�<6�<�i\����N�%hh+���&�)c��������#h~7x`6���;��'��U��|c9x���R�D�J��m��#��{:e�W[���� ���6{�S��1��7;���^3������c������o�Y�~Rx���n�����l�N-3�����xz��A}<����{r��m�Cps���f�����;E:��N���T������x���Q^��}�<D2���dpX���TW
�t��gd�}��M�tW�>�/yqK�a�t�����X���[�uyf�AI��B����A^�\�����D�2�%`�K�FI����������F7s)��:/�dz�I�(�O�����\/uM+������"V��Ao��c�#F6�AZru���k	v���{��5%�d�'HVM���D�r���\�O)�Oy{1��_1��������z+�����J���T�I��.��.�$]�=�cQ�������h�����ifM��j�v>T����e�m��Y����G�oG:;)�Q8c5�z^��U��+�_5,3�6\�����}m���z�)��w
��� �$���o�`h$���HxM�u@@��������4�JK����r�������:D����eU���6�|@��>�J�]G#"Q��VZ�|/[kk���������)��;b����Vb.��ou�����=����������a�[�V��?�������]�_P}}o�H��#?Y�'���>;��S7���f{�"���� ��-f��������m�k_m@}�!(
c�������62Y��I���������;���������lloo/��V�B���kw��|R���9K %j�)$N�D�+i���*�D|&�'E@-��I� Vu��M���a6�a9��q6Jf������E�@�Y,_
`!��iO��l��%��{�p�u��CHH�q
���@��.�'J�s2
�E}:� �z�����G��}����c~J��[��[�����o
�&��P�9���[�J����yB�c��r�����JY�<��pu>��?K���'���]�3����]���vy���=��2��<Z�e=LX��F��sr�������O^�xf����Ic��G/����
���"�����{;��PN�v����G��?z��j�g_����?�$���Wy1���'�
��Ig�
�!G��dg�������,Z�h+�
�KW�js>��/n�H�FT(&�j����n����d�B��]��' ��x�����W��5��)�D��<�+vS������G�wu:��@�����������t8L�+>�g���@_MP�cD��(�F��KAY���j��f����l�~���E�R����.��Iuks<S#;*�`	�U��Gy�,��G
���WAM���]�I�)�`!����������E6��,�K���[*W+ �,<�{��~������$n� ��2�Qb?bh����q�2�����v�����N���������4"�M_)��g#��LPx0	Tkw����x�HCl�T	���/0G3X�����<(��-FT�r1>�������c��j��cE �/���b�9����]t	�}��MQ�:_�r���^����w:��w���G,�-FR��1.��}�>$�����"����&����]��
 ���������M"��\���d$�����9� ����t�~i:��3����O�Lq���h|�E��=��<��a�:� �sa���c.�i2L������s[���'����Y���Ng��I7�����ZR���t���������������C��x0��H+HM:D���NDj���|bEEK/�����O�$����<�=l��8���o��S��;��3l���(�����q�KO�t��;��&��%�T��n�3�J`������e���a�$}�x�1�-�!�������
�6a�.$��������2���i�[���'m�v�V2�����yly�(��!#TV��kC��
q��W�T���9�r���I���?>z~z����R��3�[���1i7FQ0@|(�a�}�b1/:���/����;94����I��(�(����
s���m�W�-1�zT�|�!u����8L����M@f�u�t�/.O�Ja�k/��j8E
�����#�C�qK�����+��-��� +���N@��Z�����
��>B6A^&2�VDR<]$"u�=������;K�k��Dw����UK�2�MV�~|����m�rf�Q��R����C�K�l�����)
���=0\�������z7��)�IrcP\&��V�������&q��a}��d���YeuR:���Y����V�D�|��B��d�Ku���m��u�W6�����������Vh��/��h���rV�E�T���f�������V���M*n�2�]5:?������w����
��;�����0�`�������I<��(�
�����
=a��}V(�Ej�jo��da��Nl9��,� [#��R�AY��yP=�b�(M��p"j����	h���b����a����};���`i��;y��
sR�GW~��:A&E���z����� GH�s��P"ZV��nzJ�~	�2�H�8O��m������![���	?�z���?���i�|��+���ow{<w��D������)q��x��'����-�����&!����f��|V<�b�R{����OE�3����:�lt�D�+�Ya�������V����l�7�4n;@���~4��g��7����kO+����m��;��b���R���?K��m�g>��4�����N�>�������4��xN���(�I��<�����(����H��#Q�� 	N�%,���BE(�S6����S��e���5o�m���mF�4����[�G�E�����	���0/�w	��Cs�Z�]R�$���03�i�&�a��l@���C�A�X�(����lc�p��WW}!F��K��k$.i)����>�t��sB(��:�z�)�7���~R��SC%��T6�E����c:[��2i5K�%?�rz$�FZ��Q�����l��u���	���Q��n��� ��u���+���������.O7_��,�rm�������!_���"�d���m�nz���5����E �p����nA������q*
��g�_y��F%���`W'��+P�R�"e�����]	i�d�������:HWE��X�S��F�>f""~K�������q&]/���HI�>�����i���N�M��N'���/L�|��;��l@q��%)Y��G��)>+�8;�'.��Ih
�}0��
YNj���������%�So�IE|���]��Q�a(<@W5�4/��?#���N+Z�4�m#J��[5�'^������*�T������4z�8l�JoR�a�Bb�N�=qv���}7�F���5�`�j��d�-gm�m��`�^����*%�����,[(���J�^�xA����s8���+�p4]�uV������J7c._�l�om?"?�C�>K������������D�gKu����H��e��zQ��EM�E�%46���b��h��gf ������\����0�t%cE�O���GG+z�_mcjSz]u����lz`(����U��w:G�c,G�e�(��N.�W�?�G��y����=���
�a�tyd���D��x������=z����'�}�4n�I[�����"�u�.A�2SpQb�L3'O	oPU���{%4
����Kq����$p��M�Bg�r"U�E	�\J�k-3�Y�j�J�Zs������W]��^l!�h�����������}��>vea���n2��-��F�R�JU���T�~������|2�����_��]
_�lGVY��o��4�[�|���p/�s�{9��&4������}|���]�QOB��>�y6��"r�$*�q��/�A|�(��,������r�*���X�������,��{���6�(����N������O$���P&{��� &�������=C`X1�,i�{�~�C����*�mP����y�,5���b��5���-����d���5Qc��������c�!��7���UE
�HL;x-�O��2�s�
�����MF� ��e������N~��C���>�@	2������&��)����8~��6��q���|�����z{T�%sw|~wzq����%��wK���� ~�����d���z�zT��d��}U�[�^{WE���{.b�C�"���y��}�te����blF��b�[}�g��M���(����.k�3�^�������V��0{��B(��>�e��0�9��,���^b�������gv~���O�o�M(.����L�o�Ovz;���[�?+��X����c�4G>����N�����Y0����v�.��4;O�V��n��|�
�B^������c���Mu�&������z~|����������F�a?�����d}���x�!���"5�����X~������'9K��E���.|xw�����<y��g����N�>����g�N�8~����mo?ys�/�|���7W�����n���]�`�#t�=?1�p���'=��(�mw���a��k��AW8��Oz���������o���	^����Z6ZT���6+�������O�U0�jhe�Z�ne8���_(��c��?��?�U��x��r,��\3�����6��2���o�|��x���Lz
���J"�oT�`�?��kV(���{� DEj��py����c�]����.�������3���n��.���1uv��(;3%-ju-6��F�d�(��nH4�U�1������m���-����f�an����I2�H ^��a�c��r@�u�1��(���7[�������]k"��
`���<D��j���J���v6O��Eqjo1@��_��^f.V��m�����k����;^@N������������_��?�'�����?���?��������?������o?�o��6����?�7�����6�"��rS�
#66Erikjan Rijkers
er@xs4all.nl
In reply to: Alexander Korotkov (#65)
1 attachment(s)
Re: WIP: index support for regexp search

On Tue, April 2, 2013 23:54, Alexander Korotkov wrote:

[trgm-regexp-0.15.patch.gz]

Yes, it does look good now; Attached a list of measurements. Most of the searches that I put in
that test-program are now speeded up very much.

There still are a few regressions, for example:

HEAD azjunk6 x[aeiou]{4,5}q 83 Seq Scan 1393.465 ms
trgm_regex15 azjunk6 x[aeiou]{4,5}q 83 Bitmap Heap Scan 1728.319 ms

HEAD azjunk7 x[aeiou]{1,3}q 190031 Seq Scan 16819.555 ms
trgm_regex15 azjunk7 x[aeiou]{1,3}q 190031 Bitmap Heap Scan 21286.804 ms

Not exactly negligible, and ideally those regressions would be removed but with the huge
advantages for other cases I'd say it's worth it.

hth,

Erik Rijkers

Attachments:

re-head-13-15-20130403-0708.txt.bz2application/x-bzip2; name=re-head-13-15-20130403-0708.txt.bz2Download
#67Alexander Korotkov
aekorotkov@gmail.com
In reply to: Erikjan Rijkers (#66)
Re: WIP: index support for regexp search

On Wed, Apr 3, 2013 at 11:10 AM, Erikjan Rijkers <er@xs4all.nl> wrote:

On Tue, April 2, 2013 23:54, Alexander Korotkov wrote:

[trgm-regexp-0.15.patch.gz]

Yes, it does look good now; Attached a list of measurements. Most of the
searches that I put in
that test-program are now speeded up very much.

There still are a few regressions, for example:

HEAD azjunk6 x[aeiou]{4,5}q 83 Seq Scan
1393.465 ms
trgm_regex15 azjunk6 x[aeiou]{4,5}q 83 Bitmap Heap Scan
1728.319 ms

HEAD azjunk7 x[aeiou]{1,3}q 190031 Seq Scan
16819.555 ms
trgm_regex15 azjunk7 x[aeiou]{1,3}q 190031 Bitmap Heap Scan
21286.804 ms

Not exactly negligible, and ideally those regressions would be removed but
with the huge
advantages for other cases I'd say it's worth it.

Thank you for testing!
Exploring results more detail I found version 13 to be buggy. This version
is a dead end, we have quite different API now. Could you use v12 instead
of v13 in comparison, please?
Sometimes we have regression in comparison with head in two reasons:
1) We select index scan in both cases but with patch we spent more time for
analysis. It's inevitable disadvantage of any index. We can only take care
of analysis doesn't take too long. Current testing results don't show this
reason to be significant.
2) Sometimes we select index scan while sequential scan would be faster.
It's also inevitable disadvantage until we have a relevant statistics. We
now have similar situation, for example, with in-core geometrical search
and LIKE/ILIKE search in pg_trgm. However, probably, situation could be
improved somehow even without such statistics. But I think we can do such
conclusion based on synthetical testing, because improvements for
synthetical cases could appear to be an worsening for real-life cases.

------
With best regards,
Alexander Korotkov.

#68Tom Lane
tgl@sss.pgh.pa.us
In reply to: Alexander Korotkov (#65)
1 attachment(s)
Re: WIP: index support for regexp search

Alexander Korotkov <aekorotkov@gmail.com> writes:

[ trgm-regexp-0.15.patch.gz ]

I spent the weekend hacking on this, making a number of bug fixes and a
whole lot of cosmetic changes. I think there are large parts of this
that are in committable shape now, but I still find the actual graph
transformation logic to be mostly unintelligible. I think what's most
obscure is the distinction between the arcs list and the keys list of
each state in the expanded graph. I get the impression that the
general idea is for the arcs to represent exactly-known transitions
while the keys represent imprecisely-known transitions ... but there
seems to be at least some leakage between those categories. Could
you write down a specification for what's supposed to be happening
there?

regards, tom lane

Attachments:

trgm-regexp-0.16.patch.gzapplication/octet-streamDownload
#69Alexander Korotkov
aekorotkov@gmail.com
In reply to: Tom Lane (#68)
Re: WIP: index support for regexp search

On Mon, Apr 8, 2013 at 9:28 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Alexander Korotkov <aekorotkov@gmail.com> writes:

[ trgm-regexp-0.15.patch.gz ]

I spent the weekend hacking on this, making a number of bug fixes and a
whole lot of cosmetic changes. I think there are large parts of this
that are in committable shape now, but I still find the actual graph
transformation logic to be mostly unintelligible. I think what's most
obscure is the distinction between the arcs list and the keys list of
each state in the expanded graph. I get the impression that the
general idea is for the arcs to represent exactly-known transitions
while the keys represent imprecisely-known transitions ... but there
seems to be at least some leakage between those categories. Could
you write down a specification for what's supposed to be happening
there?

Here is my try to specify it.
At first some notions. I know, they are already in the comments, but just
in order to put it together.

Extended color - any color of source CNFA or one of two special values:
1) Unknown color - may represent any character either alphanumeric or
non-alphanumeric.
2) Blank color - may represent any non-alphanumeric character
Prefix is extended colors of last two characters read by CNFA.
Key is pair of CNFA state and prefix. So, key is a extended state which is
containing additional information which can influence further trigrams.

So, if you are in some key and traverse some CNFA arc then you moves info
another key. But there are two possible cases (or, sometimes, both of them):
1) Your move from one key into another necessary means read of some
trigram. Then you create new arc labeled with that trigram.
2) You move into another key, but you doesn't necessary read an useful
trigram. For example, arc of source CNFA is labeled by "unextractable"
color. Then you add new key into "keys" array. And outgoing arcs from this
key will also be processed similarly to source key. Therefore "keys" array
is a set of keys which are achievable from "stateKey" without reading of
useful trigram.
We could get rid of "keys" array and produce some "empty arcs" in the
second case. You can imagine that "keys" array is set of keys which are
achivable by "empty arcs" from "stateKey". States connected with "empty
arcs" could be merged on the next stage.
However, the reason of having separated addKeys stage is optimization. In
addKey function more generals keys absorb less general ones. In many cases
resulting graph becomes much simplier because of this. For example, if your
regex is not prefix, then engine puts self-referencing arcs of all possible
colors to initial state. Straight-forward processing of this could produce
enormous output graph. I had similar situation in early version of patch
where keys didn't absorb earch other.

------
With best regards,
Alexander Korotkov.

#70Tom Lane
tgl@sss.pgh.pa.us
In reply to: Alexander Korotkov (#69)
Re: WIP: index support for regexp search

Alexander Korotkov <aekorotkov@gmail.com> writes:

On Mon, Apr 8, 2013 at 9:28 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

I spent the weekend hacking on this, making a number of bug fixes and a
whole lot of cosmetic changes. I think there are large parts of this
that are in committable shape now, but I still find the actual graph
transformation logic to be mostly unintelligible. I think what's most
obscure is the distinction between the arcs list and the keys list of
each state in the expanded graph. I get the impression that the
general idea is for the arcs to represent exactly-known transitions
while the keys represent imprecisely-known transitions ... but there
seems to be at least some leakage between those categories. Could
you write down a specification for what's supposed to be happening
there?

Here is my try to specify it.

Thanks. I hacked on this some more and committed it. I found a number
of bugs along the way with respect to handling of word boundaries
(partially-blank transition trigrams) and EOL-color ($) handling.
I think it's all fixed now but it could definitely use some more
study and testing.

One issue that bothered me is that the regression tests really don't
provide much visibility into what the code is doing. Some of the bugs
had to do with failing to generate expected trigrams, for instance
col ~ 'foo bar' only generating trigram "foo" and not "bar". This still
led to getting the right answer, so the error was invisible as far as the
tests were concerned. Is it worth thinking of a way to expose what the
extract function did at SQL level, so we could test more carefully?

regards, tom lane

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#71Alexander Korotkov
aekorotkov@gmail.com
In reply to: Tom Lane (#70)
Re: WIP: index support for regexp search

On Tue, Apr 9, 2013 at 9:15 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Alexander Korotkov <aekorotkov@gmail.com> writes:

On Mon, Apr 8, 2013 at 9:28 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

I spent the weekend hacking on this, making a number of bug fixes and a
whole lot of cosmetic changes. I think there are large parts of this
that are in committable shape now, but I still find the actual graph
transformation logic to be mostly unintelligible. I think what's most
obscure is the distinction between the arcs list and the keys list of
each state in the expanded graph. I get the impression that the
general idea is for the arcs to represent exactly-known transitions
while the keys represent imprecisely-known transitions ... but there
seems to be at least some leakage between those categories. Could
you write down a specification for what's supposed to be happening
there?

Here is my try to specify it.

Thanks. I hacked on this some more and committed it. I found a number
of bugs along the way with respect to handling of word boundaries
(partially-blank transition trigrams) and EOL-color ($) handling.
I think it's all fixed now but it could definitely use some more
study and testing.

Great, thanks! I also will do some more testing.

One issue that bothered me is that the regression tests really don't

provide much visibility into what the code is doing. Some of the bugs
had to do with failing to generate expected trigrams, for instance
col ~ 'foo bar' only generating trigram "foo" and not "bar". This still
led to getting the right answer, so the error was invisible as far as the
tests were concerned. Is it worth thinking of a way to expose what the
extract function did at SQL level, so we could test more carefully?

Yes, I also had similar idea. But, I think we need some relatively stable
representation of resulting graph in order to expose it. There could be a
lot of equivalent graphs. Some changes in implementation could lead to
change from one equivalent graph to another. It would be better to not
rewrite tests in this case. Ideally, we should expose some representation
which is the same for all equivalent graphs. However, it doesn't seem to be
realistic. But, I think we could at least make it stable to order sequence
of states and color trigrams. Another option I see is to expose just set of
trigrams. It doesn't have completeness of information, but it is quite
stable.

------
With best regards,
Alexander Korotkov.

#72Alexander Korotkov
aekorotkov@gmail.com
In reply to: Tom Lane (#70)
1 attachment(s)
Re: WIP: index support for regexp search

I found you committed GiST index implementation. That's cool.
I found an easy way to optimize it. We can also use trigramsMatchGraph for
signatures. Attached patch contains implementation.
Simple example in order to demonstrate it:

Before the patch:

test=# explain (analyze, buffers) select * from words where s ~ '[abc]def';
QUERY PLAN

--------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on words (cost=4.36..40.24 rows=10 width=9) (actual
time=17.189..17.193 rows=3 loops=1)
Recheck Cond: (s ~ '[abc]def'::text)
Buffers: shared hit=858
-> Bitmap Index Scan on words_trgm_idx (cost=0.00..4.36 rows=10
width=0) (actual time=17.172..17.172 rows=3 loops=1)
Index Cond: (s ~ '[abc]def'::text)
Buffers: shared hit=*857*
Total runtime: 17.224 ms
(7 rows)

After the patch:

test=# explain (analyze, buffers) select * from words where s ~ '[abc]def';
QUERY PLAN

--------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on words (cost=4.36..40.24 rows=10 width=9) (actual
time=13.718..13.721 rows=3 loops=1)
Recheck Cond: (s ~ '[abc]def'::text)
Buffers: shared hit=498
-> Bitmap Index Scan on words_trgm_idx (cost=0.00..4.36 rows=10
width=0) (actual time=13.701..13.701 rows=3 loops=1)
Index Cond: (s ~ '[abc]def'::text)
Buffers: shared hit=*497*
Total runtime: 13.786 ms
(7 rows)

------
With best regards,
Alexander Korotkov.

Attachments:

trgm-regexp-gist-optimize.patchapplication/octet-stream; name=trgm-regexp-gist-optimize.patchDownload
diff --git a/contrib/pg_trgm/trgm_gist.c b/contrib/pg_trgm/trgm_gist.c
new file mode 100644
index 178f073..f2b4a17
*** a/contrib/pg_trgm/trgm_gist.c
--- b/contrib/pg_trgm/trgm_gist.c
*************** gtrgm_consistent(PG_FUNCTION_ARGS)
*** 401,418 ****
  								len = ARRNELEM(qtrg);
  					trgm	   *ptr = GETARR(qtrg);
  					BITVECP		sign = GETSIGN(key);
  
! 					/* descend only if at least one trigram is present */
  					res = false;
  					for (k = 0; k < len; k++)
  					{
  						CPTRGM(((char *) &tmp), ptr + k);
! 						if (GETBIT(sign, HASHVAL(tmp)))
! 						{
! 							res = true;
! 							break;
! 						}
  					}
  				}
  			}
  			else
--- 401,424 ----
  								len = ARRNELEM(qtrg);
  					trgm	   *ptr = GETARR(qtrg);
  					BITVECP		sign = GETSIGN(key);
+ 					bool	   *check;
  
! 					/*
! 					 * trigramsMatchGraph implements monotonous boolean
! 					 * function, i.e. false positives in "check" array can't
! 					 * lead to false negative answer. That's why we can use
! 					 * corresponding signature bits in the capacity of "check"
! 					 * array.
! 					 */
! 					check = (bool *) palloc(len * sizeof(bool));
  					res = false;
  					for (k = 0; k < len; k++)
  					{
  						CPTRGM(((char *) &tmp), ptr + k);
! 						check[k] = GETBIT(sign, HASHVAL(tmp));
  					}
+ 					res = trigramsMatchGraph(cache->graph, check);
+ 					pfree(check);
  				}
  			}
  			else
#73David Fetter
david@fetter.org
In reply to: Alexander Korotkov (#72)
Re: WIP: index support for regexp search

On Mon, Apr 15, 2013 at 05:53:41PM +0400, Alexander Korotkov wrote:

I found you committed GiST index implementation. That's cool.
I found an easy way to optimize it. We can also use trigramsMatchGraph for
signatures. Attached patch contains implementation.
Simple example in order to demonstrate it:

Before the patch:
Buffers: shared hit=*857*
After the patch:
Buffers: shared hit=*497*

Neato!

Inside the patch, s/monotonous/monotone/, I think.

Cheers,
David.
--
David Fetter <david@fetter.org> http://fetter.org/
Phone: +1 415 235 3778 AIM: dfetter666 Yahoo!: dfetter
Skype: davidfetter XMPP: david.fetter@gmail.com
iCal: webcal://www.tripit.com/feed/ical/people/david74/tripit.ics

Remember to vote!
Consider donating to Postgres: http://www.postgresql.org/about/donate

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#74Tom Lane
tgl@sss.pgh.pa.us
In reply to: Alexander Korotkov (#72)
Re: WIP: index support for regexp search

Alexander Korotkov <aekorotkov@gmail.com> writes:

I found you committed GiST index implementation. That's cool.
I found an easy way to optimize it. We can also use trigramsMatchGraph for
signatures. Attached patch contains implementation.

Good idea, committed.

regards, tom lane

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers