
"Noah Stein" <noah@acm.org> wrote
-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Andy Little Sent: Friday, October 22, 2004 6:09 AM To: boost@lists.boost.org Subject: [boost] pqs - physical quantities library
Hi,
I have been continuing with my physical-quantities library over the last year, http://www.servocomm.freeserve.co.uk/Cpp/physical_quantity/index.html and I am now seeking feedback as to whether it is worth putting this forward as a boost library proposal....
I've looked over your library a little. Overall, I like it. Having started one a few years ago, I understand how much work has gone into it. I have some feedback:
* I would appreciate a little more depth in the glossary. The definitions are very much about the mechanics.
I opted to just say what the things are, rather than to try to describe the 'metaphysics'. That is surprisingly hard to do IMO. What is and what isnt a physical-quantity?. However I accept the point. I have found documenting the work extremely difficult. A complete overhaul is required.
A "coherent-quantity" is a concrete-quantity with an incoherent-multiplier of 1. Does that mean a kilometer is incoherent since its incoherent-multiplier must be different than the meter?
No. The incoherent-multiplier is a conversion factor required to scale an incoherent quantity to a coherent quantity. length::km is a coherent-quantity. Therefore: The incoherent-multiplier of length::km is also 1. Note However that there is another constant in the quantity-unit, the 'coherent exponent'. In length::m the coherent exponent is 0, while in length::km the coherent-exponent is 3. The coherent-exponent is closely related to the si-prefixes eg cm -->-2, um --> -6 , km --> 3 etc In a multiplication on two coherent-quantities ( as opposed to incoherent-quantities, ie those where the incoherent-multiplier is != 1) as defined above, the coherent exponents are added at compile time, rather than runtime, thus making multiplication/division more efficient. IOW this works similarly to hand calculations. However incoherent-quantities (non SI quantities eg kgf, in, etc) must be converted to coherent-quantities first(N, cm) in some cases, making calculations less efficient. Examples of incoherent-quantities are length::mi, length::in, length::ft etc. IOW 'coherent-quantities' are those in practise referred to in the SI system as coherent units. Overall there are 3 parts to the quantity-unit. A typical declaration looks like so: quantity_unit< coherent_exponent<Numerator, Denominator>, incoherent_multiplier<MultiplicationConstant * 1000000>, quantity_unit_tag<ID>
the last part is required for corner cases eg: It is used to differentiate quantities for output purposes. For example in the following pressure::mmH20, and pressure::kgf_div_m2 are actually the same unit, (both 'incoherent-quantities' here) ,but note that output is diffferent. std::cout << pqs::pressure::mmH20(1) <<'\n'; std::cout << pqs::pressure::kgf_div_m2(1) <<'\n'; // to show they are in fact the same underlying unit std::cout << pqs::pressure::mmH20(1) / pqs::pressure::kgf_div_m2(1) << '\n'; // as opposed to std::cout << pqs::pressure::kgf_div_m2(1) / pqs::pressure::bar(1) <<'\n'; output : 1 mmH20 // note different output of two types 1 kgf.m-2 1 // dividing one by the other shows these are same unit 9.80665e-5 //otoh division of different units
Or is it coherent because it is part of the SI system, but feet, miles, etc. are incoherent? Looking through the code I believe the latter to be true, but the documentation doesn't succinctly explain that.
In following links regarding coherent and incoherent quantities it felt
Ok the latter analysis is correct :-), but requires clearer documentation on my part obviously. like
circular definitions.
Yes the docs need a restart. Criticism totally accepted :-)
* Unless I missed it, I think you need to add a term to your nomenclature. What's between an abstract and a concrete quantity? length::m is an abstract-quantity with quantity-unit but no value thus it's neither
abstract
nor concrete. I would guess that this kind of quantity will probably be discussed a bit.
* I believe the system is too SI-centric, resulting in this point and the two following. I would like to see the library move away from the SI units taking 7 of 9 prime-unit slots. I can envision a number of applications that could benefit from a quantities library but aren't based heavily on SI units. For example, if I'm modeling the business side of a networking company, my units could include computers, megabytes, and dollars. So
Not exactly... abstract-quantities have no numeric-value. They are useful only for dimensional-analysis. To perform any calculation on concrete-quantities the units are required. Without units the numeric-value is meaningless. IOW "I will arrive in 12". means nothing. "I will arrive in 12 minutes" does. there
would be a lot of tracking of dimensions I don't care about and currently not enough available dimensions currently to track what I do care about.
See the attached file "main.cpp". See also the AnonymousAbstractQuantityImplementation Concept. Anything conforming can be substituted, eg the anon_q1 struct in the above file. OTOH could be 700 dimensions if your compiler can handle it. Of course you will need to provide output and so on, however calcs work ok.
* The coherent prime-dimension-unit should be selectable. I don't want any precision issues beyond those that are strictly required. I'd prefer to see a system where I can specify a "coherency-set", e.g. S.I., Imperial, etc. Each coherency-set should be completely encapsulated from other sets. If I need conversions from one set to another, I can specialize a conversion template class for the two sets.
OK. Except that the SI is arguably The coherent set. There are no widely used others. The major purpose of the SI system has been to tie together disparate partially complete systems.
* I'm a little leery of the structure of of_length, etc. It's not extensible to adding new unit types. To bring up a system I mentioned once before in a different thread, how would I add length::cubit without mucking around in the library files themselves?
The current plan wiith these is that you Do just add in custom member typedefs within the of_length_<Value_type> struct. There are two versions of each. Obviously the one templated on the Value_type must be a struct, but the default Value_type version could be a namespace. However I found it considerably more convenient to make it a ' forwarding' class of the other: struct length : length_<of_quantity::default_value_type>{}; This can be extended: struct my_length : length { typedef some_type cubit; }; etc. OTOH it may be more convenient to create your own and add only those required, or use the ct_quantity raw. It is merely a convenience. In fact it might be better to put the actual containers in the background eg: namespace hidden{ struct length {...}; } typedef hidden::length length ; etc. Obviously it would be easy to replace the typedef with your own custom version. In fact I could do this pretty simply I guess. In fact Should do this.... next version :-)
* of_quantity seems a little limiting regarding conversion issues. If my underlying value type is a UDT (such as an arbitrary precision type), I would like to have conversion numbers be objects of that UDT to maximize precision.
The SI lays down conversion factors to 6 decimal places. + exponent Some things are limited by compile time constant issues. eg the incoherent-multiplier fits into a long. (eg the long template param of incoherent-multiplier == Constant * 1,000,000.) However extending this to arbitrary precision is possible perhaps, though I havent looked into it. Bearing in mind compile time as an issue too, however it may be possible using a different quantity_unit class. Personally though I have little interest in this, and generally use coherent-quantities which have 0 conversion error by design, so will leave that to others to implement.
* What's the plan for non-ICE pow()? A compile-time solution is clearly not an option. For completeness, it would be nice to see an example of how to deal with the situations where quantity information is lost.
Because multiplication of two quantities result in a particular Type the power-to-exponent has to be available at compile time for the current setup. (however powers can be rational eg pow<-1,2>(t) etc. ) When its not you will need to use a run-time type, eg with all the dimension information available and modifiable at runtime. This would certainly be a useful addition, eg a 'universal-quantity' and I may get round to implementing that. The compile time quantities certainly give good background and its merely a question of transferring (some) compile-time calcs to run-time. The current types would also be extremely useful here because they encapsulated the data in a concise way eg: universal_quantity x = length::m(1); x *= time::s (2); x = 1 ; //dimensionless if ( x.dimension_powers() == dimension_powers<of_length>() ){ length::m len = x; } //etc The data for the compile time types could also be reused. One way to look at the types in the"pqs/ct_quantity/types/ " headers is as a database of information. This has already beeen done to some extent in the rt_quantity, which has modifiable units and 'maps' the various units for output (see "pqs/examples/mapped_rt_quantity.cpp" and "pqs/rt_quantity/rt_units_map.hpp"), but the dimensions are fixed. However the rt_quantity has already proved useful. Hmm... maybe it would be fun to implement that. It might end up being the most useful type of all :-) regards Andy Little begin 666 main.cpp M+R\@($-O<'ER:6=H=" H0RD@06YD>2!,:71T;&4L(%=H:71E($QI9VAT($1E M=FEC92 R,# S+@T*+R\@(&%N9'E <V5R=F]C;VUM+F9R965S97)V92YC;RYU M:PT*+R\@(%!E<FUI<W-I;VX@=&\@8V]P>2P@=7-E+"!M;V1I9GDL('-E;&P@ M86YD(&1I<W1R:6)U=&4@=&AI<R!S;V9T=V%R90T*+R\@(&ES(&=R86YT960@ M<')O=FED960@=&AI<R!C;W!Y<FEG:'0@;F]T:6-E(&%P<&5A<G,@:6X@86QL M(&-O<&EE<RX-"B\O("!4:&ES('-O9G1W87)E(&ES('!R;W9I9&5D(")A<R!I M<R(@=VET:&]U="!E>'!R97-S(&]R(&EM<&QI960@=V%R<F%N='DL#0HO+R @ M86YD('=I=&@@;F\@8VQA:6T@87,@=&\@:71S('-U:71A8FEL:71Y(&9O<B!A M;GD@<'5R<&]S92X-"B-I;F-L=61E(")P<7,O<'%S+FAP<"(-"@T*;F%M97-P M86-E('!Q<WL-"@T*(" @("\O(&-U<W1O;2!A;F]N>6UP;W5S7V%B<W1R86-T M+7%U86YT:71Y#0H@(" @+R\@8V]N9F]R;6EN9R!T;R!T:&4@06YO;GEM;W5S M06)S=')A8W11=6%N=&ET>4EM<&QE;65N=&%T:6]N($-O;F-E<'0-"B @(" O M+R!R97%U:7)E<R!A;'-O(&)I;F%R>5]O<&5R871I;VX@=&\@8F4@<W!E8VEA M;&ES960@87,@8F5L;W<-"B @("!T96UP;&%T93P-"B @(" @(" @='EP96YA M;64@1FER<W14>7!E+ T*(" @(" @("!T>7!E;F%M92!396-O;F14>7!E+ T* M(" @(" @("!T>7!E;F%M92!4:&ER9%1Y<&4-"B @(" ^#0H@(" @<W1R=6-T M(&%N;VY?<3%[#0H@(" @(" @('1Y<&5D968@1FER<W14>7!E(" @(" @(" @ M(&9I<G-T7W1Y<&4[#0H@(" @(" @('1Y<&5D968@4V5C;VYD5'EP92 @(" @ M(" @('-E8V]N9%]T>7!E(#L-"B @(" @(" @='EP961E9B!4:&ER9%1Y<&4@ M(" @(" @(" @=&AI<F1?='EP93L-"@T*#0H@(" @(" @('1Y<&5D968@86YO M;E]Q,2 @='EP93L-"B @(" @(" @96YU;7L@:7-?9&EM96YS:6]N;&5S<R - M"B @(" @(" @/2 @("!F:7)S=%]T>7!E.CII<U]Z97)O#0H@(" @(" @("8F M("!S96-O;F1?='EP93HZ:7-?>F5R;PT*(" @(" @(" F)B @=&AI<F1?='EP M93HZ:7-?>F5R;WT@.PT*(" @('T[#0I]+R]P<7,-"@T*;F%M97-P86-E('!Q M<WL-"FYA;65S<&%C92!M971A>PT*#0H@(" @+R]&;VQL;W=I;6<@(')E<75I M<F5D(&9O<B!A;F]N7W$Q('1O(&-O;F9O<FT@#0H@(" @+R\@=&\@=&AE($-O M;7!I;&5T:6UE0FEN87)Y3W!E<F%T:6)L92!#;VYC97!T#0H@(" @+R\@86YD M($-O;7!I;&5T:6UE(%5N87)Y3W!E<F%T:6)L92!#;VYC97!T#0H@(" @('1E M;7!L871E(#P@#0H@(" @(" @('1Y<&5N86UE($9I<G-T5'EP92P-"B @(" @ M(" @='EP96YA;64@4V5C;VYD5'EP92P-"B @(" @(" @='EP96YA;64@5&AI M<F14>7!E+ T*(" @(" @("!I;G0@3BP-"B @(" @(" @:6YT($0-"B @(" ^ M#0H@(" @<W1R=6-T(&)I;F%R>5]O<&5R871I;VX\#0H@(" @(" @('1Y<&5N M86UE('!Q<SHZ86YO;E]Q,3P-"B @(" @(" @(" @($9I<G-T5'EP92P-"B @ M(" @(" @(" @(%-E8V]N9%1Y<&4L#0H@(" @(" @(" @("!4:&ER9%1Y<&4- M"B @(" @(" @/BP-"B @(" @(" @<'%S.CIT;U]P;W=E<BP-"B @(" @(" @ M<'%S.CIM971A.CIR871I;VYA;%]C/&EN="P@3BQ$/@T*(" @(#Y[#0H@(" @ M(" @('1Y<&5D968@='EP96YA;64@<'%S.CIM971A.CIR871I;VYA;%]C/&EN M="P@3BQ$/CHZ='EP92!R870[#0H@(" @(" @("!T>7!E9&5F('!Q<SHZ86YO M;E]Q,3P-"B @(" @(" @(" @('1Y<&5N86UE(&)I;F%R>5]O<&5R871I;VX\ M1FER<W14>7!E+'-T9#HZ;75L=&EP;&EE<RQR870^.CIR97-U;'1?='EP92P- M"B @(" @(" @(" @('1Y<&5N86UE(&)I;F%R>5]O<&5R871I;VX\4V5C;VYD M5'EP92QS=&0Z.FUU;'1I<&QI97,L<F%T/CHZ<F5S=6QT7W1Y<&4L#0H@(" @ M(" @(" @("!T>7!E;F%M92!B:6YA<GE?;W!E<F%T:6]N/%1H:7)D5'EP92QS M=&0Z.FUU;'1I<&QI97,L<F%T/CHZ<F5S=6QT7W1Y<&4-"B @(" @(" @/B!R M97-U;'1?='EP93L-"B @("!].PT*(" @(" @(" -"B @(" @=&5M<&QA=&4@ M/" -"B @(" @(" @='EP96YA;64@1FER<W14>7!E02P-"B @(" @(" @='EP M96YA;64@4V5C;VYD5'EP94$L#0H@(" @(" @('1Y<&5N86UE(%1H:7)D5'EP M94$L#0H@(" @(" @('1E;7!L871E(#QT>7!E;F%M93X@8VQA<W,@3W L#0H@ M(" @(" @('1Y<&5N86UE($9I<G-T5'EP94(L#0H@(" @(" @('1Y<&5N86UE M(%-E8V]N9%1Y<&5"+ T*(" @(" @("!T>7!E;F%M92!4:&ER9%1Y<&5"#0H@ M(" ^(" @(" @(" -"B @("!S=')U8W0@8FEN87)Y7V]P97)A=&EO;CP-"B @ M(" @(" @='EP96YA;64@<'%S.CIA;F]N7W$Q/ T*(" @(" @(" @(" @1FER M<W14>7!E02P-"B @(" @(" @(" @(%-E8V]N9%1Y<&5!+ T*(" @(" @(" @ M(" @5&AI<F14>7!E00T*(" @(" @(" ^+ T*(" @(" @("!/<"P-"B @(" @ M(" @='EP96YA;64@<'%S.CIA;F]N7W$Q/ T*(" @(" @(" @(" @1FER<W14 M>7!E0BP-"B @(" @(" @(" @(%-E8V]N9%1Y<&5"+ T*(" @(" @(" @(" @ M5&AI<F14>7!E0@T*(" @(" @(" ^+ T*(" @(" @("!T>7!E;F%M92!B;V]S M=#HZ96YA8FQE7VEF/ T*(" @(" @(" @(" @8F]O<W0Z.FUP;#HZ86YD7SP- M"B @(" @(" @(" @(" @("!P<7,Z.FUE=&$Z.F1E=&%I;#HZ:7-?=F%L:61? M8FEN87)Y7VQO9U]T<F%N<V9O<FT\#0H@(" @(" @(" @(" @(" @(" @($9I M<G-T5'EP94$L3W L1FER<W14>7!E0@T*(" @(" @(" @(" @(" @(#XL#0H@ M(" @(" @(" @(" @(" @<'%S.CIM971A.CID971A:6PZ.FES7W9A;&ED7V)I M;F%R>5]L;V=?=')A;G-F;W)M/ T*(" @(" @(" @(" @(" @(" @("!396-O M;F14>7!E02Q/<"Q396-O;F14>7!E0@T*(" @(" @(" @(" @(" @(#XL#0H@ M(" @(" @(" @(" @(" @<'%S.CIM971A.CID971A:6PZ.FES7W9A;&ED7V)I M;F%R>5]L;V=?=')A;G-F;W)M/ T*(" @(" @(" @(" @(" @(" @("!4:&ER M9%1Y<&5!+$]P+%1H:7)D5'EP94(-"B @(" @(" @(" @(" @(" ^+ T*(" @ M(" @(" @(" @(" @(&)O;W-T.CIM<&PZ.FYO=%\\#0H@(" @(" @(" @(" @ M(" @(" @('!Q<SHZ:7-?<&]W7V]P97)A=&]R/$]P/@T*(" @(" @(" @(" @ M(" @(#X-"B @(" @(" @(" @(#X-"B @(" @(" @/CHZ='EP90T*(" @(" @ M(" @(" @(" @( T*(" @/GL-"B @(" @(" @='EP961E9B!P<7,Z.F%N;VY? M<3$\#0H@(" @(" @(" @("!T>7!E;F%M92!P<7,Z.FUE=&$Z.F)I;F%R>5]L M;V=?=')A;G-F;W)M/$9I<G-T5'EP94$L3W L1FER<W14>7!E0CXZ.G)E<W5L M=%]T>7!E+ T*(" @(" @(" @(" @='EP96YA;64@<'%S.CIM971A.CIB:6YA M<GE?;&]G7W1R86YS9F]R;3Q396-O;F14>7!E02Q/<"Q396-O;F14>7!E0CXZ M.G)E<W5L=%]T>7!E+ T*(" @(" @(" @(" @='EP96YA;64@<'%S.CIM971A M.CIB:6YA<GE?;&]G7W1R86YS9F]R;3Q4:&ER9%1Y<&5!+$]P+%1H:7)D5'EP M94(^.CIR97-U;'1?='EP90T*(" @(" @(" ^(')E<W5L=%]T>7!E.PT*(" @ M(" @(" @(" @#0H@("!].PT*#0H@(" @=&5M<&QA=&4\#0H@(" @(" @('1Y M<&5N86UE($9I<G-T5'EP92 L#0H@(" @(" @('1Y<&5N86UE(%-E8V]N9%1Y M<&4L#0H@(" @(" @('1Y<&5N86UE(%1H:7)D5'EP90T*(" @(#X-"B @("!S M=')U8W0@=6YA<GE?;W!E<F%T:6]N/ T*(" @(" @("!P<7,Z.G)E8VEP<F]C M86PL#0H@(" @(" @('1Y<&5N86UE('!Q<SHZ86YO;E]Q,3P-"B @(" @(" @ M(" @($9I<G-T5'EP92P-"B @(" @(" @(" @(%-E8V]N9%1Y<&4L#0H@(" @ M(" @(" @("!4:&ER9%1Y<&4-"B @(" @(" @/@T*(" @(#Y[#0H@(" @(" @ M('1Y<&5D968@='EP96YA;64@<'%S.CIA;F]N7W$Q/ T*(" @(" @(" @(" @ M='EP96YA;64@=6YA<GE?;W!E<F%T:6]N/'-T9#HZ;F5G871E+$9I<G-T5'EP M93XZ.G)E<W5L=%]T>7!E+ T*(" @(" @(" @(" @='EP96YA;64@=6YA<GE? M;W!E<F%T:6]N/'-T9#HZ;F5G871E+%-E8V]N9%1Y<&4^.CIR97-U;'1?='EP M92P-"B @(" @(" @(" @('1Y<&5N86UE('5N87)Y7V]P97)A=&EO;CQS=&0Z M.FYE9V%T92Q4:&ER9%1Y<&4^.CIR97-U;'1?='EP90T*(" @(" @/B!R97-U M;'1?='EP93L-"B @('T[#0H-"GTO+VUE=&$-"GTO+W!Q<PT*"@II;G0@;6%I M;B@I"GL*(" @('1Y<&5D968@<'%S.CIC=%]Q=6%N=&ET>3P*(" @(" @("!P M<7,Z.FYA;65D7V%B<W1R86-T7W%U86YT:71Y/ H@(" @(" @(" @("!P<7,Z M.F%N;VY?<3$\"B @(" @(" @(" @(" @("!P<7,Z.FUE=&$Z.G)A=&EO;F%L M7V,\:6YT+#$^+ H@(" @(" @(" @(" @(" @<'%S.CIM971A.CIR871I;VYA M;%]C/&EN="PP/BP*(" @(" @(" @(" @(" @('!Q<SHZ;65T83HZ<F%T:6]N M86Q?8SQI;G0L,#X*(" @(" @(" @(" @/BP*(" @(" @(" @(" @<'%S.CIN M86UE9%]Q=6%N=&ET>5]T86<\,#X*(" @(" @(" ^+ H@(" @(" @('!Q<SHZ M<75A;G1I='E?=6YI=#P*(" @(" @(" @(" @<'%S.CIC;VAE<F5N=%]E>'!O M;F5N=#PP/BP*(" @(" @(" @(" @<'%S.CII;F-O:&5R96YT7VUU;'1I<&QI M97(\,3 P,# P,#X*(" @(" @(" ^+ H@(" @(" @(&1O=6)L92 *(" @(#X@ M("!T97-T7W1Y<&4Q.PH*(" @('1Y<&5D968@<'%S.CIC=%]Q=6%N=&ET>3P* M(" @(" @("!P<7,Z.FYA;65D7V%B<W1R86-T7W%U86YT:71Y/ H@(" @(" @ M(" @("!P<7,Z.F%N;VY?<3$\"B @(" @(" @(" @(" @("!P<7,Z.FUE=&$Z M.G)A=&EO;F%L7V,\:6YT+# ^+ H@(" @(" @(" @(" @(" @<'%S.CIM971A M.CIR871I;VYA;%]C/&EN="PQ/BP*(" @(" @(" @(" @(" @('!Q<SHZ;65T M83HZ<F%T:6]N86Q?8SQI;G0L,#X*(" @(" @(" @(" @/BP*(" @(" @(" @ M(" @<'%S.CIN86UE9%]Q=6%N=&ET>5]T86<\,#X*(" @(" @(" ^+ H@(" @ M(" @('!Q<SHZ<75A;G1I='E?=6YI=#P*(" @(" @(" @(" @<'%S.CIC;VAE M<F5N=%]E>'!O;F5N=#PP/BP*(" @(" @(" @(" @<'%S.CII;F-O:&5R96YT M7VUU;'1I<&QI97(\,3 P,# P,#X*(" @(" @(" ^+ H@(" @(" @(&EN=" * M(" @(#X@("!T97-T7W1Y<&4R.PH*"B @("!T97-T7W1Y<&4Q('0Q*#$I.PH@ M(" @=&5S=%]T>7!E,B!T,B@R*3L*(" @('!Q<SHZ;65T83HZ8FEN87)Y7V]P M97)A=&EO;CP*(" @(" @("!T97-T7W1Y<&4Q+ H@(" @(" @('-T9#HZ;75L M=&EP;&EE<RP*(" @(" @("!T97-T7W1Y<&4R"B @(" ^.CIR97-U;'1?='EP M92!T,6UU;'0R(#T@=#$@*B!T,CL*"B @("!S=&0Z.F-O=70@/#P@(G0Q("H@ M=#(@;G5M97)I8U]V86QU92 ]("(@/#P@=#%M=6QT,BYN=6UE<FEC7W9A;'5E M*"D@/#PG7&XG.PH@(" @<W1D.CIC;W5T(#P\("!T>7!E:60H=#%M=6QT,BDN M;F%M92@I(#P\("=<;B<["B @("!P<7,Z.FUE=&$Z.F)I;F%R>5]O<&5R871I M;VX\"B @(" @(" @=&5S=%]T>7!E,2P*(" @(" @("!S=&0Z.F1I=FED97,L M"B @(" @(" @=&5S=%]T>7!E,@H@(" @/CHZ<F5S=6QT7W1Y<&4@=#%D:79T M,B ]('0Q("\@=#(["B @("!S=&0Z.F-O=70@/#P@(G0Q("\@=#(@;G5M97)I M8U]V86QU92 ]("(@/#P@=#%D:79T,BYN=6UE<FEC7W9A;'5E*"D@/#PG7&XG M.PH@(" @<W1D.CIC;W5T(#P\('1Y<&5I9"AT,61I=G0R*2YN86UE*"D@/#PG M7&XG.PH*(" @("!P<7,Z.FUE=&$Z.F)I;F%R>5]O<&5R871I;VX\"B @(" @ M(" @=&5S=%]T>7!E,2P*(" @(" @("!S=&0Z.F1I=FED97,L"B @(" @(" @ M=&5S=%]T>7!E,0H@(" @/CHZ<F5S=6QT7W1Y<&4@=#%D:79T,2 ]('0Q("\@ M=#$["B @("!S=&0Z.F-O=70@/#P@(G0Q("\@=#$@;G5M97)I8U]V86QU92 ] M("(@/#P@=#%D:79T,2 \/"=<;B<["B @("!S=&0Z.F-O=70@/#P@='EP96ED M*'0Q9&EV=#$I+FYA;64H*2 \/"=<;B<["B @(" *(" @( H@(" @<'%S.CIM M971A.CIB:6YA<GE?;W!E<F%T:6]N/ H@(" @(" @('1E<W1?='EP93$L"B @ M(" @(" @<W1D.CIP;'5S+ H@(" @(" @('1E<W1?='EP93$*(" @(#XZ.G)E M<W5L=%]T>7!E('0Q<&QT,2 ]('0Q("L@=#$["@H@(" @<W1D.CIC;W5T(#P\ M(")T,2 K('0Q(&YU;65R:6-?=F%L=64@/2 B(#P\('0Q<&QT,2YN=6UE<FEC M7W9A;'5E*"D@/#PG7&XG.PH@(" @<W1D.CIC;W5T(#P\('1Y<&5I9"AT,7!L M=#$I+FYA;64H*2 \/"=<;B<["@H*(" @('!Q<SHZ;65T83HZ8FEN87)Y7V]P M97)A=&EO;CP*(" @(" @("!T97-T7W1Y<&4R+ H@(" @(" @('-T9#HZ;6EN M=7,L"B @(" @(" @=&5S=%]T>7!E,@H@(" @/CHZ<F5S=6QT7W1Y<&4@=#)M M:6YU<W0R(#T@=#(@+2!T,CL*(" @('-T9#HZ8V]U=" \/" B=#(@+2!T,B!N M=6UE<FEC7W9A;'5E(#T@(B \/"!T,FUI;G5S=#(N;G5M97)I8U]V86QU92@I M(#P\)UQN)SL*(" @('-T9#HZ8V]U=" \/"!T>7!E:60H=#)M:6YU<W0R*2YN M86UE*"D@/#PG7&XG.PH*(" @("!P<7,Z.FUE=&$Z.F)I;F%R>5]O<&5R871I M;VX\"B @(" @(" @=&5S=%]T>7!E,BP*(" @(" @("!P<7,Z.G1O7W!O=V5R M+ H@(" @(" @('!Q<SHZ;65T83HZ<F%T:6]N86Q?8SQI;G0L,BPQ/@H@(" @ M/CHZ<F5S=6QT7W1Y<&4@=#)P;W<R(#T@<'%S.CIP;W<\,CXH=#(I.PH@(" @ M<W1D.CIC;W5T(#P\(")P;W%S/#(^*'0R*2!N=6UE<FEC7W9A;'5E(#T@(B \ M/"!T,G!O=S(N;G5M97)I8U]V86QU92@I(#P\)UQN)SL*(" @('-T9#HZ8V]U M=" \/"!T>7!E:60H=#)P;W<R*2YN86UE*"D@/#PG7&XG.PH@("\O("!S=&0Z ?.F-O=70@/#P@=#)P;W<R(#P\)UQN)SL*(" @( I]"@`` ` end