WIP: RangeTypes
Ok, I have made some progress. This is still a proof-of-concept patch,
but the important pieces are working together.
Synopsis:
CREATE TYPE numrange AS RANGE (SUBTYPE=numeric,
SUBTYPE_CMP=numeric_cmp);
SELECT range_eq('[1,2.2)'::numrange,'[1,2.2]');
SELECT range_lbound('(3.7,9]'::numrange);
SELECT range(6.7);
SELECT '-'::numrange; -- empty
SELECT '[1, NULL]'::numrange; -- ] will become )
SELECT '(INF, 3)'::numrange;
I haven't completed many of the other generic functions, because I'd
like to make sure I'm on the right track first. The important thing
about the functions above is that they show ANYRANGE working in
conjunction with ANYELEMENT in various combinations, which was a
significant part of this patch.
Here are the open items:
1. Generic functions -- most of which are fairly obvious. However, I
want to make sure I'm on the right track first.
2. GiST -- I'll need a mechanism to implement the "penalty" function,
and perhaps I'll also need additional support for the picksplit
function. For the "penalty" function, I think I'll need to require a
function to convert the subtype into a float, and I can use that to find
a distance (which can be the penalty). That should also satisfy anything
that picksplit might need.
3. Typmod -- There is still one annoyance about typmod remaining. I need
to treat it like an array in find_typmod_coercion_function(), and then
create a coercion expression. Is it worth it? Would typmod on a range be
confusing, or should I just finish this item up?
4. Docs
5. Tests
6. pg_dump -- should be pretty easy; I just want to settle some of the
other stuff first.
7. Right now the parse function is quite dumb. Is there some example
code I should follow to make sure I get this right?
8. In order to properly support the various combinations of ANYRANGE and
ANYELEMENT in a function definition (which are all important), we need
to be able to determine the range type given a subtype. That means that
each subtype can only have one associated range, which sounds somewhat
limiting, but it can be worked around by using domains. I don't think
this is a major limitation. Comments?
9. Representation -- right now I store the OID of the range type in the
range itself, much like arrays, in order to call the find the functions
to operate on the subtype. Robert has some justifiable concerns about
that 4-byte overhead. Possible ideas:
* Forget about ANYRANGE altogether, and generate new catalog entries
for the generic functions for each new range type defined. I don't
particularly like this approach because it makes it very difficult to
define new generic functions.
* Somehow fix the type system so that we know the specific types of
arguments in all situations. I don't know if this is feasible.
* Store a 8- or 16-bit unique number in pg_range, and store that
number in the representation. That would be pretty ugly, and limit the
total possible range types defined at once, but it saves a couple bytes
per value.
* Try to somehow mimic what records do. Records use a global array and
use the typmod as an index into that array. It looks like a hack to me,
but might be worth borrowing anyway.
Also related to representation:
* Right now I always align the subtypes within the range according to
typalign. I could avoid that by packing the bytes tightly, and then
copying them around later. Suggestions? And what should the overall
alignment of the range type be?
* If it's a fixed-length type, we can save the varlena header byte on
the overall range; but we lose the ability to save space when one of the
boundaries of the range is missing (NULL or INF), and it would
complicate the code a little. Thoughts?
Regards,
Jeff Davis
Attachments:
On Tue, Jan 11, 2011 at 01:16:47AM -0800, Jeff Davis wrote:
Ok, I have made some progress. This is still a proof-of-concept patch,
but the important pieces are working together.Synopsis:
CREATE TYPE numrange AS RANGE (SUBTYPE=numeric,
SUBTYPE_CMP=numeric_cmp);SELECT range_eq('[1,2.2)'::numrange,'[1,2.2]');
SELECT range_lbound('(3.7,9]'::numrange);
SELECT range(6.7);
SELECT '-'::numrange; -- empty
SELECT '[1, NULL]'::numrange; -- ] will become )
SELECT '(INF, 3)'::numrange;I haven't completed many of the other generic functions, because I'd
like to make sure I'm on the right track first. The important thing
about the functions above is that they show ANYRANGE working in
conjunction with ANYELEMENT in various combinations, which was a
significant part of this patch.Here are the open items:
1. Generic functions -- most of which are fairly obvious. However, I
want to make sure I'm on the right track first.2. GiST -- I'll need a mechanism to implement the "penalty" function,
and perhaps I'll also need additional support for the picksplit
function. For the "penalty" function, I think I'll need to require a
function to convert the subtype into a float, and I can use that to find
a distance (which can be the penalty). That should also satisfy anything
that picksplit might need.3. Typmod -- There is still one annoyance about typmod remaining. I need
to treat it like an array in find_typmod_coercion_function(), and then
create a coercion expression. Is it worth it? Would typmod on a range be
confusing, or should I just finish this item up?
Probably not worth it for the first round.
4. Docs
Happy to help evenings this week :)
5. Tests
Same. What do you have so far?
6. pg_dump -- should be pretty easy; I just want to settle some of the
other stuff first.7. Right now the parse function is quite dumb. Is there some example
code I should follow to make sure I get this right?
KISS is a fine principle. Do you really need it smart on the first
round? :)
8. In order to properly support the various combinations of ANYRANGE and
ANYELEMENT in a function definition (which are all important), we need
to be able to determine the range type given a subtype. That means that
each subtype can only have one associated range, which sounds somewhat
limiting, but it can be worked around by using domains. I don't think
this is a major limitation. Comments?
As we get a more nuanced type system, this is one of the things that
will need to get reworked, so I'd say it's better not to put too much
effort into things that a refactor of the type system
<http://wiki.postgresql.org/wiki/Refactor_Type_System> would make much
better, at least right now.
Also related to representation:
* Right now I always align the subtypes within the range according to
typalign. I could avoid that by packing the bytes tightly, and then
copying them around later. Suggestions? And what should the overall
alignment of the range type be?
For the first cut, the simplest possible.
* If it's a fixed-length type, we can save the varlena header byte on
the overall range; but we lose the ability to save space when one of the
boundaries of the range is missing (NULL or INF), and it would
complicate the code a little. Thoughts?
Probably not worth complicating the code at this stage. KISS again :)
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
On Tue, 2011-01-11 at 11:13 -0800, David Fetter wrote:
3. Typmod -- There is still one annoyance about typmod remaining. I need
to treat it like an array in find_typmod_coercion_function(), and then
create a coercion expression. Is it worth it? Would typmod on a range be
confusing, or should I just finish this item up?Probably not worth it for the first round.
OK, I'll block typmods for range types for now.
4. Docs
Happy to help evenings this week :)
5. Tests
Same. What do you have so far?
Great!
I think the best tests would be around the ANYRANGE type mechanism to
see if anything seems wrong or limiting. Particularly, its interaction
with ANYELEMENT.
7. Right now the parse function is quite dumb. Is there some example
code I should follow to make sure I get this right?KISS is a fine principle. Do you really need it smart on the first
round? :)
Well, it needs to be correct ;)
Specifically, I think there will be a problem if there is a multibyte
character following a backslash. There may be other problems, as well. I
could probably get these fixed, but it might be better to follow
patterns in other code. I'll look into it.
8. In order to properly support the various combinations of ANYRANGE and
ANYELEMENT in a function definition (which are all important), we need
to be able to determine the range type given a subtype. That means that
each subtype can only have one associated range, which sounds somewhat
limiting, but it can be worked around by using domains. I don't think
this is a major limitation. Comments?As we get a more nuanced type system, this is one of the things that
will need to get reworked, so I'd say it's better not to put too much
effort into things that a refactor of the type system
<http://wiki.postgresql.org/wiki/Refactor_Type_System> would make much
better, at least right now.
Sounds good. I don't think this is an actual problem, so I'll consider
this a non-issue unless someone else has a comment.
Also related to representation:
* Right now I always align the subtypes within the range according to
typalign. I could avoid that by packing the bytes tightly, and then
copying them around later. Suggestions? And what should the overall
alignment of the range type be?For the first cut, the simplest possible.
OK. It's already about as simple as it can get, but might be fairly
wasteful.
* If it's a fixed-length type, we can save the varlena header byte on
the overall range; but we lose the ability to save space when one of the
boundaries of the range is missing (NULL or INF), and it would
complicate the code a little. Thoughts?Probably not worth complicating the code at this stage. KISS again :)
OK.
Regards,
Jeff Davis
Updated patch.
Summary of changes:
* More generic functions
* pg_dump support
* remove typmod support until it can be done correctly
* added some tests
There is still quite a bit left, including (numbers match up with
previous TODO list):
1. Generic functions -- still more work to do here. Handling the
combination of continuous range semantics with NULLs requires quite a
lot of special cases, because it's hard to share code among functions.
Even something as simple as "equals" is not as trivial as it sounds.
Perhaps I'm missing some cleaner abstractions, or perhaps I'm
over-thinking the null semantics.
3. perhaps fix typmod
4. documentation
5. more tests
7. better parser
Regards,
Jeff Davis
Attachments:
rangetypes-20110114.patch.gzapplication/x-gzip; name=rangetypes-20110114.patch.gzDownload
� $0M �<�s�6�?�����c�vb�<��"+�.��Jr�����HX��"u$eG�����$;N�zo�eZ�"���~���6�w�,����
O���/�8����o�U��vvv�d3�v�~f�w��G%A�9��)��7YDqFY�p*/�q:�������}��"/R�9���` ��?�_<��~G �%���s?������
��3 �����xP�a��<��������O����A��E�GI�?��,���� �M�'���+J�y{�gS.VL
����.���/�L���4�/Kc���(��0�6W/����S|X�~.�����w�7��.�w��0����D����A�`�|�����5Bl/����[V���O��a�WE(7�O�=�����/��^F������������}���30�O���t� K��n�E�7�����Y���L|,�l��]3t�f<�&^����������>x3 B��")�I,�?��!��q��r��9b�c5W�����k�8M��B>R���Y�jx�P&�������@P�X#���n�H�����"�����2`\�����>X�+��mi�7��s����w�w��A���������WG��������t�������)O�#�����h�-��� �7��^�����������:9|�'{0����z�7��F k%�D0X6T�`��
��n����Z#���6Ba��V�@H�9������6�M?�A~n0��0��f�b>O����$�/�����W���z&��0�v��2���s�&���{�����s��p����[J|���q:���`oa�y�F����~C����A_Qy�`��?Vf���k��m�Xs��+C~@����gbxe���A���I��(]�}\9����W���\������4K�0���^������!�&�_lbC|`~�`��%8�R��oa�e�vQ�j���'�����S�^?E^:��+\@e��'i~���� �Pj4@*�N���_,fh��~���O}���(A~!�I���N��=l�x1�9@�9=P��_�1[�<���@2�3P�
�j
�[�Ja��8$.�F$4L���`�������MSM���i��20�*��qy�+O�d���I �!���^�LA����~#����-/Hz��q�m-�\�!��Kn������^�JE��.P*#�[���,%6�o�O������Q��1iu�ZM� \F$��#H��GX���BOp`Pa��sH�x��mp���sA�z�C��`GA��eaA` �$�!5}�W��B!X��R�N
�T�H��z�
�jO�R������%���!+�6�g�����eO��.;�^t��:��`��}���l�}.�R=�����z�^��������/�0?��{�k��2���6~���)q�s�P��S����3s��|���j�D���������*!i��_����
_��1f��q� ���Z��a�r�^�S$`�c���F_���&����t�_�&<s�r��
js��T ��@���\�&|
���(g�:�3D�0�W+�?�F�?��������}�D�w�Q������B�t��� �T8�z�4�k�b�K�����
u���1�6qD�Q����Z7�AfB�
f��Y�]��p9�w���?����_��$�k �]�~�lR}y
�f �o���%��C`%l;>t�OD�{\D���+H�Q�G �7�$@t�#���TF�E�[�$
�}��=9P�����gi%kP6O7M���3��?^����sc�cX �@��X���@4�!�A��{wQq�����r��O*@��w�g]����*rA/��k���w �JG"S1x��lS����h�X(�>�����1$u9�?r�u'�"�����T�u����G��egLIa��rN���w}�����V��Ab?P�*#�)P�M�O���XT�(g��tD���S\���"�Sv�%�0M�l�h�pW����R������fJp�.�SXW�����1��Lv��GI�A0���!"��C�%r�
3����b� ���C�������3����X�����:9t���/g���9���?G��;��B'Z�{���a���]�R����)�L�g�� �3�s%�1&K�q4�D����6b����������_�4u�
��Am ��|R"Q��9`�c��;������Q��-�ux7����XK�������<��
ze�������b1�(�X
a������Z���O�H;�V��������&��Q��7�3l��y�Bn�;��@6u��Zb"�`l|
6��L��l�4���&���l\�;I
;�3�� D"������C�A7�� (h� �f�)4}H����
p�Y���-/��Bz��_���7�� <:�� �)�&p�K�ibI�K�R�7 ��bAt�����
{�:��J�1 ����1J�-�K��U�/�%�-�j�
����"&A1�\A�@�?�3���y�g���K�����h~��G g�'����`�]��gB*9�DLx��1p�Hg�j����E��>��9"Gn���jv���`��r�g��O;^�^t��M����������w�7�������5C�&���U��e��4�:E-X�qt�L�����U:���T��P�DW�!�-��@@��E�3�U�<Uc����+�k-xI-�J!Mj�$��~�dS�BKJ�)�`�7E����C0�k�PF����+,�A���<�5�p����S��@�@�!M��;�^g�m����Au(1>�:�w;���;�
���f%�����?������E����d�a�V�U {�5d�U�����
��p�:M���u�R�O�9s��,f>��0���p��IZ�:q�������K��i��R N��J�+�;�J o���Y�v�l��U�Vh�v�0���=��z���@�n�E��10���(*�74 �S�-�d3��A������\��_bh��Oi��_��C�z�(�q2z
�c���suB���BBZ��x��U(�y�����U���w��1c�;C��I�c�O�����j.�[���\�!���H�,r�p_1Ea~�p
�o��P��(���c���
�"U�yA_�#*�N�H ���@,G+���$�-�cP��1F(�0��b��Q��sq�FX����E�����1�.s�P0�0}!'�j�1S=���Z@ ]d����}�6�a����b6[�4�
�����x��� ��./��,��
^����&��������?o���*�AF>C��xp6�;��fb$h�����8p+������wcH��A�y����*�����@"�zy�� z0�;������<��j����x�
���: �r\#�UI�>���=3�c�&Wq�������$�!K�NQ��T��5 ������<?���
�O�)�Z!�]�@qN��>�����J����e�))mh�����*���+��G���C�'��\v�)9[�m��jY&dG_ @i����$~b����L�u�z��ec2�@wm����������N0<��&��<�26��%g ��+�^�!l>�ObF� p���gC��Z�)� ��$�x=�5�L�ei+��~�JK��\5� u;��iB�-:���l!�N��5�5QVN����%I�]bh�ab-�'LWe�����q
AP2o�%%G�BQ �P�L��:��O
�fe��������FE�V!+�%�H�]�J�����a�
n�n�T@*�[��1����f}�bo�����k��=k'_��S��J���` ���]�nU��u��/���}�=���%E%�c�/
y�"��2�� ���]!�9f���tp9&X(��v;h�w����>���<�
|
lMw
y�e@��F'��V���2c�����,y�x�rjHqjjh����P�����(�
��%�������om�M7��0'M�%�w� +�j'e���I}�����g��I�`#J�GT:c�����l��Dj��c�6YZ�x=+
���$�
�'3�Gc��+ N]eQ�Y�p�>G#��r��{&�F�zN����D(��M$���$��$��&����!^�)��� U��v��v��~�q��cC���1M�Q�=��o��0�f��j��|Q��iU����|
����;�Fr=RUdC�Z�V�`U���+���Z���`��q5X9Ro�,����Z����J��F_��#��w��E:Q������6G��-
D��MA� ���1h��c�M!��>dY4����v���e�����?1e]�B0�%�y�� 2^�c��H4����M�'N��F���G��fo�De ��[.Q("��z�!�E���2���M�E�����/.|�]��e���F(3@m�Ps�"�T��y"
�K�,o��F���v ��E�i��Gb�Nw�v�~������z��o=�~���p����:><Xs��Rv�q:���(g�[������n�<�3�I��Cy
>|�E�\��_���V@��gS�i��S�1NV���}��o��0�y������+a�5@�"�U�����Ci<g��v6]��Q��3�3���B�����s���h�*���m���=�����<����c�5o�7g��?�9��at������BJ�1�~�����b���E��B��{A���b�f.���U�$����b�����
^2n�C���s��T�
Yi$�I�u~��D����yo.�|�k��^[��r:w����� ����t������^r��5��x�P���9��`���B��y�>��{g�L�#&{&{L�'z�r��� �tAF1y�����g?o�R`_(�~�b�WEp1|����s�����q��y�H��p�f
��.H>�g�a������������?�6k���>����+T�Y5p���� D�Z�x�p��5�O�}���������c���ll�^!?�tT�����7��HK����,�2���:=��j��������q�.�����
�4ny�"���A:_"C��*Val����A���D��!|���}��,���WN><����� ��OU�=���\2���7x���g���e���ZU����\��Y�ooz����j��mT�A�)��O*��Z����U;5 ���/���������� �&�]9t���
:�C�k
�;�^u�� +�tLn�s�*��@~+��:>-Z��6���J��
���X ���B�:+���}fR�V��{P����mx4�C�]V4����vR�����h�",C/c<���2x�v7i�
�]��WUh�g��$����=��g�Qiu\G�{.����C�K����R� u�/�>�0l��'����J��2
��-�������)l����,���
88>:p��������������4����p,m�9�_{��7��A�����z,nE4~3��yx��n�����1�q�Q����p�&��H�|H��9 L��_��u��K�Y����c��m;�3��QwXrc0�$R:�`k���
;L����,�Vh����}pZG*!$e*��t68G� ��zW��;4���q�[�`�����a������X�4�����/G!Q�������
1<_�A}{���� �h3z�M����]����������<]U�_%$���;����`Io�m�A~[?��=�?<BD�zD��Mz�[�����2�� >���g[�Z`h.S�s�Mo�D�#|+�\(D:�[���]������G_.�c���'������$oE�YAH���y Fk:�r=�@����I�T��e��(����&�'�K���X�N���W�{�����
���r{��B�&�3d��-�W�-=��u���o�����W��������]�0c�����s��c(��_�a��^(�g��U�)do����4���o�n�F�Y�+�k���,��6{[Mu��]K��_�WG�h�[JTD*����o�� @�)����mv+K$0��0�\]�G�7��`��q-/�@�X��/u����1[��
�}<g���vMM���Q����=d���2�
" E�:�sZbz�I�,�� �:�&���yx�����*�W�D =b�I�v<)��v���l'�i;R��W��V���;%{���t������J�0Sr. � uF��a�Ee��QGq�J�C[��E��()��,O�f��u���:��l�^3�jF �:���v��O��l�!�jB���J$����i`���/t������U��W�@�4 �[co����C��#x
kbQ����1mp�u���{'���<�[N�r��/6@��Yt�A����}����H���h�����`�q��"t�
u�o�$�M��C �����}c
�g�UPG���I�c,Wr�l����q����E��2E4-�"*�QgPm ��r�'��y�����qj�E":���`���
��eP����x�.Gi��v�����1'4a"9X��B���AC����QI26���_x����bi�EJe��[-��S�F��Zb>OOB:O�Y�62�����������[�Z�'c�H�xv��'9�X�J1;�t
���-!��ai���t��:latp�6H�.R���Yy~����p8������ r�����B{�/�[��X���'O�
�[Q��7�5�4��^+m7��:��)�y����;��
�U�[
��VS���0�?�����8"m))�t����%%s�tN^������[<�.��_��N������`���PzuV��{d����X��_ S�&F����c�w�����I��f�]��a���?XY�M��`W8E{�ZP�X��c��+�������V|x����_���l���d����yw���Q#yD���m����jy���TW��B�+c��ld��#k�V�>������t
G'�oL��;��}� [7���d]���3�#�����P�tB6�?��_�C� ������K��O�v9�
L&G5���&z!��- �+%���nz��(�#w�=uO�"nV���ODW)��Zce:F�aJ;)����D m����\;^W����SM�2���jj��.Z������N]�G�`�Scx����?Q����g_�$�r=��>�$��L ��q���t;������V�+����~����I��lk��d���=�.��4��a�;�4^!v`���p>P��0�3'�,����V9<�j��5e#���5mvX��
����i�0�����<���^��#N�q�m)���]Kt���{!���=�i8dS�kUV�kw4�M��n�1�,#��Q� s:��$"����Y"��%G���H4��uiC��X��V E�h��3��� ��a��h ]�g���2����<jT��UmOP���h����{Bz�:, Vc��������L��BV^V+ua�,R)bV���*6�?(K�����x�(r�Dz�?bCM�%n�`��~�h�&gR��C���3��|O�'^8����a�M\������'��Q������������0���b�q��w���f�u�`�H��-|W����4w�"��}�����`�d��N��M�����%���sLC9���4���|0���|���"�c���:PJ���8���}�7Lubm�GVI����4��t���N��{��O/f�X ��D{8���0Qn�M3��i�E��I/^��u��X���� XD����ip|��+����J��J�K�Z7#�����&������i��+��Lzt�����R���(>+���XP&���Wj��
��}���
������^�T9#�����6VBEn��MWb����� �|�=h�e�4����H���~�|Zx�06J��)�5�(����5�!E��s�.]*8'Y��� ����g?pLes�.���^������������ ��HJ��F��S�"�#�O�9�f{�52�\f ���2sq�����������*gd�W��g�a��G�e����g0�`:V�t�?���y���p������D.��H��s9�8�e��1m����zz�&��oyvzq�����.��]L\zn����hi���a�On��m��W����u�����x�P��L4��[��M|����48;4����hPOOYZiT�Ea<`�x!R�S|���p^��c���-��l{!NPrx���"�)L��:
�V9�/_KE^�������m��'��U��m���6:����n�eq1��"��#���r��^�^����`i��"���"a<Z���4JbI��.��1��@��q"S<� ?8� �=��o��^@���p�1{,y�<�s���h/2���>K"����`�Z�31mhS�_�H��>����kNz��#�pY �%�������1�DYY"���'�o��0{^��O���8/eT��w��:]����8:I���8yC�R?���`K�%- ����
C�+�8�'_��8*V[��.�%���D_|�1��y%Wc��S�R< 0���9�� �hr�^�����X�R�����y���Ig�)F>e�^�x��n������3�1{g�y����H����[c02������p���HUH��U��X�D��h�P��4��N
�/}��TRI��^<�-�`<����msw�9{����Y`0p����O�y�>o_uN�D�!,�4�/F��P�p~�e3B�����d*0��4��*�>�P9���7���8?��}���Fr���z3�_fs
K��w_����b���L��_��&b��M�@���b�; �G��Bq�4Z������N�z�F��rj����>l�*�����I{��?Vw�����O�?�?r���.���9~��O��"]F����{�.�Ob�]x�;�����|�e�[�!g�} ��Z��V������M��VRm\��)��b�Z��-6T���_�7����s�?�t���� mk�)����f���k�_����]�~�P~p+����w2��7�M�^�'���~p��>� S
�nd"#)��
�k�x�I���'�?;L������l�Z���a����O��C���#wd��7g�>�V���8�?�v1�����`��)���P)0(>=�1F���X��?�
��M>�TO0O�� �� ?Sg�����g�i[���T�Ju�T�JucNc���g��ts�I���<����H��b�t��q�q�Y��d+R��)�u}���2�.5Uq��,�����F�,/�F��i��(���r;��QGy�0�^&��+�?�� y@��*�aJ������@z8�h��^��R�zJ?��o���0B
�:��`D�Q�HHD���l%�����Mc� ���
��5��xZ`���e�F��
��s�����5�J6���P�4I�XP�QI��6�F%�qq���� �4�-���� �(H�Dw
J�-3�S�kld��j�l�?���;~v�ce�g�J����N�H����L�\Z��O�����J-v�Y-?w?e7�LU�!���_�5��8��/�P�X��`�z8$�Y�=E����O�f�`�
H�L��y-����i�J��c�#E��.m�:���I���)f��S������^���v��W�o��r���"���rn]���~�_������E��
��hp��_��;�1#Y=X���p�3���Y3�d������G�b�=N��b�LYL1}�����1i��9������Z��q�a~'(j}4�5��`�\�9������|o�1��c{��:�L������Hw�j��"���8����c��y���F�je"�FT����C�L�YJ�����s��t{k�~��O�W������W<��7M��� s7�-a���k-���iI������P2���T%��YV�
���O� >$J������=����������p6�AFnY_ F�m����A�(�uo?n���1��\�.��m�UQIL��A��7��<`�h_rb�@qQ��ZP\$Q��A���F\Y;��8�$�[�,���*;fRg�����<#Cdmh���E�Tg�������V���7������@�n"�������������>���8�ZJ ��� ������4��`��:���B�lX?�f��.9A��.�����r;1W�� O%�EC
'��>������f�B�aM�^Q��4�U������� ����6d���uG�7�r��6������bk�6��z��qA���R����TL�,�"�}f��j����8Sl �pf���Eg:g��PgRMU�i�P
�v���iC)�!l�o0���}wK$�u����Q?\�t�� ��PY��iuP;[�&���-Nj��x����@.�I-��_J"�jK�J���Z\P����i�k�;�=���������7N��cO�qA��X�<�>���������u ^�x(V�X��qjF���br ��_D����&���9������E����D���/��b��b�{7
gn)�V���H a�\��$T�}��W���"�w�e��9��W�����M��s��PHu�{���r�~�lnl:?���>l��S������]e�)+e���Qq�����~
��"�2����|��p�q��oTOL�|�*����(|��O�nV]����.g3@�T� �b��x J%c_k����M�fV �%�E������p6�5����V��'����:4�
LC2n����� ���Y=�E<�t�cNA��T�b9�b��#��s�����1��L��e���������f�}��[�^l�����7�2��aKg�?��'���2��� �e�A4R�|8�gk��NIiw.����{\wv0�������M������`�r�e�%����qA�=��H��X��xc�T��N��NQ��6c��I�l���x-�v�_�5`��u����@W4�kA[��-
B�'�e���9�f9n��c j�a��#
��<�8�.}�(j�_�v�_j����o���O��6<��kz�m�/�C�v �7��/�h[#����\�A!P���h6���0J�r�O��y9��H��0C�i'v�U�G��X��7���Yyc7Y���u��4��-�/q��������?����^���r��V�����%��������
��&�$����������o,�b��l����$_���@h�
��F�c�����h�M������!-�i�hK`�g��������Z����Y��1�~<��;/}L4��@�D/�/�
&/���~�U�z&�q���Dy�>�Q�e�I'��E�� ����m��C��e�����L�6����e���g�[�?��F��� ���)��b��#(������8����H�x�T�����#�{�����hl,���/���zY�}�A.��i���q*�Zx<�����p. ���ics�c��
�y}��v^;���������{Z@���i��V�r#��_C�l�U�����x,�F,tV��@g��/�>��7�]����u��Zj1Vk�i|m�MA#���AV�^$�
���6��
l�d�Y&���`�Y��J�>�`uEV�u9���&>�K��W-��C����J{��>T��)5�,�vcX�$�>���@�M�vZ���|�M
�R.+sFj^M����g�O?�����^
T^W����*����:���@,��~VW��]����Ysr������W��Q��"(�����������]V�3��<]�����P��l��0��(���s�P���p�|��]���T��2� ���p������kt��:�Go��A��xZ����}�~��.����� r����3��P�]h����qK��>}�����0IQ�1���ivT?d\�;��6[�I�n�k��������6G@D�����&j!t�P�P��Z�F�^;:����&#�<�����!���cq�p�1�uI&����WDEH#I(��G�f�!��83��3yO.�XP#3lHY0���NO�/)� #�x�����
�� ���;��c*@��[���H�t�9���K^rQ������)�"�����uP���X(0)]��7�w�=� ����q��������d^��A���BF���X��;���(E3�9�Pc����A��)�����_�(��a�������1
�4�f����`>����.����|������I����{�R��#fh��C�v_�_=Vpz2��d��S�����~F2.8�i��+Jd����n�M�5��+��8�y�o��%���[����ZQ�4���'��K��f��<��I�y�D�\�+�����S�q��N����=Z�D{MZe����F���h�}tH�y��!���p���n�=���B���W������w��CJyK{��sa����+t����<B�����3�_�=�U���1�����n~YM��=��S�7I6��$��.��� &cS�����X��k���k�w/e*�����u�n�������_���p���D1���T�����w���`>��9~3�2�c�(D�I� ��gc;�*��p��
4J r�:���X d����z�Mj��m1d� �Hqf�����V6U�s�%��$���]
�L���]�2���E�������3�^,Ni�(��b|�����+���lu]�k��t���X��N�+�5� by<Y�J�
���SHG�Yi6�\���.������+���/5�q��%�U��K(g����U�4[�O���������m����/T������VO���8-X�����R�[��$�W���#P�O�!���j-��� ���xm$���G��B�g�&�u���������h��8D��F7�_��W��X�(�sJ*�"���l1�N��;�l��3cT����������Z4��P� �I��KOhb5�*i���~��R�_��� )��u�������0W�t�^��F���B�C� �� u�n4��v_�h���I���h+Q#S��;I�?;�7a��M[?�y),�%$,2�hv�������@���P��~���e���B�Q�x#r�����x9H��������w��x���u��e���Y[-��]������*�<����l5Z�V��k�S"2����P�1(nU���)�����L�5Uu�{�k�z��:06x�Z�u��!l�x>�H��7Z��h��l��,���v���$P�GJ���� AE�*;k��`��+c����wR�c;��4}L���AUO<�7n@8 |�sR f���f>�I}���Q�:���G��K� 4��+P~��Z\o��8�D�� `;���%
g��S��?VfV�Y�U�Y���v�\`�~�E����g�s���_����]����#L�=�4��]q��2��J��L^=�����y�y�]������S
�#��=��z���-�t���}+� i.|��i�B�<���y���U�_�~��Eb��p������s��0�(��B��GQ7X�z��B�
���\l��F�:�DU����rt�sb��
��8������(9l5��QS��W��,����;'�wO^����m����*o~��������6����:�=���\/�s����-�N+��l�-
���O���/t�Wq,�+����vw��_�������xW��4B�3D��!~��:���t&�0BO�����p�s�x0B��C�2�{M���n8���:�������i[��cx�k����@�v�$%� �S�I_�orl�����Lg/bK#".�!l��1�����_�E�H�I��_�{qw9��:�l�����~���L�_��>L��� ���}�kKL��.��:�5��0�Y����_|��w�S�����I���!����d#_2�GFK�������7�V���2(C��8�S��#B�������o��H?9�sr|&wL�y�����J�u������O0�g�r�Sy�I���7I�W%�&9Ym�T�7���v:��m�'��U�G�U�Or���#�[[`r\d�;y��&���,4���@[�N��^;R������;�;g�k��dRO7t#�O����@n�����/�QR.�_�)��j
y�ZE"F�'����,d����
+8#��B�`����t?���eW���f ������1��5.���B���{���~v�!����`s�Y_��C���&��,y���d2������0�0-���.��o_uqh�_���Z
�_�1ak�����.si0�N.����z�������AI�Pg��z��@�(�N-�N6?=��������
�xY?<����1�i���f��y��>�8m�P�C���:���"