Initial code commit

This commit is contained in:
sosguns2002 2017-05-16 14:39:11 +03:00
parent b5e9d2a858
commit 61227c428e
523 changed files with 166644 additions and 0 deletions

View File

@ -0,0 +1,3 @@
The package is a container for the [madIS](https://code.google.com/p/madis/) Python-based system developed by [NKUA](http://en.uoa.gr/).
It requires the `apsw` Python package to be installed in the operating system.

View File

@ -0,0 +1,40 @@
\.orig$
\.orig\..*$
\.chg\..*$
\.rej$
\.conflict\~$
^src/tests/(?!readme.txt$).*$
^nbproject/.*$
^.idea/.*$
^src/docs/build/_static/.*$
^/src/docs/build/_static/.*$
^src/docs/build/_sources/.*$
^/src/docs/build/_sources/.*$
^src/docs/html/(?!readme.txt$).*$
^/src/docs/html/(?!readme.txt$).*$
^src/libexternal/(?!__init__.py$).*$
^src/functionslocal/row/(?!__init__.py$).*$
^/src/functionslocal/row/(?!__init__.py$).*$
^src/functionslocal/aggregate/(?!__init__.py$).*$
^/src/functionslocal/aggregate/(?!__init__.py$).*$
^src/functionslocal/vtable/(?!__init__.py$).*$
^/src/functionslocal/vtable/(?!__init__.py$).*$
^src/docs/build/.*$
^/src/docs/build/.*$
^src/docs/source/row\.txt$
^/src/docs/source/row\.txt$
^src/docs/source/aggregate\.txt$
^/src/docs/source/aggregate\.txt$
^src/docs/source/vtable\.txt$
^/src/docs/source/vtable\.txt$
# use glob syntax.
syntax: glob
*.pyc
*.db3
mterm_tel
project.properties
project.xml
private.xml
private.properties
src/docs/html/_sources/row.txt

View File

@ -0,0 +1,32 @@
Copyright and License
=====================
Copyright (C) 2009-2013 Lefteris Stamatogiannakis, Mei Li Triantafyllidi,
Ioannis Foufoulas, Maria Vayanou, Marialena Kyriakidi.
The external libraries used throughout the madIS project are copyright
of their respective authors.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
* The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
* Altered source versions must be plainly marked as such, and must not
be misrepresented as being the original software.
* This notice may not be removed or altered from any source
distribution.
Alternatively you may strike the license above and use it under any
OSI approved open source license such as those listed at
http://opensource.org/licenses/alphabetical

View File

@ -0,0 +1,257 @@
Asia AF
Europe AL
Africa AG
Oceania AQ
Europe AN
Africa AO
Americas AV
Americas AC
Americas AR
Asia AM
Americas AA
Oceania AS
Europe AU
Asia AJ
Americas BF
Asia BA
Asia BG
Americas BB
Europe BO
Europe BE
Americas BH
Africa BN
Americas BD
Asia BT
Americas BL
Europe BK
Africa BC
Americas BR
Americas VI
Asia BX
Europe BU
Africa UV
Africa BY
Asia CB
Africa CM
Americas CA
Africa CV
Americas CJ
Africa CT
Africa CD
Americas CI
Asia CH
Asia KT
Asia CK
Americas CO
Africa CN
Africa CF
Oceania CW
Americas CS
Africa IV
Europe HR
Americas CU
Asia CY
Europe EZ
Europe DA
Africa DJ
Americas DO
Americas DR
Americas EC
Africa EG
Americas ES
Africa EK
Africa ER
Europe EN
Africa ET
Americas FA
Europe FO
Oceania FJ
Europe FI
Europe FR
Americas FG
Oceania FP
Africa GB
Africa GA
Asia GG
Europe GM
Africa GH
Europe GI
Europe GR
Americas GL
Americas GJ
Americas GP
Oceania GQ
Americas GT
Africa GV
Africa PU
Americas GY
Americas HA
Europe VT
Americas HO
Europe HU
Europe IC
Asia IN
Asia ID
Asia IR
Asia IZ
Europe EI
Asia IS
Europe IT
Americas JM
Asia JA
Asia JO
Asia KZ
Africa KE
Oceania KR
Asia KN
Asia KS
Asia KU
Asia KG
Asia LA
Europe LG
Asia LE
Africa LT
Africa LI
Africa LY
Europe LS
Europe LH
Europe LU
Europe MK
Africa MA
Africa MI
Asia MY
Asia MV
Africa ML
Europe MT
Oceania RM
Americas MB
Africa MR
Africa MP
Africa MF
Americas MX
Oceania
Europe MD
Europe MN
Asia MG
Americas MH
Africa MO
Africa MZ
Asia BM
Africa WA
Oceania NR
Asia NP
Europe NL
Americas NT
Oceania NC
Oceania NZ
Americas NU
Africa NG
Africa NI
Oceania NE
Oceania NF
Oceania CQ
Europe NO
Asia MU
Asia PK
Oceania PS
Americas PM
Oceania PP
Americas PA
Americas PE
Asia RP
Oceania PC
Europe PL
Europe PO
Americas RQ
Asia QA
Africa RE
Europe RO
Asia RS
Africa RW
Americas SC
Americas ST
Americas SB
Americas VC
Europe SM
Africa TP
Asia SA
Africa SG
Europe SR
Africa SE
Africa SL
Asia SN
Europe LO
Europe SI
Oceania BP
Africa SO
Africa SF
Europe SP
Asia CE
Africa SU
Americas NS
Europe SV
Africa WZ
Europe SW
Europe SZ
Asia SY
Asia TW
Asia TI
Africa TZ
Asia TH
Africa TO
Oceania TL
Oceania TN
Americas TD
Africa TS
Asia TU
Asia TX
Americas TK
Oceania TV
Africa UG
Europe UP
Asia TC
Europe UK
Americas US
Americas UY
Asia UZ
Oceania NH
Americas VE
Asia VM
Americas VQ
Oceania WF
Africa WI
Oceania WS
Asia YM
Africa CG
Africa ZA
Africa ZI
Asia HK
Asia MC
Antarctica AY
Atlantic Ocean BV
Asia IO
Indian Ocean FS
Indian Ocean HM
Europe MW
Atlantic Ocean SH
Atlantic Ocean SX
Asia AT
Americas BQ
Oceania CR
Europe EE
Asia GZ
Europe IM
Oceania FM
Americas FA
Europe GK
Europe JE
Americas IP
Europe JN
Europe MJ
Asia PF
Asia PG
Europe RB
Asia TT
Asia WE
Oceania WQ
Americas UM
1 Asia AF
2 Europe AL
3 Africa AG
4 Oceania AQ
5 Europe AN
6 Africa AO
7 Americas AV
8 Americas AC
9 Americas AR
10 Asia AM
11 Americas AA
12 Oceania AS
13 Europe AU
14 Asia AJ
15 Americas BF
16 Asia BA
17 Asia BG
18 Americas BB
19 Europe BO
20 Europe BE
21 Americas BH
22 Africa BN
23 Americas BD
24 Asia BT
25 Americas BL
26 Europe BK
27 Africa BC
28 Americas BR
29 Americas VI
30 Asia BX
31 Europe BU
32 Africa UV
33 Africa BY
34 Asia CB
35 Africa CM
36 Americas CA
37 Africa CV
38 Americas CJ
39 Africa CT
40 Africa CD
41 Americas CI
42 Asia CH
43 Asia KT
44 Asia CK
45 Americas CO
46 Africa CN
47 Africa CF
48 Oceania CW
49 Americas CS
50 Africa IV
51 Europe HR
52 Americas CU
53 Asia CY
54 Europe EZ
55 Europe DA
56 Africa DJ
57 Americas DO
58 Americas DR
59 Americas EC
60 Africa EG
61 Americas ES
62 Africa EK
63 Africa ER
64 Europe EN
65 Africa ET
66 Americas FA
67 Europe FO
68 Oceania FJ
69 Europe FI
70 Europe FR
71 Americas FG
72 Oceania FP
73 Africa GB
74 Africa GA
75 Asia GG
76 Europe GM
77 Africa GH
78 Europe GI
79 Europe GR
80 Americas GL
81 Americas GJ
82 Americas GP
83 Oceania GQ
84 Americas GT
85 Africa GV
86 Africa PU
87 Americas GY
88 Americas HA
89 Europe VT
90 Americas HO
91 Europe HU
92 Europe IC
93 Asia IN
94 Asia ID
95 Asia IR
96 Asia IZ
97 Europe EI
98 Asia IS
99 Europe IT
100 Americas JM
101 Asia JA
102 Asia JO
103 Asia KZ
104 Africa KE
105 Oceania KR
106 Asia KN
107 Asia KS
108 Asia KU
109 Asia KG
110 Asia LA
111 Europe LG
112 Asia LE
113 Africa LT
114 Africa LI
115 Africa LY
116 Europe LS
117 Europe LH
118 Europe LU
119 Europe MK
120 Africa MA
121 Africa MI
122 Asia MY
123 Asia MV
124 Africa ML
125 Europe MT
126 Oceania RM
127 Americas MB
128 Africa MR
129 Africa MP
130 Africa MF
131 Americas MX
132 Oceania
133 Europe MD
134 Europe MN
135 Asia MG
136 Americas MH
137 Africa MO
138 Africa MZ
139 Asia BM
140 Africa WA
141 Oceania NR
142 Asia NP
143 Europe NL
144 Americas NT
145 Oceania NC
146 Oceania NZ
147 Americas NU
148 Africa NG
149 Africa NI
150 Oceania NE
151 Oceania NF
152 Oceania CQ
153 Europe NO
154 Asia MU
155 Asia PK
156 Oceania PS
157 Americas PM
158 Oceania PP
159 Americas PA
160 Americas PE
161 Asia RP
162 Oceania PC
163 Europe PL
164 Europe PO
165 Americas RQ
166 Asia QA
167 Africa RE
168 Europe RO
169 Asia RS
170 Africa RW
171 Americas SC
172 Americas ST
173 Americas SB
174 Americas VC
175 Europe SM
176 Africa TP
177 Asia SA
178 Africa SG
179 Europe SR
180 Africa SE
181 Africa SL
182 Asia SN
183 Europe LO
184 Europe SI
185 Oceania BP
186 Africa SO
187 Africa SF
188 Europe SP
189 Asia CE
190 Africa SU
191 Americas NS
192 Europe SV
193 Africa WZ
194 Europe SW
195 Europe SZ
196 Asia SY
197 Asia TW
198 Asia TI
199 Africa TZ
200 Asia TH
201 Africa TO
202 Oceania TL
203 Oceania TN
204 Americas TD
205 Africa TS
206 Asia TU
207 Asia TX
208 Americas TK
209 Oceania TV
210 Africa UG
211 Europe UP
212 Asia TC
213 Europe UK
214 Americas US
215 Americas UY
216 Asia UZ
217 Oceania NH
218 Americas VE
219 Asia VM
220 Americas VQ
221 Oceania WF
222 Africa WI
223 Oceania WS
224 Asia YM
225 Africa CG
226 Africa ZA
227 Africa ZI
228 Asia HK
229 Asia MC
230 Antarctica AY
231 Atlantic Ocean BV
232 Asia IO
233 Indian Ocean FS
234 Indian Ocean HM
235 Europe MW
236 Atlantic Ocean SH
237 Atlantic Ocean SX
238 Asia AT
239 Americas BQ
240 Oceania CR
241 Europe EE
242 Asia GZ
243 Europe IM
244 Oceania FM
245 Americas FA
246 Europe GK
247 Europe JE
248 Americas IP
249 Europe JN
250 Europe MJ
251 Asia PF
252 Asia PG
253 Europe RB
254 Asia TT
255 Asia WE
256 Oceania WQ
257 Americas UM

View File

@ -0,0 +1,259 @@
id name total_area land_area water_area coastline total_border population p_young p_adult p_old p_growth labor_force phone_mobiles phone_mainlines internet_users isps birth_rate death_rate
AA Aruba 193.00 193.00 0.00 69 0.00 100018.00 19.70 70.20 10.10 1.52 41500.00 98400 37100 24000 12.83 7.61
AC Antigua and Barbuda 442.60 442.60 0.00 153 0.00 69481.00 27.30 69.00 3.70 0.53 30000.00 54000 38000 20000 16 16.62 5.31
TC United Arab Emirates 83600.00 83600.00 0.00 1318 867.00 4444011.00 20.60 78.50 0.90 4.00 2968000.00 4535000 1237000 1397000 1 16.09 2.16
AF Afghanistan 647500.00 647500.00 0.00 0 5529.00 31889923.00 44.60 53.00 2.40 2.63 15000000.00 1400000 280000 30000 1 46.21 19.96
AG Algeria 2381740.00 2381740.00 0.00 998 6343.00 33333216.00 27.20 67.90 4.80 1.22 9310000.00 13661000 2572000 1920000 2 17.11 4.62
AJ Azerbaijan 86600.00 86100.00 500.00 0 2013.00 8120247.00 25.40 67.70 7.00 0.69 5191000.00 2242000 1091000 678800 2 17.47 8.35
AL Albania 28748.00 27398.00 1350.00 362 720.00 3600523.00 24.10 66.60 9.30 0.53 1090000.00 1259000 255000 75000 10 15.16 5.33
AM Armenia 29800.00 28400.00 1400.00 0 1254.00 2971650.00 19.50 69.30 11.20 -0.13 1200000.00 320000 600000 150000 9 12.34 8.29
AN Andorra 468.00 468.00 0.00 0 120.30 71822.00 14.50 71.20 14.30 0.84 42420.00 64600 35400 21900 1 8.45 6.45
AO Angola 1246700.00 1246700.00 0.00 1600 5198.00 12263596.00 43.70 53.50 2.80 2.18 6393000.00 1094000 94300 172000 1 44.51 24.81
AQ American Samoa 199.00 199.00 0.00 116 0.00 57663.00 33.60 63.50 2.90 -0.26 17630.00 2377 15000 1 21.83 3.24
AR Argentina 2766890.00 2736690.00 30200.00 4989 9861.00 40301927.00 24.90 64.40 10.70 0.94 15350000.00 22100000 8800000 10000000 33 16.53 7.55
AS Australia 7686850.00 7617930.00 68920.00 25760 0.00 20434176.00 19.30 67.40 13.20 0.82 10660000.00 18420000 11460000 14664000 571 12.02 7.56
AT Ashmore and Cartier Islands 5.00 5.00 0.00 74 0.00 0.00
AU Austria 83870.00 82444.00 1426.00 0 2562.00 8199783.00 15.10 67.50 17.50 0.08 3880000.00 8160000 3705000 4650000 37 8.69 9.84
AV Anguilla 102.00 102.00 0.00 61 0.00 13677.00 22.30 70.80 6.90 1.38 6049.00 1800 6200 3000 16 13.97 5.34
AX Akrotiri 123.00 56 47.40 0.00
AY Antarctica 14000000.00 14000000.00 17968 0.00 0.00 0
BA Bahrain 665.00 665.00 0.00 161 0.00 708573.00 26.90 69.50 3.70 1.39 352000.00 748700 196500 152700 1 17.53 4.21
BB Barbados 431.00 431.00 0.00 97 0.00 280946.00 19.70 71.40 8.90 0.37 128500.00 206200 134900 160000 19 12.61 8.61
BC Botswana 600370.00 585370.00 15000.00 0 4013.00 1815508.00 35.80 60.30 3.90 1.50 288400.00 823100 132000 60000 11 23.17 13.63
BD Bermuda 53.30 53.30 0.00 103 0.00 66163.00 18.30 69.20 12.50 0.58 38360.00 49000 56000 39000 20 11.26 7.84
BE Belgium 30528.00 30278.00 250.00 67 1385.00 10392226.00 16.50 66.10 17.40 0.12 4890000.00 9460000 4801000 5100000 61 10.29 10.32
BF The Bahamas 13940.00 10070.00 3870.00 3542 0.00 305655.00 27.00 66.50 6.50 0.60 176300.00 186000 139900 93000 19 17.30 9.13
BG Bangladesh 144000.00 133910.00 10090.00 580 4246.00 150448339.00 33.10 63.40 3.50 2.06 68000000.00 9000000 1070000 300000 10 29.36 8.13
BH Belize 22966.00 22806.00 160.00 386 516.00 294385.00 38.90 57.50 3.50 2.26 113000.00 93100 33300 35000 2 28.34 5.76
BK Bosnia and Herzegovina 51129.00 51129.00 0.00 20 1459.00 4552198.00 15.00 70.40 14.60 1.00 1026000.00 1594000 968900 806400 3 8.80 8.42
BL Bolivia 1098580.00 1084390.00 14190.00 0 6940.00 9119152.00 34.30 61.10 4.60 1.42 4300000.00 2421000 646300 480000 9 22.82 7.44
BM Burma 678500.00 657740.00 20760.00 1930 5876.00 47373958.00 26.10 68.60 5.30 0.82 28490000.00 183400 476200 78000 1 17.48 9.33
BN Benin 112620.00 110620.00 2000.00 121 1989.00 8078314.00 43.90 53.70 2.40 2.67 3211000.00 386700 76300 425000 4 38.10 11.94
BO Belarus 207600.00 207600.00 0.00 0 2900.00 9724723.00 14.70 70.40 14.90 -0.41 4300000.00 4098000 3284300 3394000 23 9.50 13.98
BP Solomon Islands 28450.00 27540.00 910.00 5313 0.00 566842.00 40.70 55.90 3.30 2.54 249200.00 6000 7400 8400 1 29.27 3.87
BQ Navassa Island 5.40 5.40 0.00 8 0.00 0.00
BR Brazil 8511965.00 8456510.00 55455.00 7491 16885.00 190010647.00 25.30 68.40 6.30 1.01 96340000.00 86210000 42382000 25900000 50 16.30 6.19
BT Bhutan 47000.00 47000.00 0.00 0 1075.00 2327849.00 38.60 57.40 4.00 2.08 37800 32700 25000 33.28 12.46
BU Bulgaria 110910.00 110550.00 360.00 354 1808.00 7322858.00 13.90 68.70 17.40 -0.84 3510000.00 6245000 2483000 2200000 200 9.62 14.28
BV Bouvet Island 49.00 49.00 0.00 30 0.00 0.00
BX Brunei 5770.00 5270.00 500.00 161 381.00 374577.00 27.80 69.00 3.20 1.81 180400.00 205900 90000 56000 2 18.56 3.26
BY Burundi 27830.00 25650.00 2180.00 0 974.00 8390505.00 46.30 51.20 2.60 3.59 2990000.00 153000 27700 25000 1 41.97 13.17
CA Canada 9984670.00 9093507.00 891163.00 202080 8893.00 33390141.00 17.30 69.20 13.50 0.87 17590000.00 16600000 18276000 21900000 760 10.75 7.86
CB Cambodia 181040.00 176520.00 4520.00 443 2572.00 13995904.00 34.00 62.40 3.60 1.73 7000000.00 1062000 36400 41000 2 25.53 8.24
CD Chad 1284000.00 1259200.00 24800.00 0 5968.00 9885661.00 47.30 49.80 2.90 2.32 2719000.00 210000 13000 35000 1 42.35 16.69
CE Sri Lanka 65610.00 64740.00 870.00 1340 0.00 20926315.00 24.30 67.90 7.80 0.98 7500000.00 4284000 1510000 280000 5 17.00 6.01
CF Republic of the Congo 342000.00 341500.00 500.00 169 5504.00 3800610.00 46.30 50.80 2.90 2.64 490000 13800 36000 1 42.16 12.59
CG Democratic Republic of the Congo 2345410.00 2267600.00 77810.00 37 10730.00 65751512.00 47.60 49.90 2.60 3.39 15000000.00 2746000 10600 140600 1 42.96 10.34
CH China 9596960.00 9326410.00 270550.00 14500 22117.00 1321851888.00 20.40 71.70 7.90 0.61 798000000.00 437480000 350433000 123000000 3 13.45 7.00
CI Chile 756950.00 748800.00 8150.00 6435 6339.00 16284741.00 24.10 67.40 8.50 0.92 6940000.00 10570000 3436000 6700000 7 15.03 5.87
CJ Cayman Islands 262.00 262.00 0.00 160 0.00 46600.00 20.30 71.00 8.60 2.50 23450.00 17000 38000 9909 16 12.60 4.98
CK Cocos Islands 14.00 14.00 0.00 26 0.00 596.00 0.00 287 2
CM Cameroon 475440.00 469440.00 6000.00 402 4591.00 18060382.00 41.30 55.50 3.20 2.24 6394000.00 2259000 99400 167000 1 35.07 12.66
CN Comoros 2170.00 2170.00 0.00 340 0.00 711417.00 42.60 54.40 3.00 2.84 144500.00 16100 16900 20000 1 36.35 7.95
CO Colombia 1138910.00 1038700.00 100210.00 3208 6309.00 44379598.00 29.80 64.80 5.40 1.43 20810000.00 21850000 7678800 4739000 18 20.16 5.54
CQ Northern Mariana Islands 477.00 477.00 0.00 1482 0.00 84546.00 18.90 79.50 1.60 2.46 44470.00 20500 21000 10000 1 19.27 2.29
CR Coral Sea Islands 0.00 3095 0.00 0.00
CS Costa Rica 51100.00 50660.00 440.00 1290 639.00 4133884.00 27.80 66.40 5.80 1.41 1866000.00 1101000 1388000 1000000 3 18.02 4.39
CT Central African Republic 622984.00 622984.00 0.00 0 5203.00 4369038.00 41.60 54.20 4.10 1.51 60000 10000 9000 1 33.52 18.46
CU Cuba 110860.00 110860.00 0.00 3735 29.00 11394043.00 18.80 70.50 10.70 0.27 4820000.00 134500 849900 190000 5 11.44 7.14
CV Cape Verde 4033.00 4033.00 0.00 965 0.00 423613.00 36.90 56.40 6.70 0.61 120600.00 81700 71400 25000 1 24.40 6.50
CW Cook Islands 236.70 236.70 0.00 120 0.00 21750.00 34.10 59.50 6.40 -1.20 6820.00 1500 6200 3600 3 21.00
CY Cyprus 9250.00 9240.00 10.00 648 0.00 788457.00 19.90 68.30 11.80 0.53 298000 6 12.56 7.72
DA Denmark 43094.00 42394.00 700.00 7314 68.00 5468120.00 18.60 66.00 15.40 0.31 2910000.00 5469000 3350000 3763000 13 10.91 10.30
DJ Djibouti 23000.00 22980.00 20.00 314 516.00 496374.00 43.40 53.20 3.40 1.98 282000.00 34500 11100 9000 1 39.07 19.23
DO Dominica 754.00 754.00 0.00 148 0.00 72386.00 25.60 64.20 10.20 0.18 25000.00 41800 21000 20500 16 15.75 8.44
DR Dominican Republic 48730.00 48380.00 350.00 1288 360.00 9365818.00 32.10 62.20 5.70 1.50 3896000.00 3623000 894500 938300 24 22.91 5.32
DX Dhekelia 130.80 28 360.00
EC Ecuador 283560.00 276840.00 6720.00 2237 2010.00 13755680.00 32.60 62.30 5.10 1.55 4570000.00 6246000 1701000 616000 31 21.91 4.21
EE European Union 4324782.00 65993 12440.80 490426060.00 15.72 67.16 17.11 0.16 222700000.00 466000000 238000000 247000000 10.00 10.00
EG Egypt 1001450.00 995450.00 6000.00 2450 2665.00 80335036.00 32.20 63.20 4.60 1.72 21800000.00 14045000 10396000 5000000 50 22.53 5.11
EI Ireland 70280.00 68890.00 1390.00 1448 360.00 4109086.00 20.80 67.50 11.70 1.14 2120000.00 4210000 2033000 2060000 22 14.40 7.79
EK Equatorial Guinea 28051.00 28051.00 0.00 296 539.00 551201.00 41.50 54.80 3.80 2.02 96900 10000 5000 1 35.16 15.01
EN Estonia 45226.00 43211.00 2015.00 3794 633.00 1315912.00 15.00 67.50 17.50 -0.64 673000.00 1445000 442000 690000 38 10.17 13.30
ER Eritrea 121320.00 121320.00 0.00 2234 1626.00 4906585.00 43.50 52.90 3.60 2.46 58000 37700 70000 5 33.97 9.36
ES El Salvador 21040.00 20720.00 320.00 307 545.00 6948073.00 36.10 58.70 5.20 1.70 2856000.00 2412000 971500 637100 4 26.13 5.60
ET Ethiopia 1127127.00 1119683.00 7444.00 0 5328.00 76511887.00 43.40 53.80 2.70 2.27 27270000.00 410600 610300 113000 1 37.39 14.67
EZ Czech Republic 78866.00 77276.00 1590.00 0 2290.20 10228744.00 14.10 71.20 14.70 -0.07 5310000.00 11776000 3217300 5100000 8.96 10.64
FI Finland 338145.00 304473.00 33672.00 1250 2681.00 5238460.00 16.90 66.70 16.40 0.13 2620000.00 5231000 2120000 3286000 3 10.42 9.93
FJ Fiji 18270.00 18270.00 0.00 1129 0.00 918675.00 30.90 64.70 4.40 1.39 137000.00 142200 102000 61000 2 22.37 5.66
FA Falkland Islands 12173.00 12173.00 0.00 1288 0.00 3105.00 2.44 1724.00 0 2400 1900 2
FM Federated States of Micronesia 702.00 702.00 0.00 6112 0.00 107862.00 35.90 61.20 2.90 -0.15 37410.00 14100 12400 14000 1 24.14 4.66
FO Faroe Islands 1399.00 1399.00 0.00 1117 0.00 47511.00 20.60 65.30 14.10 0.54 24250.00 42500 23800 33000 2 14.12 8.69
FP French Polynesia 4167.00 3660.00 507.00 2525 0.00 278963.00 25.40 68.20 6.30 1.46 65930.00 87000 53400 55000 2 16.41 4.61
FR France 643427.00 640053.00 3374.00 4668 0.00 18.60 65.20 16.20 0.59 27880000.00 49370000 38433000 29945000 62 12.91 8.55
FS French Southern and Antarctic Lands 28 0.00 0.00
GA The Gambia 11300.00 10000.00 1300.00 80 740.00 1688359.00 44.10 53.20 2.80 2.78 400000.00 247500 44000 49000 2 38.86 11.99
GB Gabon 267667.00 257667.00 10000.00 885 2551.00 1454867.00 42.10 53.90 4.00 2.04 581000.00 649800 39100 67000 1 35.96 12.45
GG Georgia 69700.00 69700.00 0.00 310 1461.00 4646003.00 16.70 66.60 16.70 -0.33 2040000.00 1459000 683200 175600 6 10.54 9.37
GH Ghana 239460.00 230940.00 8520.00 539 2094.00 22931299.00 38.20 58.20 3.60 1.97 10870000.00 2842000 321500 401300 12 29.85 9.55
GI Gibraltar 6.50 6.50 0.00 12 1.20 27967.00 17.20 66.30 16.50 0.13 12690.00 9797 24512 6200 2 10.69 9.40
GJ Grenada 344.00 344.00 0.00 121 0.00 89971.00 32.80 64.10 3.10 0.34 42300.00 43300 32700 19000 14 21.87 6.61
GK Guernsey 78.00 78.00 0.00 50 0.00 65573.00 14.80 67.40 17.80 0.24 31470.00 43800 55100 36000 8.65 10.07
GL Greenland 2166086.00 2166086.00 44087 0.00 56344.00 24.00 69.10 6.90 -0.03 32120.00 32200 25300 38000 1 16.01 7.93
GM Germany 357021.00 349223.00 7798.00 2389 3621.00 82400996.00 13.90 66.30 19.80 -0.03 43660000.00 79200000 55046000 50616000 200 8.20 10.71
GQ Guam 541.30 541.30 0.00 126 0.00 173456.00 28.60 64.50 6.90 1.40 62050.00 98000 84134 79000 20 18.56 4.56
GR Greece 131940.00 130800.00 1140.00 13676 1228.00 10706290.00 14.30 66.70 19.00 0.16 4880000.00 10043000 6303000 3800000 27 9.62 10.33
GT Guatemala 108890.00 108430.00 460.00 400 1687.00 12728111.00 40.80 55.50 3.60 2.15 5020000.00 3168000 1132000 756000 5 29.09 5.27
GV Guinea 245857.00 245857.00 0.00 320 3399.00 9947814.00 44.30 52.50 3.20 2.62 3700000.00 189000 26200 46000 4 41.53 15.33
GY Guyana 214970.00 196850.00 18120.00 459 2949.00 769095.00 26.10 68.60 5.30 0.23 418000.00 281400 110100 160000 3 18.09 8.28
GZ Gaza Strip 360.00 360.00 0.00 40 62.00 1482405.00 47.60 49.90 2.50 3.66 259000.00 1095000 349000 243000 3 38.90 3.74
HA Haiti 27750.00 27560.00 190.00 1771 360.00 8706497.00 42.10 54.40 3.50 2.45 3600000.00 400000 140000 500000 3 35.87 10.40
HK Hong Kong 1092.00 1042.00 50.00 733 30.00 6980412.00 13.00 74.00 12.90 0.56 3630000.00 8693000 3795000 4879000 17 7.34 6.45
HM Heard Island and McDonald Islands 412.00 412.00 0.00 102 0.00 0.00
HO Honduras 112090.00 111890.00 200.00 820 1520.00 7483763.00 39.30 57.20 3.50 2.09 2589000.00 1282000 494400 223000 8 27.59 5.32
HR Croatia 56542.00 56414.00 128.00 5835 2197.00 4493312.00 16.00 67.10 16.90 -0.04 1720000.00 2984000 1890000 1451000 9 9.63 11.57
HU Hungary 93030.00 92340.00 690.00 0 2171.00 9956108.00 15.30 69.30 15.40 -0.25 4200000.00 9320000 3356000 3050000 16 9.66 13.05
IC Iceland 103000.00 100250.00 2750.00 4970 0.00 301931.00 21.40 66.80 11.80 0.82 173000.00 304000 193900 258000 20 13.57 6.77
ID Indonesia 1919440.00 1826440.00 93000.00 54716 2830.00 234693997.00 28.70 65.60 5.70 1.21 108200000.00 46910000 12772000 16000000 24 19.65 6.25
IM Isle of Man 572.00 572.00 0.00 160 0.00 75831.00 17.10 65.80 17.10 0.51 39690.00 51000 10.96 11.10
IN India 3287590.00 2973190.00 314400.00 7000 14103.00 1129866154.00 31.80 63.10 5.10 1.61 509300000.00 69193000 49750000 60000000 43 22.69 6.58
IO British Indian Ocean Territory 54400.00 60.00 54340.00 698 0.00 0.00 1
IP Clipperton Island 6.00 6.00 0.00 11 0.00 0.00
IR Iran 1648000.00 1636000.00 12000.00 2440 5440.00 65397521.00 23.20 71.40 5.40 0.66 24360000.00 8500000 18986000 7500000 100 16.57 5.65
IS Israel 20770.00 20330.00 440.00 273 1017.00 6426679.00 26.10 64.20 9.80 1.15 2600000.00 7757000 2936000 3700000 21 17.71 6.17
IT Italy 301230.00 294020.00 7210.00 7600 1932.20 58147733.00 13.80 66.40 19.90 0.01 24630000.00 72200000 25049000 28870000 93 8.54 10.50
IV Cote d'Ivoire 322460.00 318000.00 4460.00 515 3110.00 18013409.00 40.60 56.60 2.80 2.00 6738000.00 2190000 257900 160000 5 34.69 14.74
IZ Iraq 437072.00 432162.00 4910.00 58 3650.00 27499638.00 39.40 57.60 3.00 2.62 7400000.00 8700000 1547000 36000 1 31.44 5.26
JA Japan 377835.00 374744.00 3091.00 29751 0.00 127433494.00 13.80 65.20 21.00 -0.09 66440000.00 94745000 58780000 86300000 73 8.10 8.98
JE Jersey 116.00 116.00 0.00 70 0.00 91321.00 16.90 67.30 15.80 0.24 53560.00 83900 73900 27000 9.02 9.32
JM Jamaica 10991.00 10831.00 160.00 1022 0.00 2780132.00 32.50 60.10 7.40 0.78 1100000.00 2700000 342000 1067000 21 20.44 6.59
JN Jan Mayen 377.00 377.00 0.00 124 0.00 0.00 13
JO Jordan 92300.00 91971.00 329.00 26 1635.00 6053193.00 33.00 63.00 4.00 2.41 1512000.00 3013000 628200 629500 5 20.69 2.68
KE Kenya 582650.00 569250.00 13400.00 536 3477.00 36913721.00 42.10 55.20 2.60 2.80 1955000.00 6500000 281800 1055000 65 38.94 10.95
KG Kyrgyzstan 198500.00 191300.00 7200.00 0 3878.00 5284149.00 30.30 63.50 6.20 1.35 2700000.00 541700 438200 280000 23.08 7.02
KN North Korea 120540.00 120410.00 130.00 2495 1673.00 23301725.00 23.30 68.10 8.50 0.79 9600000.00 980000 1 15.06 7.21
KR Kiribati 811.00 811.00 0.00 1143 0.00 107817.00 38.20 58.40 3.40 2.24 7870.00 600 4500 2000 1 30.48 8.12
KS South Korea 98480.00 98190.00 290.00 2413 238.00 49044790.00 18.30 72.10 9.60 0.39 23770000.00 38342000 23745000 33900000 11 9.93 5.99
KT Christmas Island 135.00 135.00 0.00 139 0.00 1402.00 0.00 464 2
KU Kuwait 17820.00 17820.00 0.00 499 462.00 2505559.00 26.70 70.50 2.80 3.56 1136000.00 2536000 510300 700000 3 21.95 2.39
KZ Kazakhstan 2717300.00 2669800.00 47500.00 0 12012.00 15284929.00 22.50 69.20 8.30 0.35 7834000.00 4955000 2500000 400000 10 16.23 9.40
LA Laos 236800.00 230800.00 6000.00 0 5083.00 6521998.00 41.20 55.70 3.10 2.37 2100000.00 520546 90067 25000 1 34.98 11.28
LE Lebanon 10400.00 10230.00 170.00 225 454.00 3925502.00 26.20 66.70 7.10 1.20 1500000.00 1178000 990000 700000 22 18.08 6.10
LG Latvia 64589.00 63589.00 1000.00 531 1368.00 2259810.00 13.60 69.60 16.70 -0.65 1136000.00 1872000 731000 1030000 41 9.43 13.64
LH Lithuania 65200.00 90 1613.00 3575439.00 14.90 69.30 15.80 -0.29 1617000.00 4353000 801100 1222000 32 8.87 11.05
LI Liberia 111370.00 96320.00 15050.00 579 1585.00 3195931.00 43.60 53.60 2.70 4.84 160000 6900 1000 2 43.75 22.24
LO Slovakia 48845.00 48800.00 45.00 0 1524.00 5447502.00 16.40 71.50 12.20 0.15 2629000.00 4540000 1197000 2500000 6 10.65 9.48
LS Liechtenstein 160.00 160.00 0.00 0 76.00 34247.00 17.10 70.00 12.80 0.75 29500.00 11400 19900 20000 44 10.02 7.30
LT Lesotho 30355.00 30355.00 0.00 0 909.00 2125262.00 35.70 59.30 5.00 0.14 838000.00 245100 48000 43000 1 24.72 22.49
LU Luxembourg 2586.00 2586.00 0.00 0 359.00 480222.00 18.80 66.60 14.70 1.21 203000.00 720000 244500 315000 8 11.84 8.42
LY Libya 1759540.00 1759540.00 0.00 1770 4348.00 6036914.00 33.40 62.40 4.20 2.26 1787000.00 234800 750000 205000 1 26.09 3.47
MA Madagascar 587040.00 581540.00 5500.00 4828 0.00 19448815.00 43.90 53.00 3.10 3.01 7300000.00 504700 66900 90000 2 38.60 8.51
MC Macau 28.20 28.20 0.00 41 0.34 456989.00 15.40 76.60 8.00 0.84 248000.00 532800 174400 201000 1 8.57 4.59
MD Moldova 33843.00 33371.00 472.00 0 1389.00 4320490.00 16.50 72.60 10.90 -0.11 1339000.00 1090000 929400 406000 2 10.88 10.85
MF Mayotte 374.00 374.00 0.00 185 0.00 208783.00 45.80 52.50 1.80 3.62 44560.00 48100 10000 40.35 7.53
MG Mongolia 1564116.00 0 8220.00 2951786.00 28.70 67.40 3.90 1.49 1577000.00 557200 156000 268300 5 21.07 6.21
MH Montserrat 102.00 102.00 0.00 40 0.00 9538.00 23.50 65.70 10.80 1.05 4521.00 70 17 17.51 7.02
MI Malawi 118480.00 94080.00 24400.00 0 2881.00 13603181.00 46.10 51.20 2.70 2.38 4500000.00 429300 102700 52500 3 42.09 18.25
MJ Montenegro 14026.00 13812.00 214.00 294 625.00 684736.00 -1.00 259100.00 543220 177663 50000 11.18 8.39
MK Macedonia 25333.00 24856.00 477.00 0 766.00 2055915.00 19.80 69.10 11.10 0.26 899000.00 1261000 533200 392671 6 12.02 8.78
ML Mali 1240000.00 1220000.00 20000.00 0 7243.00 11995402.00 48.20 48.80 3.10 2.68 3930000.00 869600 75000 60000 13 49.61 16.51
MN Monaco 1.95 1.95 0.00 4 4.40 32671.00 15.00 62.30 22.70 0.39 44000.00 19300 33700 16000 2 9.12 12.92
MO Morocco 446550.00 446300.00 250.00 1835 2017.90 33757175.00 31.00 63.90 5.10 1.53 11250000.00 12393000 1341000 4600000 8 21.64 5.54
MP Mauritius 2040.00 2030.00 10.00 177 0.00 1250882.00 23.50 69.80 6.70 0.80 555000.00 713300 359000 180000 2 15.26 6.88
MR Mauritania 1030700.00 1030400.00 300.00 754 5074.00 3270065.00 45.50 52.40 2.20 2.87 786000.00 745600 41000 14000 5 40.56 11.89
MT Malta 316.00 316.00 0.00 197 0.00 401880.00 16.70 69.50 13.80 0.41 164000.00 324000 202100 127200 6 10.28 8.19
MU Oman 212460.00 212460.00 0.00 2092 1374.00 3204897.00 42.70 54.60 2.70 3.23 920000.00 1333000 265200 245000 1 35.76 3.78
MV Maldives 300.00 300.00 0.00 644 0.00 369031.00 42.90 54.00 3.10 2.73 101300.00 271053 32181 19000 1 34.20 6.88
MX Mexico 1972550.00 1923040.00 49510.00 9330 4353.00 108700891.00 30.10 64.00 5.90 1.15 38090000.00 47462000 19512000 18622000 51 20.36 4.76
MY Malaysia 329750.00 328550.00 1200.00 4675 2669.00 24821286.00 32.20 62.90 4.80 1.76 10730000.00 19545000 4366000 11016000 7 22.65 5.05
MZ Mozambique 801590.00 784090.00 17500.00 2470 4571.00 20905585.00 44.70 52.50 2.80 1.80 9400000.00 1220000 69700 138000 11 38.54 20.51
NC New Caledonia 19060.00 18575.00 485.00 2254 0.00 221943.00 27.90 65.30 6.80 1.20 78990.00 134300 55300 76000 1 17.75 5.72
NE Niue 260.00 260.00 0.00 64 0.00 1492.00 -0.03 663.00 400 1100 900 1
NF Norfolk Island 34.60 34.60 0.00 32 0.00 2114.00 20.20 63.90 15.90 0.01 0 2532 700 2
NG Niger 1267000.00 1266700.00 300.00 0 5697.00 12894865.00 46.90 50.60 2.40 2.90 70000.00 299900 24000 24000 1 50.16 20.59
NH Vanuatu 12200.00 12200.00 0.00 2528 0.00 211971.00 31.90 64.30 3.80 1.46 76410.00 12700 6800 7500 1 22.35 7.75
NI Nigeria 923768.00 910768.00 13000.00 853 4047.00 135031164.00 42.20 54.70 3.10 2.38 48990000.00 21571000 1223000 5000000 11 40.20 16.68
NL Netherlands 41526.00 33883.00 7643.00 451 1027.00 16570613.00 17.80 67.80 14.40 0.46 7600000.00 15834000 7600000 10806000 52 10.70 8.69
NO Norway 323802.00 307442.00 16360.00 25148 2542.00 4627926.00 19.00 66.10 14.80 0.36 2420000.00 4755000 2129000 3140000 13 11.27 9.37
NP Nepal 147181.00 143181.00 4000.00 0 2926.00 28901790.00 38.30 57.90 3.80 2.13 11110000.00 248800 448600 175000 6 30.46 9.14
NR Nauru 21.00 21.00 0.00 30 0.00 13528.00 36.40 61.60 2.00 1.78 1500 1900 300 1 24.47 6.65
NS Suriname 163270.00 161470.00 1800.00 386 1703.00 470784.00 28.00 65.70 6.20 1.10 156700.00 232800 81100 30000 2 17.31 5.50
NT Netherlands Antilles 960.00 960.00 0.00 364 15.00 223652.00 23.60 67.40 9.00 0.78 83600.00 200000 81000 2000 6 14.56 6.39
NU Nicaragua 129494.00 120254.00 9240.00 910 1231.00 5675356.00 35.50 61.30 3.20 1.86 2261000.00 1119000 220900 140000 3 24.12 4.42
NZ New Zealand 268680.00 268021.00 15134 0.00 4115771.00 20.80 67.30 11.90 0.95 2180000.00 3530000 1800000 3200000 36 13.61 7.54
OO Southern Ocean 20327000.00 17968 0.00
PA Paraguay 406750.00 397300.00 9450.00 0 3995.00 6669086.00 37.20 57.70 5.10 2.42 2742000.00 1887000 320300 200000 4 28.77 4.54
PC Pitcairn Islands 47.00 47.00 0.00 51 0.00 48.00 0.00 15.00 1
PE Peru 1285220.00 1280000.00 5220.00 2414 7461.00 28674757.00 30.30 64.20 5.40 1.29 9210000.00 5583000 2250000 4600000 10 20.09 6.21
PF Paracel Islands 0.00 518 0.00 0.00
PG Spratly Islands 0.00 926 0.00 0.00
PK Pakistan 803940.00 778720.00 25220.00 1046 6774.00 164741924.00 36.90 58.80 4.30 1.83 48290000.00 48289136 5162798 10500000 30 27.52 8.00
PL Poland 312685.00 304465.00 8220.00 491 3056.00 38518241.00 15.50 71.10 13.30 -0.05 17260000.00 29166000 11803000 10600000 19 9.94 9.94
PM Panama 78200.00 75990.00 2210.00 2490 555.00 3242173.00 30.00 63.60 6.40 1.56 1441000.00 1352000 440100 300000 6 21.45 5.44
PO Portugal 92391.00 91951.00 440.00 1793 1214.00 10642836.00 16.50 66.30 17.30 0.33 5580000.00 11448000 4234000 7783000 16 10.59 10.56
PP Papua New Guinea 462840.00 452860.00 9980.00 5152 820.00 5795887.00 37.60 58.50 3.90 2.16 3477000.00 26000 62000 170000 3 28.76 7.14
PS Palau 458.00 458.00 0.00 1519 0.00 20842.00 26.00 69.20 4.70 1.23 9777.00 1000 6700 1 17.70 6.77
PU Guinea-Bissau 36120.00 28000.00 8120.00 350 724.00 1472780.00 41.20 55.80 3.00 2.05 480000.00 67000 10600 26000 2 36.81 16.29
QA Qatar 11437.00 11437.00 0.00 563 60.00 907229.00 23.10 72.90 4.00 2.39 508000.00 854900 205400 219000 1 15.56 4.82
RB Serbia 88361.00 88361.00 0.00 0 2027.00 10150265.00 2961000.00 5229000 2685000 1400000
RM Marshall Islands 11854.30 181.30 11673.00 370 0.00 61815.00 38.30 58.90 2.80 2.21 14680.00 1198 5510 2000 1 32.37 4.66
RO Romania 237500.00 230340.00 7160.00 225 2508.00 22276056.00 15.60 69.60 14.70 -0.13 9330000.00 13354000 4391000 4940000 38 10.67 11.81
RP Philippines 300000.00 298170.00 1830.00 36289 0.00 91077287.00 34.50 61.30 4.10 1.76 35790000.00 32810000 3438000 7820000 33 24.48 5.36
RQ Puerto Rico 13790.00 8870.00 4921.00 501 0.00 3944259.00 21.00 65.90 13.10 0.39 1300000.00 2682000 1112000 1000000 76 12.79 7.78
RS Russia 17075200.00 16995800.00 79400.00 37653 20096.50 141377752.00 14.60 71.10 14.40 -0.48 73880000.00 120000000 40100000 23700000 300 10.92 16.04
RW Rwanda 26338.00 24948.00 1390.00 0 893.00 9907509.00 41.90 55.70 2.50 2.77 4600000.00 290000 23000 38000 2 40.16 14.91
SA Saudi Arabia 2149690.00 2149690.00 0.00 2640 4431.00 27601038.00 38.20 59.40 2.40 2.06 7125000.00 13300000 4500000 3200000 22 29.10 2.55
SB Saint Pierre and Miquelon 242.00 242.00 0.00 120 0.00 7036.00 23.00 65.90 11.10 0.13 3450.00 4800 1 13.08 6.82
SC Saint Kitts and Nevis 261.00 261.00 0.00 135 0.00 39349.00 27.20 64.90 7.90 0.62 18170.00 10000 25000 10000 16 17.89 8.16
SE Seychelles 455.00 455.00 0.00 491 0.00 81895.00 25.40 68.50 6.10 0.43 30900.00 57000 21400 20000 1 15.83 6.25
SF South Africa 1219912.00 1219912.00 0.00 2798 4862.00 43997828.00 29.10 65.50 5.40 -0.46 16090000.00 33960000 4729000 5100000 150 17.94 22.45
SG Senegal 196190.00 192000.00 4190.00 531 2640.00 12521851.00 42.00 55.00 3.00 2.65 4749000.00 1730000 266600 540000 1 37.40 10.96
SH Saint Helena 413.00 0.00 60 0.00 7543.00 18.70 71.10 10.20 0.53 2486.00 2200 1000 1 11.93 6.63
SI Slovenia 20273.00 20151.00 122.00 47 1382.00 2009245.00 13.70 70.30 16.00 -0.07 1026000.00 1759000 816400 1090000 11 9.00 10.41
SL Sierra Leone 71740.00 71620.00 120.00 402 958.00 6144562.00 44.80 52.00 3.20 2.29 1369000.00 113200 24000 10000 1 45.41 22.64
SM San Marino 61.20 61.20 0.00 0 39.00 29615.00 16.80 66.10 17.10 1.22 20470.00 16800 20600 14300 2 9.89 8.27
SN Singapore 692.70 682.70 10.00 193 0.00 4553009.00 15.20 76.30 8.50 1.28 2400000.00 4385000 1848000 2422000 9 9.17 4.40
SO Somalia 637657.00 627337.00 10320.00 3025 2340.00 9118773.00 44.40 53.00 2.60 2.83 3700000.00 500000 100000 90000 3 44.60 16.28
SP Spain 504782.00 499542.00 5240.00 4964 1917.80 40448191.00 14.40 67.80 17.80 0.12 21770000.00 41328000 18322000 19205000 56 9.98 9.81
0.00 6852.00
ST Saint Lucia 616.00 606.00 10.00 158 0.00 170649.00 29.40 65.50 5.10 1.30 43800.00 93000 51100 55000 15 19.28 5.03
SU Sudan 2505810.00 2376000.00 129810.00 853 7687.00 39379358.00 41.60 56.00 2.40 2.08 7415000.00 1828000 670000 2800000 2 34.86 14.39
SV Svalbard 61020.00 61020.00 0.00 3587 0.00 2214.00 -0.01 13
SW Sweden 449964.00 410934.00 39030.00 3218 2233.00 9031088.00 16.40 65.70 17.90 0.16 4590000.00 8436000 6447000 6800000 29 10.20 10.27
SX South Georgia and the South Sandwich Islands 3903.00 3903.00 0.00 0.00 0.00
SY Syria 185180.00 184050.00 1130.00 193 2253.00 19314747.00 36.50 60.10 3.30 2.24 5505000.00 3128000 2903000 1100000 1 27.19 4.74
SZ Switzerland 41290.00 39770.00 1520.00 0 1852.00 7554661.00 16.10 68.20 15.80 0.38 3810000.00 6847000 5123000 5098000 44 9.66 8.51
TD Trinidad and Tobago 5128.00 5128.00 0.00 362 0.00 1056608.00 19.50 71.60 8.90 -0.88 618000.00 800000 323500 160000 17 13.07 10.76
TH Thailand 514000.00 511770.00 2230.00 3219 4863.00 65068149.00 21.60 70.10 8.20 0.66 36410000.00 27379000 7035000 8420000 15 13.73 7.10
TI Tajikistan 143100.00 142700.00 400.00 0 3651.00 7076598.00 35.00 61.20 3.80 1.90 3700000.00 265000 245200 5000 4 27.33 7.05
TK Turks and Caicos Islands 430.00 430.00 0.00 389 0.00 21746.00 31.30 64.80 3.90 2.72 4848.00 1700 5700 14 21.48 4.23
TL Tokelau 10.00 10.00 0.00 101 0.00 1449.00 42.00 53.00 5.00 -0.02 440.00 0 300 1
TN Tonga 748.00 718.00 30.00 419 0.00 116921.00 34.60 61.20 4.20 1.85 33910.00 16400 11200 3000 2 23.67 5.20
TO Togo 56785.00 54385.00 2400.00 56 1647.00 5701579.00 42.00 55.30 2.70 2.72 1302000.00 443600 58600 300000 3 36.83 9.65
TP Sao Tome and Principe 1001.00 1001.00 0.00 209 0.00 199579.00 47.30 49.00 3.70 3.13 35050.00 12000 7000 20000 1 39.72 6.28
TS Tunisia 163610.00 155360.00 8250.00 1148 1424.00 10276158.00 24.00 69.20 6.90 0.99 3502000.00 5681000 1258000 953800 1 15.54 5.17
TT East Timor 15007.00 706 228.00 1084971.00 35.70 61.10 3.20 2.06 1000 26.77 6.19
TU Turkey 780580.00 770760.00 9820.00 7200 2648.00 71158647.00 24.90 68.10 6.90 1.04 24800000.00 43609000 18978000 16000000 50 16.40 6.00
TV Tuvalu 26.00 26.00 0.00 24 0.00 11992.00 29.80 65.20 5.00 1.54 3615.00 0 700 1300 1 22.43 7.00
TW Taiwan 35980.00 32260.00 3720.00 1566 0.00 22858872.00 17.80 72.00 10.20 0.30 10460000.00 22170000 13615000 13210000 8 8.97 6.54
TX Turkmenistan 488100.00 488100.00 0 3736.00 5097028.00 34.70 60.90 4.40 1.62 2320000.00 52000 495000 36000 1 25.36 6.17
TZ Tanzania 945087.00 886037.00 59050.00 1424 3861.00 39384223.00 43.90 53.30 2.80 2.09 19350000.00 1942000 148400 333000 6 35.95 13.36
UG Uganda 236040.00 199710.00 36330.00 0 2698.00 30262610.00 50.20 47.60 2.20 3.57 13760000.00 1525000 100800 500000 2 48.12 12.64
UK United Kingdom 244820.00 241590.00 3230.00 12429 360.00 60776238.00 17.20 67.00 15.80 0.28 31100000.00 61091000 32943000 37600000 10.67 10.09
UM United States Pacific Island Wildlife Refuges 5 360.00 0.00
UP Ukraine 603700.00 603700.00 0.00 2782 4663.00 46299862.00 14.00 69.60 16.30 -0.68 22300000.00 17214000 12142000 5278000 260 9.45 16.07
US United States 9826630.00 9161923.00 664707.00 19924 12034.00 301139947.00 20.20 67.20 12.60 0.89 151400000.00 219400000 268000000 205327000 7000 14.16 8.26
UV Burkina Faso 274200.00 273800.00 400.00 0 3193.00 14326203.00 46.70 50.90 2.50 3.00 5000000.00 572200 97400 64600 1 45.28 15.31
UY Uruguay 176220.00 173620.00 2600.00 660 1648.00 3460607.00 23.00 63.80 13.20 0.50 1270000.00 600000 1000000 680000 14 14.41 9.16
UZ Uzbekistan 447400.00 425400.00 22000.00 0 6221.00 27780059.00 32.40 62.80 4.80 1.73 14440000.00 1100000 1717000 880000 42 26.46 7.73
VC Saint Vincent and the Grenadines 389.00 389.00 0.00 84 0.00 118149.00 25.90 67.60 6.50 0.25 41680.00 70600 22500 8000 15 16.02 5.97
VE Venezuela 912050.00 882050.00 30000.00 2800 4993.00 26023528.00 31.60 63.40 5.10 1.49 12500000.00 12496000 3605000 3040000 16 21.22 5.08
VI British Virgin Islands 153.00 153.00 0.00 80 0.00 23552.00 20.20 74.50 5.40 1.92 12770.00 8000 11700 4000 16 14.82 4.42
VM Vietnam 329560.00 325360.00 4200.00 3444 4639.00 85262356.00 26.30 67.90 5.80 1.00 44580000.00 9593000 15845000 13100000 5 16.63 6.19
VQ Virgin Islands 1910.00 346.00 1564.00 188 0.00 108448.00 21.80 66.50 11.70 -0.17 43980.00 64200 70900 30000 50 13.68 6.59
VT Holy See 0.44 0.44 0.00 0 3.20 821.00 0.00 5120 93
WA Namibia 825418.00 825418.00 0.00 1572 3936.00 2055080.00 37.70 58.60 3.80 0.48 653000.00 495000 127900 75000 2 23.52 19.15
WE West Bank 5860.00 5640.00 220.00 0 404.00 2535927.00 42.40 54.20 3.40 2.99 568000.00 1095000 349000 243000 8 30.99 3.85
WF Wallis and Futuna 274.00 274.00 0.00 129 0.00 16309.00 3104.00 0 1900 900 1
WI Western Sahara 266000.00 266000.00 0.00 1110 2046.00 382617.00 45.40 52.30 2.30 12000.00 0 1
WQ Wake Island 6.50 6.50 0.00 19 0.00 0.00
WS Samoa 2944.00 2934.00 10.00 403 0.00 214265.00 38.10 56.30 5.60 1.29 90000.00 24000 13300 6000 2 28.28 5.88
WZ Swaziland 17363.00 17203.00 160.00 0 535.00 1133066.00 40.30 56.10 3.60 -0.34 300000.00 200000 35000 36000 5 26.98 30.35
XO Indian Ocean 68556000.00 66526 535.00
XQ Arctic Ocean 14056000.00 45389 535.00
YM Yemen 527970.00 527970.00 0.00 1906 1746.00 22230531.00 46.30 51.10 2.60 3.46 5759000.00 2075000 900000 220000 1 42.67 8.05
ZA Zambia 752614.00 740724.00 11890.00 0 5664.00 11477447.00 45.70 51.90 2.40 1.66 4903000.00 946600 94700 231000 5 40.78 21.46
ZH Atlantic Ocean 76762000.00 111866 5664.00
ZI Zimbabwe 390580.00 386670.00 3910.00 0 3066.00 12311143.00 37.20 59.30 3.50 0.60 3958000.00 699000 328000 1000000 6 27.72 21.76
ZN Pacific Ocean 155557000.00 135663 3066.00
ZZ Iles Eparses 35 3066.00 0.00
1 id name total_area land_area water_area coastline total_border population p_young p_adult p_old p_growth labor_force phone_mobiles phone_mainlines internet_users isps birth_rate death_rate
2 AA Aruba 193.00 193.00 0.00 69 0.00 100018.00 19.70 70.20 10.10 1.52 41500.00 98400 37100 24000 12.83 7.61
3 AC Antigua and Barbuda 442.60 442.60 0.00 153 0.00 69481.00 27.30 69.00 3.70 0.53 30000.00 54000 38000 20000 16 16.62 5.31
4 TC United Arab Emirates 83600.00 83600.00 0.00 1318 867.00 4444011.00 20.60 78.50 0.90 4.00 2968000.00 4535000 1237000 1397000 1 16.09 2.16
5 AF Afghanistan 647500.00 647500.00 0.00 0 5529.00 31889923.00 44.60 53.00 2.40 2.63 15000000.00 1400000 280000 30000 1 46.21 19.96
6 AG Algeria 2381740.00 2381740.00 0.00 998 6343.00 33333216.00 27.20 67.90 4.80 1.22 9310000.00 13661000 2572000 1920000 2 17.11 4.62
7 AJ Azerbaijan 86600.00 86100.00 500.00 0 2013.00 8120247.00 25.40 67.70 7.00 0.69 5191000.00 2242000 1091000 678800 2 17.47 8.35
8 AL Albania 28748.00 27398.00 1350.00 362 720.00 3600523.00 24.10 66.60 9.30 0.53 1090000.00 1259000 255000 75000 10 15.16 5.33
9 AM Armenia 29800.00 28400.00 1400.00 0 1254.00 2971650.00 19.50 69.30 11.20 -0.13 1200000.00 320000 600000 150000 9 12.34 8.29
10 AN Andorra 468.00 468.00 0.00 0 120.30 71822.00 14.50 71.20 14.30 0.84 42420.00 64600 35400 21900 1 8.45 6.45
11 AO Angola 1246700.00 1246700.00 0.00 1600 5198.00 12263596.00 43.70 53.50 2.80 2.18 6393000.00 1094000 94300 172000 1 44.51 24.81
12 AQ American Samoa 199.00 199.00 0.00 116 0.00 57663.00 33.60 63.50 2.90 -0.26 17630.00 2377 15000 1 21.83 3.24
13 AR Argentina 2766890.00 2736690.00 30200.00 4989 9861.00 40301927.00 24.90 64.40 10.70 0.94 15350000.00 22100000 8800000 10000000 33 16.53 7.55
14 AS Australia 7686850.00 7617930.00 68920.00 25760 0.00 20434176.00 19.30 67.40 13.20 0.82 10660000.00 18420000 11460000 14664000 571 12.02 7.56
15 AT Ashmore and Cartier Islands 5.00 5.00 0.00 74 0.00 0.00
16 AU Austria 83870.00 82444.00 1426.00 0 2562.00 8199783.00 15.10 67.50 17.50 0.08 3880000.00 8160000 3705000 4650000 37 8.69 9.84
17 AV Anguilla 102.00 102.00 0.00 61 0.00 13677.00 22.30 70.80 6.90 1.38 6049.00 1800 6200 3000 16 13.97 5.34
18 AX Akrotiri 123.00 56 47.40 0.00
19 AY Antarctica 14000000.00 14000000.00 17968 0.00 0.00 0
20 BA Bahrain 665.00 665.00 0.00 161 0.00 708573.00 26.90 69.50 3.70 1.39 352000.00 748700 196500 152700 1 17.53 4.21
21 BB Barbados 431.00 431.00 0.00 97 0.00 280946.00 19.70 71.40 8.90 0.37 128500.00 206200 134900 160000 19 12.61 8.61
22 BC Botswana 600370.00 585370.00 15000.00 0 4013.00 1815508.00 35.80 60.30 3.90 1.50 288400.00 823100 132000 60000 11 23.17 13.63
23 BD Bermuda 53.30 53.30 0.00 103 0.00 66163.00 18.30 69.20 12.50 0.58 38360.00 49000 56000 39000 20 11.26 7.84
24 BE Belgium 30528.00 30278.00 250.00 67 1385.00 10392226.00 16.50 66.10 17.40 0.12 4890000.00 9460000 4801000 5100000 61 10.29 10.32
25 BF The Bahamas 13940.00 10070.00 3870.00 3542 0.00 305655.00 27.00 66.50 6.50 0.60 176300.00 186000 139900 93000 19 17.30 9.13
26 BG Bangladesh 144000.00 133910.00 10090.00 580 4246.00 150448339.00 33.10 63.40 3.50 2.06 68000000.00 9000000 1070000 300000 10 29.36 8.13
27 BH Belize 22966.00 22806.00 160.00 386 516.00 294385.00 38.90 57.50 3.50 2.26 113000.00 93100 33300 35000 2 28.34 5.76
28 BK Bosnia and Herzegovina 51129.00 51129.00 0.00 20 1459.00 4552198.00 15.00 70.40 14.60 1.00 1026000.00 1594000 968900 806400 3 8.80 8.42
29 BL Bolivia 1098580.00 1084390.00 14190.00 0 6940.00 9119152.00 34.30 61.10 4.60 1.42 4300000.00 2421000 646300 480000 9 22.82 7.44
30 BM Burma 678500.00 657740.00 20760.00 1930 5876.00 47373958.00 26.10 68.60 5.30 0.82 28490000.00 183400 476200 78000 1 17.48 9.33
31 BN Benin 112620.00 110620.00 2000.00 121 1989.00 8078314.00 43.90 53.70 2.40 2.67 3211000.00 386700 76300 425000 4 38.10 11.94
32 BO Belarus 207600.00 207600.00 0.00 0 2900.00 9724723.00 14.70 70.40 14.90 -0.41 4300000.00 4098000 3284300 3394000 23 9.50 13.98
33 BP Solomon Islands 28450.00 27540.00 910.00 5313 0.00 566842.00 40.70 55.90 3.30 2.54 249200.00 6000 7400 8400 1 29.27 3.87
34 BQ Navassa Island 5.40 5.40 0.00 8 0.00 0.00
35 BR Brazil 8511965.00 8456510.00 55455.00 7491 16885.00 190010647.00 25.30 68.40 6.30 1.01 96340000.00 86210000 42382000 25900000 50 16.30 6.19
36 BT Bhutan 47000.00 47000.00 0.00 0 1075.00 2327849.00 38.60 57.40 4.00 2.08 37800 32700 25000 33.28 12.46
37 BU Bulgaria 110910.00 110550.00 360.00 354 1808.00 7322858.00 13.90 68.70 17.40 -0.84 3510000.00 6245000 2483000 2200000 200 9.62 14.28
38 BV Bouvet Island 49.00 49.00 0.00 30 0.00 0.00
39 BX Brunei 5770.00 5270.00 500.00 161 381.00 374577.00 27.80 69.00 3.20 1.81 180400.00 205900 90000 56000 2 18.56 3.26
40 BY Burundi 27830.00 25650.00 2180.00 0 974.00 8390505.00 46.30 51.20 2.60 3.59 2990000.00 153000 27700 25000 1 41.97 13.17
41 CA Canada 9984670.00 9093507.00 891163.00 202080 8893.00 33390141.00 17.30 69.20 13.50 0.87 17590000.00 16600000 18276000 21900000 760 10.75 7.86
42 CB Cambodia 181040.00 176520.00 4520.00 443 2572.00 13995904.00 34.00 62.40 3.60 1.73 7000000.00 1062000 36400 41000 2 25.53 8.24
43 CD Chad 1284000.00 1259200.00 24800.00 0 5968.00 9885661.00 47.30 49.80 2.90 2.32 2719000.00 210000 13000 35000 1 42.35 16.69
44 CE Sri Lanka 65610.00 64740.00 870.00 1340 0.00 20926315.00 24.30 67.90 7.80 0.98 7500000.00 4284000 1510000 280000 5 17.00 6.01
45 CF Republic of the Congo 342000.00 341500.00 500.00 169 5504.00 3800610.00 46.30 50.80 2.90 2.64 490000 13800 36000 1 42.16 12.59
46 CG Democratic Republic of the Congo 2345410.00 2267600.00 77810.00 37 10730.00 65751512.00 47.60 49.90 2.60 3.39 15000000.00 2746000 10600 140600 1 42.96 10.34
47 CH China 9596960.00 9326410.00 270550.00 14500 22117.00 1321851888.00 20.40 71.70 7.90 0.61 798000000.00 437480000 350433000 123000000 3 13.45 7.00
48 CI Chile 756950.00 748800.00 8150.00 6435 6339.00 16284741.00 24.10 67.40 8.50 0.92 6940000.00 10570000 3436000 6700000 7 15.03 5.87
49 CJ Cayman Islands 262.00 262.00 0.00 160 0.00 46600.00 20.30 71.00 8.60 2.50 23450.00 17000 38000 9909 16 12.60 4.98
50 CK Cocos Islands 14.00 14.00 0.00 26 0.00 596.00 0.00 287 2
51 CM Cameroon 475440.00 469440.00 6000.00 402 4591.00 18060382.00 41.30 55.50 3.20 2.24 6394000.00 2259000 99400 167000 1 35.07 12.66
52 CN Comoros 2170.00 2170.00 0.00 340 0.00 711417.00 42.60 54.40 3.00 2.84 144500.00 16100 16900 20000 1 36.35 7.95
53 CO Colombia 1138910.00 1038700.00 100210.00 3208 6309.00 44379598.00 29.80 64.80 5.40 1.43 20810000.00 21850000 7678800 4739000 18 20.16 5.54
54 CQ Northern Mariana Islands 477.00 477.00 0.00 1482 0.00 84546.00 18.90 79.50 1.60 2.46 44470.00 20500 21000 10000 1 19.27 2.29
55 CR Coral Sea Islands 0.00 3095 0.00 0.00
56 CS Costa Rica 51100.00 50660.00 440.00 1290 639.00 4133884.00 27.80 66.40 5.80 1.41 1866000.00 1101000 1388000 1000000 3 18.02 4.39
57 CT Central African Republic 622984.00 622984.00 0.00 0 5203.00 4369038.00 41.60 54.20 4.10 1.51 60000 10000 9000 1 33.52 18.46
58 CU Cuba 110860.00 110860.00 0.00 3735 29.00 11394043.00 18.80 70.50 10.70 0.27 4820000.00 134500 849900 190000 5 11.44 7.14
59 CV Cape Verde 4033.00 4033.00 0.00 965 0.00 423613.00 36.90 56.40 6.70 0.61 120600.00 81700 71400 25000 1 24.40 6.50
60 CW Cook Islands 236.70 236.70 0.00 120 0.00 21750.00 34.10 59.50 6.40 -1.20 6820.00 1500 6200 3600 3 21.00
61 CY Cyprus 9250.00 9240.00 10.00 648 0.00 788457.00 19.90 68.30 11.80 0.53 298000 6 12.56 7.72
62 DA Denmark 43094.00 42394.00 700.00 7314 68.00 5468120.00 18.60 66.00 15.40 0.31 2910000.00 5469000 3350000 3763000 13 10.91 10.30
63 DJ Djibouti 23000.00 22980.00 20.00 314 516.00 496374.00 43.40 53.20 3.40 1.98 282000.00 34500 11100 9000 1 39.07 19.23
64 DO Dominica 754.00 754.00 0.00 148 0.00 72386.00 25.60 64.20 10.20 0.18 25000.00 41800 21000 20500 16 15.75 8.44
65 DR Dominican Republic 48730.00 48380.00 350.00 1288 360.00 9365818.00 32.10 62.20 5.70 1.50 3896000.00 3623000 894500 938300 24 22.91 5.32
66 DX Dhekelia 130.80 28 360.00
67 EC Ecuador 283560.00 276840.00 6720.00 2237 2010.00 13755680.00 32.60 62.30 5.10 1.55 4570000.00 6246000 1701000 616000 31 21.91 4.21
68 EE European Union 4324782.00 65993 12440.80 490426060.00 15.72 67.16 17.11 0.16 222700000.00 466000000 238000000 247000000 10.00 10.00
69 EG Egypt 1001450.00 995450.00 6000.00 2450 2665.00 80335036.00 32.20 63.20 4.60 1.72 21800000.00 14045000 10396000 5000000 50 22.53 5.11
70 EI Ireland 70280.00 68890.00 1390.00 1448 360.00 4109086.00 20.80 67.50 11.70 1.14 2120000.00 4210000 2033000 2060000 22 14.40 7.79
71 EK Equatorial Guinea 28051.00 28051.00 0.00 296 539.00 551201.00 41.50 54.80 3.80 2.02 96900 10000 5000 1 35.16 15.01
72 EN Estonia 45226.00 43211.00 2015.00 3794 633.00 1315912.00 15.00 67.50 17.50 -0.64 673000.00 1445000 442000 690000 38 10.17 13.30
73 ER Eritrea 121320.00 121320.00 0.00 2234 1626.00 4906585.00 43.50 52.90 3.60 2.46 58000 37700 70000 5 33.97 9.36
74 ES El Salvador 21040.00 20720.00 320.00 307 545.00 6948073.00 36.10 58.70 5.20 1.70 2856000.00 2412000 971500 637100 4 26.13 5.60
75 ET Ethiopia 1127127.00 1119683.00 7444.00 0 5328.00 76511887.00 43.40 53.80 2.70 2.27 27270000.00 410600 610300 113000 1 37.39 14.67
76 EZ Czech Republic 78866.00 77276.00 1590.00 0 2290.20 10228744.00 14.10 71.20 14.70 -0.07 5310000.00 11776000 3217300 5100000 8.96 10.64
77 FI Finland 338145.00 304473.00 33672.00 1250 2681.00 5238460.00 16.90 66.70 16.40 0.13 2620000.00 5231000 2120000 3286000 3 10.42 9.93
78 FJ Fiji 18270.00 18270.00 0.00 1129 0.00 918675.00 30.90 64.70 4.40 1.39 137000.00 142200 102000 61000 2 22.37 5.66
79 FA Falkland Islands 12173.00 12173.00 0.00 1288 0.00 3105.00 2.44 1724.00 0 2400 1900 2
80 FM Federated States of Micronesia 702.00 702.00 0.00 6112 0.00 107862.00 35.90 61.20 2.90 -0.15 37410.00 14100 12400 14000 1 24.14 4.66
81 FO Faroe Islands 1399.00 1399.00 0.00 1117 0.00 47511.00 20.60 65.30 14.10 0.54 24250.00 42500 23800 33000 2 14.12 8.69
82 FP French Polynesia 4167.00 3660.00 507.00 2525 0.00 278963.00 25.40 68.20 6.30 1.46 65930.00 87000 53400 55000 2 16.41 4.61
83 FR France 643427.00 640053.00 3374.00 4668 0.00 18.60 65.20 16.20 0.59 27880000.00 49370000 38433000 29945000 62 12.91 8.55
84 FS French Southern and Antarctic Lands 28 0.00 0.00
85 GA The Gambia 11300.00 10000.00 1300.00 80 740.00 1688359.00 44.10 53.20 2.80 2.78 400000.00 247500 44000 49000 2 38.86 11.99
86 GB Gabon 267667.00 257667.00 10000.00 885 2551.00 1454867.00 42.10 53.90 4.00 2.04 581000.00 649800 39100 67000 1 35.96 12.45
87 GG Georgia 69700.00 69700.00 0.00 310 1461.00 4646003.00 16.70 66.60 16.70 -0.33 2040000.00 1459000 683200 175600 6 10.54 9.37
88 GH Ghana 239460.00 230940.00 8520.00 539 2094.00 22931299.00 38.20 58.20 3.60 1.97 10870000.00 2842000 321500 401300 12 29.85 9.55
89 GI Gibraltar 6.50 6.50 0.00 12 1.20 27967.00 17.20 66.30 16.50 0.13 12690.00 9797 24512 6200 2 10.69 9.40
90 GJ Grenada 344.00 344.00 0.00 121 0.00 89971.00 32.80 64.10 3.10 0.34 42300.00 43300 32700 19000 14 21.87 6.61
91 GK Guernsey 78.00 78.00 0.00 50 0.00 65573.00 14.80 67.40 17.80 0.24 31470.00 43800 55100 36000 8.65 10.07
92 GL Greenland 2166086.00 2166086.00 44087 0.00 56344.00 24.00 69.10 6.90 -0.03 32120.00 32200 25300 38000 1 16.01 7.93
93 GM Germany 357021.00 349223.00 7798.00 2389 3621.00 82400996.00 13.90 66.30 19.80 -0.03 43660000.00 79200000 55046000 50616000 200 8.20 10.71
94 GQ Guam 541.30 541.30 0.00 126 0.00 173456.00 28.60 64.50 6.90 1.40 62050.00 98000 84134 79000 20 18.56 4.56
95 GR Greece 131940.00 130800.00 1140.00 13676 1228.00 10706290.00 14.30 66.70 19.00 0.16 4880000.00 10043000 6303000 3800000 27 9.62 10.33
96 GT Guatemala 108890.00 108430.00 460.00 400 1687.00 12728111.00 40.80 55.50 3.60 2.15 5020000.00 3168000 1132000 756000 5 29.09 5.27
97 GV Guinea 245857.00 245857.00 0.00 320 3399.00 9947814.00 44.30 52.50 3.20 2.62 3700000.00 189000 26200 46000 4 41.53 15.33
98 GY Guyana 214970.00 196850.00 18120.00 459 2949.00 769095.00 26.10 68.60 5.30 0.23 418000.00 281400 110100 160000 3 18.09 8.28
99 GZ Gaza Strip 360.00 360.00 0.00 40 62.00 1482405.00 47.60 49.90 2.50 3.66 259000.00 1095000 349000 243000 3 38.90 3.74
100 HA Haiti 27750.00 27560.00 190.00 1771 360.00 8706497.00 42.10 54.40 3.50 2.45 3600000.00 400000 140000 500000 3 35.87 10.40
101 HK Hong Kong 1092.00 1042.00 50.00 733 30.00 6980412.00 13.00 74.00 12.90 0.56 3630000.00 8693000 3795000 4879000 17 7.34 6.45
102 HM Heard Island and McDonald Islands 412.00 412.00 0.00 102 0.00 0.00
103 HO Honduras 112090.00 111890.00 200.00 820 1520.00 7483763.00 39.30 57.20 3.50 2.09 2589000.00 1282000 494400 223000 8 27.59 5.32
104 HR Croatia 56542.00 56414.00 128.00 5835 2197.00 4493312.00 16.00 67.10 16.90 -0.04 1720000.00 2984000 1890000 1451000 9 9.63 11.57
105 HU Hungary 93030.00 92340.00 690.00 0 2171.00 9956108.00 15.30 69.30 15.40 -0.25 4200000.00 9320000 3356000 3050000 16 9.66 13.05
106 IC Iceland 103000.00 100250.00 2750.00 4970 0.00 301931.00 21.40 66.80 11.80 0.82 173000.00 304000 193900 258000 20 13.57 6.77
107 ID Indonesia 1919440.00 1826440.00 93000.00 54716 2830.00 234693997.00 28.70 65.60 5.70 1.21 108200000.00 46910000 12772000 16000000 24 19.65 6.25
108 IM Isle of Man 572.00 572.00 0.00 160 0.00 75831.00 17.10 65.80 17.10 0.51 39690.00 51000 10.96 11.10
109 IN India 3287590.00 2973190.00 314400.00 7000 14103.00 1129866154.00 31.80 63.10 5.10 1.61 509300000.00 69193000 49750000 60000000 43 22.69 6.58
110 IO British Indian Ocean Territory 54400.00 60.00 54340.00 698 0.00 0.00 1
111 IP Clipperton Island 6.00 6.00 0.00 11 0.00 0.00
112 IR Iran 1648000.00 1636000.00 12000.00 2440 5440.00 65397521.00 23.20 71.40 5.40 0.66 24360000.00 8500000 18986000 7500000 100 16.57 5.65
113 IS Israel 20770.00 20330.00 440.00 273 1017.00 6426679.00 26.10 64.20 9.80 1.15 2600000.00 7757000 2936000 3700000 21 17.71 6.17
114 IT Italy 301230.00 294020.00 7210.00 7600 1932.20 58147733.00 13.80 66.40 19.90 0.01 24630000.00 72200000 25049000 28870000 93 8.54 10.50
115 IV Cote d'Ivoire 322460.00 318000.00 4460.00 515 3110.00 18013409.00 40.60 56.60 2.80 2.00 6738000.00 2190000 257900 160000 5 34.69 14.74
116 IZ Iraq 437072.00 432162.00 4910.00 58 3650.00 27499638.00 39.40 57.60 3.00 2.62 7400000.00 8700000 1547000 36000 1 31.44 5.26
117 JA Japan 377835.00 374744.00 3091.00 29751 0.00 127433494.00 13.80 65.20 21.00 -0.09 66440000.00 94745000 58780000 86300000 73 8.10 8.98
118 JE Jersey 116.00 116.00 0.00 70 0.00 91321.00 16.90 67.30 15.80 0.24 53560.00 83900 73900 27000 9.02 9.32
119 JM Jamaica 10991.00 10831.00 160.00 1022 0.00 2780132.00 32.50 60.10 7.40 0.78 1100000.00 2700000 342000 1067000 21 20.44 6.59
120 JN Jan Mayen 377.00 377.00 0.00 124 0.00 0.00 13
121 JO Jordan 92300.00 91971.00 329.00 26 1635.00 6053193.00 33.00 63.00 4.00 2.41 1512000.00 3013000 628200 629500 5 20.69 2.68
122 KE Kenya 582650.00 569250.00 13400.00 536 3477.00 36913721.00 42.10 55.20 2.60 2.80 1955000.00 6500000 281800 1055000 65 38.94 10.95
123 KG Kyrgyzstan 198500.00 191300.00 7200.00 0 3878.00 5284149.00 30.30 63.50 6.20 1.35 2700000.00 541700 438200 280000 23.08 7.02
124 KN North Korea 120540.00 120410.00 130.00 2495 1673.00 23301725.00 23.30 68.10 8.50 0.79 9600000.00 980000 1 15.06 7.21
125 KR Kiribati 811.00 811.00 0.00 1143 0.00 107817.00 38.20 58.40 3.40 2.24 7870.00 600 4500 2000 1 30.48 8.12
126 KS South Korea 98480.00 98190.00 290.00 2413 238.00 49044790.00 18.30 72.10 9.60 0.39 23770000.00 38342000 23745000 33900000 11 9.93 5.99
127 KT Christmas Island 135.00 135.00 0.00 139 0.00 1402.00 0.00 464 2
128 KU Kuwait 17820.00 17820.00 0.00 499 462.00 2505559.00 26.70 70.50 2.80 3.56 1136000.00 2536000 510300 700000 3 21.95 2.39
129 KZ Kazakhstan 2717300.00 2669800.00 47500.00 0 12012.00 15284929.00 22.50 69.20 8.30 0.35 7834000.00 4955000 2500000 400000 10 16.23 9.40
130 LA Laos 236800.00 230800.00 6000.00 0 5083.00 6521998.00 41.20 55.70 3.10 2.37 2100000.00 520546 90067 25000 1 34.98 11.28
131 LE Lebanon 10400.00 10230.00 170.00 225 454.00 3925502.00 26.20 66.70 7.10 1.20 1500000.00 1178000 990000 700000 22 18.08 6.10
132 LG Latvia 64589.00 63589.00 1000.00 531 1368.00 2259810.00 13.60 69.60 16.70 -0.65 1136000.00 1872000 731000 1030000 41 9.43 13.64
133 LH Lithuania 65200.00 90 1613.00 3575439.00 14.90 69.30 15.80 -0.29 1617000.00 4353000 801100 1222000 32 8.87 11.05
134 LI Liberia 111370.00 96320.00 15050.00 579 1585.00 3195931.00 43.60 53.60 2.70 4.84 160000 6900 1000 2 43.75 22.24
135 LO Slovakia 48845.00 48800.00 45.00 0 1524.00 5447502.00 16.40 71.50 12.20 0.15 2629000.00 4540000 1197000 2500000 6 10.65 9.48
136 LS Liechtenstein 160.00 160.00 0.00 0 76.00 34247.00 17.10 70.00 12.80 0.75 29500.00 11400 19900 20000 44 10.02 7.30
137 LT Lesotho 30355.00 30355.00 0.00 0 909.00 2125262.00 35.70 59.30 5.00 0.14 838000.00 245100 48000 43000 1 24.72 22.49
138 LU Luxembourg 2586.00 2586.00 0.00 0 359.00 480222.00 18.80 66.60 14.70 1.21 203000.00 720000 244500 315000 8 11.84 8.42
139 LY Libya 1759540.00 1759540.00 0.00 1770 4348.00 6036914.00 33.40 62.40 4.20 2.26 1787000.00 234800 750000 205000 1 26.09 3.47
140 MA Madagascar 587040.00 581540.00 5500.00 4828 0.00 19448815.00 43.90 53.00 3.10 3.01 7300000.00 504700 66900 90000 2 38.60 8.51
141 MC Macau 28.20 28.20 0.00 41 0.34 456989.00 15.40 76.60 8.00 0.84 248000.00 532800 174400 201000 1 8.57 4.59
142 MD Moldova 33843.00 33371.00 472.00 0 1389.00 4320490.00 16.50 72.60 10.90 -0.11 1339000.00 1090000 929400 406000 2 10.88 10.85
143 MF Mayotte 374.00 374.00 0.00 185 0.00 208783.00 45.80 52.50 1.80 3.62 44560.00 48100 10000 40.35 7.53
144 MG Mongolia 1564116.00 0 8220.00 2951786.00 28.70 67.40 3.90 1.49 1577000.00 557200 156000 268300 5 21.07 6.21
145 MH Montserrat 102.00 102.00 0.00 40 0.00 9538.00 23.50 65.70 10.80 1.05 4521.00 70 17 17.51 7.02
146 MI Malawi 118480.00 94080.00 24400.00 0 2881.00 13603181.00 46.10 51.20 2.70 2.38 4500000.00 429300 102700 52500 3 42.09 18.25
147 MJ Montenegro 14026.00 13812.00 214.00 294 625.00 684736.00 -1.00 259100.00 543220 177663 50000 11.18 8.39
148 MK Macedonia 25333.00 24856.00 477.00 0 766.00 2055915.00 19.80 69.10 11.10 0.26 899000.00 1261000 533200 392671 6 12.02 8.78
149 ML Mali 1240000.00 1220000.00 20000.00 0 7243.00 11995402.00 48.20 48.80 3.10 2.68 3930000.00 869600 75000 60000 13 49.61 16.51
150 MN Monaco 1.95 1.95 0.00 4 4.40 32671.00 15.00 62.30 22.70 0.39 44000.00 19300 33700 16000 2 9.12 12.92
151 MO Morocco 446550.00 446300.00 250.00 1835 2017.90 33757175.00 31.00 63.90 5.10 1.53 11250000.00 12393000 1341000 4600000 8 21.64 5.54
152 MP Mauritius 2040.00 2030.00 10.00 177 0.00 1250882.00 23.50 69.80 6.70 0.80 555000.00 713300 359000 180000 2 15.26 6.88
153 MR Mauritania 1030700.00 1030400.00 300.00 754 5074.00 3270065.00 45.50 52.40 2.20 2.87 786000.00 745600 41000 14000 5 40.56 11.89
154 MT Malta 316.00 316.00 0.00 197 0.00 401880.00 16.70 69.50 13.80 0.41 164000.00 324000 202100 127200 6 10.28 8.19
155 MU Oman 212460.00 212460.00 0.00 2092 1374.00 3204897.00 42.70 54.60 2.70 3.23 920000.00 1333000 265200 245000 1 35.76 3.78
156 MV Maldives 300.00 300.00 0.00 644 0.00 369031.00 42.90 54.00 3.10 2.73 101300.00 271053 32181 19000 1 34.20 6.88
157 MX Mexico 1972550.00 1923040.00 49510.00 9330 4353.00 108700891.00 30.10 64.00 5.90 1.15 38090000.00 47462000 19512000 18622000 51 20.36 4.76
158 MY Malaysia 329750.00 328550.00 1200.00 4675 2669.00 24821286.00 32.20 62.90 4.80 1.76 10730000.00 19545000 4366000 11016000 7 22.65 5.05
159 MZ Mozambique 801590.00 784090.00 17500.00 2470 4571.00 20905585.00 44.70 52.50 2.80 1.80 9400000.00 1220000 69700 138000 11 38.54 20.51
160 NC New Caledonia 19060.00 18575.00 485.00 2254 0.00 221943.00 27.90 65.30 6.80 1.20 78990.00 134300 55300 76000 1 17.75 5.72
161 NE Niue 260.00 260.00 0.00 64 0.00 1492.00 -0.03 663.00 400 1100 900 1
162 NF Norfolk Island 34.60 34.60 0.00 32 0.00 2114.00 20.20 63.90 15.90 0.01 0 2532 700 2
163 NG Niger 1267000.00 1266700.00 300.00 0 5697.00 12894865.00 46.90 50.60 2.40 2.90 70000.00 299900 24000 24000 1 50.16 20.59
164 NH Vanuatu 12200.00 12200.00 0.00 2528 0.00 211971.00 31.90 64.30 3.80 1.46 76410.00 12700 6800 7500 1 22.35 7.75
165 NI Nigeria 923768.00 910768.00 13000.00 853 4047.00 135031164.00 42.20 54.70 3.10 2.38 48990000.00 21571000 1223000 5000000 11 40.20 16.68
166 NL Netherlands 41526.00 33883.00 7643.00 451 1027.00 16570613.00 17.80 67.80 14.40 0.46 7600000.00 15834000 7600000 10806000 52 10.70 8.69
167 NO Norway 323802.00 307442.00 16360.00 25148 2542.00 4627926.00 19.00 66.10 14.80 0.36 2420000.00 4755000 2129000 3140000 13 11.27 9.37
168 NP Nepal 147181.00 143181.00 4000.00 0 2926.00 28901790.00 38.30 57.90 3.80 2.13 11110000.00 248800 448600 175000 6 30.46 9.14
169 NR Nauru 21.00 21.00 0.00 30 0.00 13528.00 36.40 61.60 2.00 1.78 1500 1900 300 1 24.47 6.65
170 NS Suriname 163270.00 161470.00 1800.00 386 1703.00 470784.00 28.00 65.70 6.20 1.10 156700.00 232800 81100 30000 2 17.31 5.50
171 NT Netherlands Antilles 960.00 960.00 0.00 364 15.00 223652.00 23.60 67.40 9.00 0.78 83600.00 200000 81000 2000 6 14.56 6.39
172 NU Nicaragua 129494.00 120254.00 9240.00 910 1231.00 5675356.00 35.50 61.30 3.20 1.86 2261000.00 1119000 220900 140000 3 24.12 4.42
173 NZ New Zealand 268680.00 268021.00 15134 0.00 4115771.00 20.80 67.30 11.90 0.95 2180000.00 3530000 1800000 3200000 36 13.61 7.54
174 OO Southern Ocean 20327000.00 17968 0.00
175 PA Paraguay 406750.00 397300.00 9450.00 0 3995.00 6669086.00 37.20 57.70 5.10 2.42 2742000.00 1887000 320300 200000 4 28.77 4.54
176 PC Pitcairn Islands 47.00 47.00 0.00 51 0.00 48.00 0.00 15.00 1
177 PE Peru 1285220.00 1280000.00 5220.00 2414 7461.00 28674757.00 30.30 64.20 5.40 1.29 9210000.00 5583000 2250000 4600000 10 20.09 6.21
178 PF Paracel Islands 0.00 518 0.00 0.00
179 PG Spratly Islands 0.00 926 0.00 0.00
180 PK Pakistan 803940.00 778720.00 25220.00 1046 6774.00 164741924.00 36.90 58.80 4.30 1.83 48290000.00 48289136 5162798 10500000 30 27.52 8.00
181 PL Poland 312685.00 304465.00 8220.00 491 3056.00 38518241.00 15.50 71.10 13.30 -0.05 17260000.00 29166000 11803000 10600000 19 9.94 9.94
182 PM Panama 78200.00 75990.00 2210.00 2490 555.00 3242173.00 30.00 63.60 6.40 1.56 1441000.00 1352000 440100 300000 6 21.45 5.44
183 PO Portugal 92391.00 91951.00 440.00 1793 1214.00 10642836.00 16.50 66.30 17.30 0.33 5580000.00 11448000 4234000 7783000 16 10.59 10.56
184 PP Papua New Guinea 462840.00 452860.00 9980.00 5152 820.00 5795887.00 37.60 58.50 3.90 2.16 3477000.00 26000 62000 170000 3 28.76 7.14
185 PS Palau 458.00 458.00 0.00 1519 0.00 20842.00 26.00 69.20 4.70 1.23 9777.00 1000 6700 1 17.70 6.77
186 PU Guinea-Bissau 36120.00 28000.00 8120.00 350 724.00 1472780.00 41.20 55.80 3.00 2.05 480000.00 67000 10600 26000 2 36.81 16.29
187 QA Qatar 11437.00 11437.00 0.00 563 60.00 907229.00 23.10 72.90 4.00 2.39 508000.00 854900 205400 219000 1 15.56 4.82
188 RB Serbia 88361.00 88361.00 0.00 0 2027.00 10150265.00 2961000.00 5229000 2685000 1400000
189 RM Marshall Islands 11854.30 181.30 11673.00 370 0.00 61815.00 38.30 58.90 2.80 2.21 14680.00 1198 5510 2000 1 32.37 4.66
190 RO Romania 237500.00 230340.00 7160.00 225 2508.00 22276056.00 15.60 69.60 14.70 -0.13 9330000.00 13354000 4391000 4940000 38 10.67 11.81
191 RP Philippines 300000.00 298170.00 1830.00 36289 0.00 91077287.00 34.50 61.30 4.10 1.76 35790000.00 32810000 3438000 7820000 33 24.48 5.36
192 RQ Puerto Rico 13790.00 8870.00 4921.00 501 0.00 3944259.00 21.00 65.90 13.10 0.39 1300000.00 2682000 1112000 1000000 76 12.79 7.78
193 RS Russia 17075200.00 16995800.00 79400.00 37653 20096.50 141377752.00 14.60 71.10 14.40 -0.48 73880000.00 120000000 40100000 23700000 300 10.92 16.04
194 RW Rwanda 26338.00 24948.00 1390.00 0 893.00 9907509.00 41.90 55.70 2.50 2.77 4600000.00 290000 23000 38000 2 40.16 14.91
195 SA Saudi Arabia 2149690.00 2149690.00 0.00 2640 4431.00 27601038.00 38.20 59.40 2.40 2.06 7125000.00 13300000 4500000 3200000 22 29.10 2.55
196 SB Saint Pierre and Miquelon 242.00 242.00 0.00 120 0.00 7036.00 23.00 65.90 11.10 0.13 3450.00 4800 1 13.08 6.82
197 SC Saint Kitts and Nevis 261.00 261.00 0.00 135 0.00 39349.00 27.20 64.90 7.90 0.62 18170.00 10000 25000 10000 16 17.89 8.16
198 SE Seychelles 455.00 455.00 0.00 491 0.00 81895.00 25.40 68.50 6.10 0.43 30900.00 57000 21400 20000 1 15.83 6.25
199 SF South Africa 1219912.00 1219912.00 0.00 2798 4862.00 43997828.00 29.10 65.50 5.40 -0.46 16090000.00 33960000 4729000 5100000 150 17.94 22.45
200 SG Senegal 196190.00 192000.00 4190.00 531 2640.00 12521851.00 42.00 55.00 3.00 2.65 4749000.00 1730000 266600 540000 1 37.40 10.96
201 SH Saint Helena 413.00 0.00 60 0.00 7543.00 18.70 71.10 10.20 0.53 2486.00 2200 1000 1 11.93 6.63
202 SI Slovenia 20273.00 20151.00 122.00 47 1382.00 2009245.00 13.70 70.30 16.00 -0.07 1026000.00 1759000 816400 1090000 11 9.00 10.41
203 SL Sierra Leone 71740.00 71620.00 120.00 402 958.00 6144562.00 44.80 52.00 3.20 2.29 1369000.00 113200 24000 10000 1 45.41 22.64
204 SM San Marino 61.20 61.20 0.00 0 39.00 29615.00 16.80 66.10 17.10 1.22 20470.00 16800 20600 14300 2 9.89 8.27
205 SN Singapore 692.70 682.70 10.00 193 0.00 4553009.00 15.20 76.30 8.50 1.28 2400000.00 4385000 1848000 2422000 9 9.17 4.40
206 SO Somalia 637657.00 627337.00 10320.00 3025 2340.00 9118773.00 44.40 53.00 2.60 2.83 3700000.00 500000 100000 90000 3 44.60 16.28
207 SP Spain 504782.00 499542.00 5240.00 4964 1917.80 40448191.00 14.40 67.80 17.80 0.12 21770000.00 41328000 18322000 19205000 56 9.98 9.81
208 0.00 6852.00
209 ST Saint Lucia 616.00 606.00 10.00 158 0.00 170649.00 29.40 65.50 5.10 1.30 43800.00 93000 51100 55000 15 19.28 5.03
210 SU Sudan 2505810.00 2376000.00 129810.00 853 7687.00 39379358.00 41.60 56.00 2.40 2.08 7415000.00 1828000 670000 2800000 2 34.86 14.39
211 SV Svalbard 61020.00 61020.00 0.00 3587 0.00 2214.00 -0.01 13
212 SW Sweden 449964.00 410934.00 39030.00 3218 2233.00 9031088.00 16.40 65.70 17.90 0.16 4590000.00 8436000 6447000 6800000 29 10.20 10.27
213 SX South Georgia and the South Sandwich Islands 3903.00 3903.00 0.00 0.00 0.00
214 SY Syria 185180.00 184050.00 1130.00 193 2253.00 19314747.00 36.50 60.10 3.30 2.24 5505000.00 3128000 2903000 1100000 1 27.19 4.74
215 SZ Switzerland 41290.00 39770.00 1520.00 0 1852.00 7554661.00 16.10 68.20 15.80 0.38 3810000.00 6847000 5123000 5098000 44 9.66 8.51
216 TD Trinidad and Tobago 5128.00 5128.00 0.00 362 0.00 1056608.00 19.50 71.60 8.90 -0.88 618000.00 800000 323500 160000 17 13.07 10.76
217 TH Thailand 514000.00 511770.00 2230.00 3219 4863.00 65068149.00 21.60 70.10 8.20 0.66 36410000.00 27379000 7035000 8420000 15 13.73 7.10
218 TI Tajikistan 143100.00 142700.00 400.00 0 3651.00 7076598.00 35.00 61.20 3.80 1.90 3700000.00 265000 245200 5000 4 27.33 7.05
219 TK Turks and Caicos Islands 430.00 430.00 0.00 389 0.00 21746.00 31.30 64.80 3.90 2.72 4848.00 1700 5700 14 21.48 4.23
220 TL Tokelau 10.00 10.00 0.00 101 0.00 1449.00 42.00 53.00 5.00 -0.02 440.00 0 300 1
221 TN Tonga 748.00 718.00 30.00 419 0.00 116921.00 34.60 61.20 4.20 1.85 33910.00 16400 11200 3000 2 23.67 5.20
222 TO Togo 56785.00 54385.00 2400.00 56 1647.00 5701579.00 42.00 55.30 2.70 2.72 1302000.00 443600 58600 300000 3 36.83 9.65
223 TP Sao Tome and Principe 1001.00 1001.00 0.00 209 0.00 199579.00 47.30 49.00 3.70 3.13 35050.00 12000 7000 20000 1 39.72 6.28
224 TS Tunisia 163610.00 155360.00 8250.00 1148 1424.00 10276158.00 24.00 69.20 6.90 0.99 3502000.00 5681000 1258000 953800 1 15.54 5.17
225 TT East Timor 15007.00 706 228.00 1084971.00 35.70 61.10 3.20 2.06 1000 26.77 6.19
226 TU Turkey 780580.00 770760.00 9820.00 7200 2648.00 71158647.00 24.90 68.10 6.90 1.04 24800000.00 43609000 18978000 16000000 50 16.40 6.00
227 TV Tuvalu 26.00 26.00 0.00 24 0.00 11992.00 29.80 65.20 5.00 1.54 3615.00 0 700 1300 1 22.43 7.00
228 TW Taiwan 35980.00 32260.00 3720.00 1566 0.00 22858872.00 17.80 72.00 10.20 0.30 10460000.00 22170000 13615000 13210000 8 8.97 6.54
229 TX Turkmenistan 488100.00 488100.00 0 3736.00 5097028.00 34.70 60.90 4.40 1.62 2320000.00 52000 495000 36000 1 25.36 6.17
230 TZ Tanzania 945087.00 886037.00 59050.00 1424 3861.00 39384223.00 43.90 53.30 2.80 2.09 19350000.00 1942000 148400 333000 6 35.95 13.36
231 UG Uganda 236040.00 199710.00 36330.00 0 2698.00 30262610.00 50.20 47.60 2.20 3.57 13760000.00 1525000 100800 500000 2 48.12 12.64
232 UK United Kingdom 244820.00 241590.00 3230.00 12429 360.00 60776238.00 17.20 67.00 15.80 0.28 31100000.00 61091000 32943000 37600000 10.67 10.09
233 UM United States Pacific Island Wildlife Refuges 5 360.00 0.00
234 UP Ukraine 603700.00 603700.00 0.00 2782 4663.00 46299862.00 14.00 69.60 16.30 -0.68 22300000.00 17214000 12142000 5278000 260 9.45 16.07
235 US United States 9826630.00 9161923.00 664707.00 19924 12034.00 301139947.00 20.20 67.20 12.60 0.89 151400000.00 219400000 268000000 205327000 7000 14.16 8.26
236 UV Burkina Faso 274200.00 273800.00 400.00 0 3193.00 14326203.00 46.70 50.90 2.50 3.00 5000000.00 572200 97400 64600 1 45.28 15.31
237 UY Uruguay 176220.00 173620.00 2600.00 660 1648.00 3460607.00 23.00 63.80 13.20 0.50 1270000.00 600000 1000000 680000 14 14.41 9.16
238 UZ Uzbekistan 447400.00 425400.00 22000.00 0 6221.00 27780059.00 32.40 62.80 4.80 1.73 14440000.00 1100000 1717000 880000 42 26.46 7.73
239 VC Saint Vincent and the Grenadines 389.00 389.00 0.00 84 0.00 118149.00 25.90 67.60 6.50 0.25 41680.00 70600 22500 8000 15 16.02 5.97
240 VE Venezuela 912050.00 882050.00 30000.00 2800 4993.00 26023528.00 31.60 63.40 5.10 1.49 12500000.00 12496000 3605000 3040000 16 21.22 5.08
241 VI British Virgin Islands 153.00 153.00 0.00 80 0.00 23552.00 20.20 74.50 5.40 1.92 12770.00 8000 11700 4000 16 14.82 4.42
242 VM Vietnam 329560.00 325360.00 4200.00 3444 4639.00 85262356.00 26.30 67.90 5.80 1.00 44580000.00 9593000 15845000 13100000 5 16.63 6.19
243 VQ Virgin Islands 1910.00 346.00 1564.00 188 0.00 108448.00 21.80 66.50 11.70 -0.17 43980.00 64200 70900 30000 50 13.68 6.59
244 VT Holy See 0.44 0.44 0.00 0 3.20 821.00 0.00 5120 93
245 WA Namibia 825418.00 825418.00 0.00 1572 3936.00 2055080.00 37.70 58.60 3.80 0.48 653000.00 495000 127900 75000 2 23.52 19.15
246 WE West Bank 5860.00 5640.00 220.00 0 404.00 2535927.00 42.40 54.20 3.40 2.99 568000.00 1095000 349000 243000 8 30.99 3.85
247 WF Wallis and Futuna 274.00 274.00 0.00 129 0.00 16309.00 3104.00 0 1900 900 1
248 WI Western Sahara 266000.00 266000.00 0.00 1110 2046.00 382617.00 45.40 52.30 2.30 12000.00 0 1
249 WQ Wake Island 6.50 6.50 0.00 19 0.00 0.00
250 WS Samoa 2944.00 2934.00 10.00 403 0.00 214265.00 38.10 56.30 5.60 1.29 90000.00 24000 13300 6000 2 28.28 5.88
251 WZ Swaziland 17363.00 17203.00 160.00 0 535.00 1133066.00 40.30 56.10 3.60 -0.34 300000.00 200000 35000 36000 5 26.98 30.35
252 XO Indian Ocean 68556000.00 66526 535.00
253 XQ Arctic Ocean 14056000.00 45389 535.00
254 YM Yemen 527970.00 527970.00 0.00 1906 1746.00 22230531.00 46.30 51.10 2.60 3.46 5759000.00 2075000 900000 220000 1 42.67 8.05
255 ZA Zambia 752614.00 740724.00 11890.00 0 5664.00 11477447.00 45.70 51.90 2.40 1.66 4903000.00 946600 94700 231000 5 40.78 21.46
256 ZH Atlantic Ocean 76762000.00 111866 5664.00
257 ZI Zimbabwe 390580.00 386670.00 3910.00 0 3066.00 12311143.00 37.20 59.30 3.50 0.60 3958000.00 699000 328000 1000000 6 27.72 21.76
258 ZN Pacific Ocean 155557000.00 135663 3066.00
259 ZZ Iles Eparses 35 3066.00 0.00

View File

@ -0,0 +1,2 @@
python generate_function_doc.py
sphinx-build -E -b html ./source/ ./html

View File

@ -0,0 +1,65 @@
import sys, os
sys.path.append((os.path.join(sys.path[0],'..')))
import functions
from shutil import copyfile
functions.register()
curpath = os.path.abspath(sys.path[0])
def gendoc(funtype, toplevelonly=False):
file=open(os.path.join(curpath, 'source', funtype+'.txt'),'w')
tmpstr=".. _"+(funtype.lower()+' functions list:').replace(' ','-')+'\n\n'
tmpstr+=funtype[0].upper()+funtype[1:]+' functions list'
file.write(tmpstr+'\n')
file.write('='*len(tmpstr)+'\n\n')
file.write('.. automodule:: functions.'+funtype+'.__init__\n\n')
docs={}
if not toplevelonly:
for i,v in functions.functions[funtype].iteritems():
if not v.__name__.startswith('functionslocal'):
if v.__module__ not in docs:
docs[v.__module__]=[]
docs[v.__module__].append(i)
else:
for i,v in functions.functions[funtype].iteritems():
if not v.__name__.startswith('functionslocal'):
tstr='functions.vtable.'+i
if tstr not in docs:
docs[tstr]=True
for i,v in sorted(docs.items()):
modulestr='.. module:: functions.'+funtype+'.'+i.split('.')[2]+'\n\n'
if not toplevelonly:
modstr=':mod:`'+i.split('.')[2]+'` functions'
else:
modstr=':mod:`'+i.split('.')[2]+'` function'
file.write(modstr+'\n')
file.write('-'*len(modstr)+'\n\n')
file.write(modulestr)
file.write('')
if not toplevelonly:
for i1 in sorted(v):
tmpstr='**'+i1+' function**'
file.write(tmpstr)
if not functions.functions[funtype][i1].__doc__:
file.write('\n\n')
else:
file.write(str(functions.functions[funtype][i1].__doc__)+'\n\n')
else:
if not functions.functions[funtype][i.split('.')[-1]].__doc__:
file.write('\n\n')
else:
file.write(str(functions.functions[funtype][i.split('.')[-1]].__doc__)+'\n\n')
copyfile(os.path.join(curpath, '..', 'LICENSE.txt'), os.path.join(curpath, 'source', 'license.txt'))
gendoc('row')
gendoc('aggregate')
gendoc('vtable', True)

View File

@ -0,0 +1,2 @@
This directory contains Madis' html documentation. This directory isn't
tracked by mercurial

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 B

View File

@ -0,0 +1,164 @@
/**********************************************************************
*
* Customize the values given below to suit your needs.
* You can make additional copies of this file with
* different customizated settings if you need to load
* jsMath with different parameters.
*
* Load this page via:
*
* <SCRIPT SRC="path-to-jsMath/easy/load.js"></SCRIPT>
*
* (If you are including this file into your page via Server-Side
* Includes, you should remove line above.)
*
* You can make copies of this file with different settings
* if you need to have several different configurations.
*
**********************************************************************/
if (!window.jsMath) {window.jsMath = {}}
jsMath.Easy = {
//
// The URL of the root jsMath directory on your server
// (it must be in the same domain as the HTML page).
// It should include "http://yoursite.com/", or should
// be relative to the root of your server. It is possible
// to be a relative URL, but it will be relative to the
// HTML page loading this file.
//
// If you leave this blank, jsMath will try to look it up from
// the URL where it loaded this file, but that may not work.
//
root: "",
//
// The default scaling factor for mathematics compared to the
// surrounding text.
//
scale: 120,
//
// 1 means use the autoload plug-in to decide if jsMath should be loaded
// 0 means always load jsMath
//
autoload: 1,
//
// Setting any of these will cause the tex2math plugin to be used
// to add the <DIV> and <SPAN> tags that jsMath needs. See the
// documentation for the tex2math plugin for more information.
//
processSlashParens: 1, // process \(...\) in text?
processSlashBrackets: 1, // process \[...\] in text?
processDoubleDollars: 1, // process $$...$$ in text?
processSingleDollars: 0, // process $...$ in text?
processLaTeXenvironments: 0, // process \begin{xxx}...\end{xxx} outside math mode?
fixEscapedDollars: 0, // convert \$ to $ outside of math mode?
doubleDollarsAreInLine: 0, // make $$...$$ be in-line math?
allowDisableTag: 1, // allow ID="tex2math_off" to disable tex2math?
//
// If you want to use your own custom delimiters for math instead
// of the usual ones, then uncomment the following four lines and
// insert your own delimiters within the quotes. You may want to
// turn off processing of the dollars and other delimiters above
// as well, though you can use them in combination with the
// custom delimiters if you wish. See the tex2math documentation
// for more details.
//
//customDelimiters: [
// '[math]','[/math]', // to begin and end in-line math
// '[display]','[/display]' // to begin and end display math
//],
//
// Disallow the use of the @(...) mechanism for including raw HTML
// in the contents of \hbox{}? (If used in a content-management system
// where users are allowed to enter mathematics, setting this to 0
// would allow them to enter arbitrary HTML code within their
// math formulas, and that poses a security risk.)
//
safeHBoxes: 1,
//
// Show TeX source when mathematics is double-clicked?
//
allowDoubleClicks: 1,
//
// Show jsMath font warning messages? (Disabling this prevents yours
// users from finding out that they can have a better experience on your
// site by installing some fonts, so don't disable this).
//
showFontWarnings: 0,
//
// Use "Process" or "ProcessBeforeShowing". See the jsMath
// author's documentation for the difference between these
// two routines.
//
method: "Process",
//
// List of plug-ins and extensions that you want to be
// loaded automatically. E.g.
// ["plugins/mimeTeX.js","extensions/AMSsymbols.js"]
//
loadFiles: [],
//
// List of fonts to load automatically. E.g.
// ["cmmib10"]
//
loadFonts: [],
//
// List of macros to define. These are of the form
// name: value
// where 'value' is the replacement text for the macro \name.
// The 'value' can also be [value,n] where 'value' is the replacement
// text and 'n' is the number of parameters for the macro.
// Note that backslashes must be doubled in the replacement string.
// E.g.,
// {
// RR: '{\\bf R}',
// bold: ['{\\bf #1}', 1]
// }
//
macros: {},
//
// Allow jsMath to enter global mode?
// (Uses frames, so may not always work with complex web sites)
//
allowGlobal: 1,
//
// Disable image fonts? (In case you don't load them on your server.)
//
noImageFonts: 1
};
/****************************************************************/
/****************************************************************/
//
// DO NOT MAKE CHANGES BELOW THIS
//
/****************************************************************/
/****************************************************************/
if (jsMath.Easy.root == "") {
jsMath.Easy.root = document.getElementsByTagName("script");
jsMath.Easy.root = jsMath.Easy.root[jsMath.Easy.root.length-1].src
if (jsMath.Easy.root.match(/\/easy\/[^\/]*$/)) {
jsMath.Easy.root = jsMath.Easy.root.replace(/\/easy\/[^\/]*$/,"");
} else {
jsMath.Easy.root = jsMath.Easy.root.replace(/\/(jsMath\/(easy\/)?)?[^\/]*$/,"/jsMath");
}
}
jsMath.Easy.root = jsMath.Easy.root.replace(/\/$/,""); // trim trailing "/" if any
document.write('<SCRIPT SRC="'+jsMath.Easy.root+'/jsMath-easy-load.js"><'+'/SCRIPT>');

View File

@ -0,0 +1,293 @@
/*
* extensions/AMSmath.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file defines most of the macros and environments from
* the amsmath LaTeX package. You can activate it by calling
*
* jsMath.Extension.Require('AMSmath');
*
* once jsMath.js has been loaded, or by adding "extensions/AMSmath.js"
* to the loadFiles array in jsMath/easy/load.js.
*
* You may wish to load AMSsymbols.js as well, but note that it
* requires the extra msam10 and msb10 fonts that you will have
* to install on your server first.
*
* ---------------------------------------------------------------------
*
* Copyright 2007 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/********************************************************************/
jsMath.Extension.Require("moreArrows");
jsMath.Package(jsMath.Parser,{
macros: {
intI: ['Macro','\\mathchoice{\\!}{}{}{}\\!\\!\\int'],
iint: ['Macro','\\!\\!\\!\\mathop{\\,\\,\\,\\int\\intI}'],
iiint: ['Macro','\\!\\!\\!\\mathop{\\,\\,\\,\\int\\intI\\intI}'],
iiiint: ['Macro','\\!\\!\\!\\mathop{\\,\\,\\,\\int\\intI\\intI\\intI}'],
idotsint: ['Macro','\\!\\!\\mathop{\\,\\,\\int\\cdots\\int}'],
dddot: ['Macro','\\mathop{#1}\\limits^{\\textstyle ...}',1],
ddddot: ['Macro','\\mathop{#1}\\limits^{\\textstyle ....}',1],
sideset: ['Macro','\\mathop{\\rlap{\\phantom{#3}}}#1\\!{#3}#2',3],
stackrel: ['Macro','\\mathrel{\\mathop{#2}\\limits^{#1}}',2],
boxed: ['Macro','\\fbox{$\\displaystyle{#1}$}',1],
tag: 'HandleTag',
notag: ['Macro',''],
substack: ['Macro','\\begin{subarray}{c}#1\\end{subarray}',1],
varliminf: ['Macro','\\mathop{\\underline{\\raise1.5pt{\\rule{0pt}{.6em}{0pt}\\smash{\\lower1.5pt{\\rm lim}}}}}'],
varlimsup: ['Macro','\\mathop{\\overline{\\rule{0pt}{.6em}{0pt}\\smash{\\rm lim}}}'],
varinjlim: ['Macro','\\mathop{\\underrightarrow{\\rm lim}}'],
varprojlim: ['Macro','\\mathop{\\underleftarrow{\\rm lim}}'],
DeclareMathOperator: 'HandleDeclareOp',
operatorname: 'HandleOperatorName',
genfrac: 'Genfrac',
frac: ['Genfrac',"","","",""],
tfrac: ['Genfrac',"","","","1"],
dfrac: ['Genfrac',"","","","0"],
binom: ['Genfrac',"(",")","0pt",""],
tbinom: ['Genfrac',"(",")","0pt","1"],
dbinom: ['Genfrac',"(",")","0pt","0"],
cfrac: 'CFrac',
shoveleft: ['HandleShove','left'],
shoveright: ['HandleShove','right']
},
environments: {
align: ['Array',null,null,'rlrlrlrlrlrl',[5/18,2,5/18,2,5/18,2,5/18,2,5/18,2,5/18],1,'D'],
'align*': ['Array',null,null,'rlrlrlrlrlrl',[5/18,2,5/18,2,5/18,2,5/18,2,5/18,2,5/18],1,'D'],
aligned: ['Array',null,null,'rlrlrlrlrlrl',[5/18,2,5/18,2,5/18,2,5/18,2,5/18,2,5/18],1,'D'],
multline: 'Multline',
'multline*': 'Multline',
split: ['Array',null,null,'rl',[5/18],1,'D'],
gather: ['Array',null,null,'c',null,1,'D'],
'gather*': ['Array',null,null,'c',null,1,'D'],
gathered: ['Array',null,null,'c',null,1,'D'],
subarray: ['Array',null,null,null,[0,0,0,0],1,'S',0,.25],
smallmatrix: ['Array',null,null,'cccccccccc',[1/3,1/3,1/3,1/3,1/3,1/3,1/3,1/3,1/3,1/3],1,'S',0]
},
delimiter: {
'\\lvert': [4,2,0x6A,3,0x0C],
'\\rvert': [5,2,0x6A,3,0x0C],
'\\lVert': [4,2,0x6B,3,0x0D],
'\\rVert': [5,2,0x6B,3,0x0D]
},
/*
* Ignore the tag for now
*/
HandleTag: function (name) {
var arg = this.trimSpaces(this.GetArgument(this.cmd+name)); if (this.error) return;
if (arg == "*") this.GetArgument(this.cmd+name);
},
/*
* Handle \DeclareMathOperator
*/
HandleDeclareOp: function (name) {
var limits = "";
var cs = this.trimSpaces(this.GetArgument(this.cmd+name)); if (this.error) return;
if (cs == "*") {
limits = "\\limits";
cs = this.trimSpaces(this.GetArgument(this.cmd+name)); if (this.error) return;
}
if (cs.charAt(0) == "\\") {cs = cs.substr(1)}
var op = this.GetArgument(this.cmd+name); if (this.error) return;
op = op.replace(/\*/g,'\\char{cmr10}{0x2A}').replace(/-/g,'\\char{cmr10}{0x2D}');
jsMath.Parser.prototype.macros[cs] = ['Macro','\\mathop{\\rm '+op+'}'+limits];
},
HandleOperatorName: function (name) {
var limits = "\\nolimits";
var op = this.trimSpaces(this.GetArgument(this.cmd+name)); if (this.error) return;
if (op == "*") {
limits = "\\limits";
op = this.trimSpaces(this.GetArgument(this.cmd+name)); if (this.error) return;
}
op = op.replace(/\*/g,'\\char{cmr10}{0x2A}').replace(/-/g,'\\char{cmr10}{0x2D}');
this.string = '\\mathop{\\rm '+op+'}'+limits+this.string.slice(this.i);
this.i = 0;
},
/*
* Record presence of \shoveleft and \shoveright
*/
HandleShove: function (name,data) {
if (this.mlist.data.entry == null) {this.mlist.data.entry = {}}
this.mlist.data.entry.shove = data[0];
},
/*
* Handle \cfrac
*/
CFrac: function (name) {
var lr = this.GetBrackets(this.cmd+name); if (this.error) return;
var num = this.GetArgument(this.cmd+name); if (this.error) return;
var den = this.GetArgument(this.cmd+name); if (this.error) return;
num = this.Process('\\strut\\textstyle{'+num+'}'); if (this.error) return;
den = this.Process('\\strut\\textstyle{'+den+'}'); if (this.error) return;
var data = this.mlist.data;
var TeX = jsMath.Typeset.TeX(data.style,data.size);
if (lr != "") {
if (lr != 'l' && lr != 'r') {this.Error("Illegal alignment specified in "+this.cmd+name); return}
num = jsMath.Box.Set(num,data.style,data.size);
den = jsMath.Box.Set(den,data.style,data.size);
if (num.w > den.w) {
if (lr == 'l') {den.html += jsMath.HTML.Spacer(num.w-den.w)}
else {den.html = jsMath.HTML.Spacer(num.w-den.w) + den.html}
den.w = num.w;
} else if (num.w < den.w) {
if (lr == 'l') {num.html += jsMath.HTML.Spacer(den.w-num.w)}
else {num.html = jsMath.HTML.Spacer(den.w-num.w) + num.html}
num.w = den.w;
}
}
this.mlist.Add(jsMath.mItem.Fraction(name,num,den,TeX.default_rule_thickness));
},
/*
* Implement AMS generalized fraction
*/
Genfrac: function (name,data) {
var left = data[0]; var right = data[1];
var thickness = data[2]; var style = data[3];
if (left != null) {left = this.delimiter[left]} else
{left = this.GetDelimiterArg(this.cmd+name); if (this.error) return}
if (right != null) {right = this.delimiter[right]} else
{right = this.GetDelimiterArg(this.cmd+name); if (this.error) return}
if (thickness == null) {thickness = this.GetArgument(this.cmd+name); if (this.error) return}
if (style == null) {style = this.GetArgument(this.cmd+name); if (this.error) return}
var num = this.ProcessArg(this.cmd+name); if (this.error) return;
var den = this.ProcessArg(this.cmd+name); if (this.error) return;
if (left == "") {left = null}; if (right == "") {right = null}
if (thickness == "") {
var TeX =jsMath.Typeset.TeX(this.mlist.data.style,this.mlist.data.size);
thickness = TeX.default_rule_thickness;
} else {
thickness = this.ParseDimen(thickness,this.cmd+name,0,0);
}
var frac = jsMath.mItem.Fraction(name,num,den,thickness,left,right);
if (style != "") {
style = (["D","T","S","SS"])[style];
if (style == null) {this.Error("Bad math style for "+this.cmd+name); return}
var mlist = new jsMath.mList([new jsMath.mItem('style',{style:style}),frac]);
this.mlist.Add(jsMath.mItem.Atom('inner',{type:'mlist',mlist: mlist}));
} else {
this.mlist.Add(frac);
}
},
/*
* Implements the multline environment
*/
Multline: function (name,delim) {
var data = this.mlist.data;
var width = this.GetBrackets(this.cmd+'begin{'+name+'}'); if (this.error) return;
var arg = this.GetEnd(name); if (this.error) return;
var parse = new jsMath.Parser(arg+this.cmd+'\\',null,data.size,'D');
parse.matrix = name; parse.row = []; parse.table = []; parse.rspacing = [];
parse.Parse(); if (parse.error) {this.Error(parse); return}
parse.HandleRow(name,1); // be sure the last row is recorded
//
// check rows for extra columns and maximum width
//
var i; var row; var W = 0;
for (i = 0; i < parse.table.length; i++) {
row = parse.table[i];
if (row.length > 1) {
this.Error("Rows can contain only one equation in '"+name+"' environment");
return;
}
if (row[0].w > W) {W = row[0].w}
}
//
// Determine width of display
//
if (width == "") {width = W+2} else {
width = this.ParseDimen(width,name,0,0);
if (width < W) {width = W}
}
//
// Shove the top and bottom lines
//
if (parse.table.length > 1) {
parse.table[0][0].entry.shove = 'left';
row = parse.table[parse.table.length-1];
if (!row[0].entry.shove) {row[0].entry.shove = 'right'}
}
//
// Adjust widths of shoved lines
//
for (i = 0; i < parse.table.length; i++) {
row = parse.table[i][0];
if (row.entry.shove && row.w < width) {
switch (row.entry.shove) {
case 'left':
row.html += jsMath.HTML.Spacer(width-row.w);
break;
case 'right':
row.html = jsMath.HTML.Spacer(width-row.w)+row.html;
break;
}
row.w = width;
}
}
//
// Do the layout
//
var box = jsMath.Box.Layout(data.size,parse.table);
this.mlist.Add(jsMath.mItem.Atom('ord',box));
},
/*
* Get a delimiter or empty argument
*/
GetDelimiterArg: function (name) {
var c = this.trimSpaces(this.GetArgument(name)); if (this.error) return null;
if (c == "") return null;
if (this.delimiter[c]) return this.delimiter[c];
this.Error("Missing or unrecognized delimiter for "+name);
return null;
}
});

View File

@ -0,0 +1,290 @@
/*
* extensions/AMSsymbol.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file defines the macros needed to access the AMS symbol fonts
* available in msam10 and msbm10. You can activate it by calling
*
* jsMath.Extension.Require('AMSsymbols');
*
* once jsMath.js has been loaded.
*
* Note that you will need to install the msam10 and msbm10 fonts
* that are available from the jsMath extra font page at
*
* http://www.math.union.edu/locate/jsMath/download/extra-fonts/
*
* in order to make this work in image mode. Note that there is no
* unicode fallback mode for these fonts at this time.
*
* ---------------------------------------------------------------------
*
* Copyright 2006 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/********************************************************************/
delete jsMath.Parser.prototype.macros['hbar'];
delete jsMath.Parser.prototype.macros['angle'];
delete jsMath.Parser.prototype.macros['rightleftharpoons'];
jsMath.Extension.MathChar("msam10",{
// Miscellaneous symbols
vartriangle: [3,0x4D],
triangledown: [0,0x4F],
square: [0,0x03],
lozenge: [0,0x06],
circledS: [0,0x73],
angle: [0,0x5C],
measuredangle: [0,0x5D],
backprime: [0,0x38],
blacktriangle: [0,0x4E],
blacktriangledown: [0,0x48],
blacksquare: [0,0x04],
blacklozenge: [0,0x07],
bigstar: [0,0x46],
sphericalangle: [0,0x5E],
complement: [0,0x7B],
// Binary operators
dotplus: [2,0x75],
Cap: [2,0x65],
doublecap: [2,0x65],
Cup: [2,0x64],
doublecup: [2,0x64],
barwedge: [2,0x5A],
veebar: [2,0x59],
doublebarwedge: [2,0x5B],
boxminus: [2,0x0C],
boxtimes: [2,0x02],
boxdot: [2,0x00],
boxplus: [2,0x01],
leftthreetimes: [2,0x68],
rightthreetimes: [2,0x69],
curlywedge: [2,0x66],
curlyvee: [2,0x67],
circleddash: [2,0x7F],
circledast: [2,0x7E],
circledcirc: [2,0x7D],
centerdot: [2,0x05],
intercal: [2,0x7C],
// Binary relations
leqq: [3,0x35],
leqslant: [3,0x36],
eqslantless: [3,0x30],
lesssim: [3,0x2E],
lessapprox: [3,0x2F],
lll: [3,0x6E],
llless: [3,0x6E],
lessgtr: [3,0x37],
lesseqgtr: [3,0x51],
lesseqqgtr: [3,0x53],
doteqdot: [3,0x2B],
Doteq: [3,0x2B],
risingdotseq: [3,0x3A],
fallingdotseq: [3,0x3B],
backsim: [3,0x76],
backsimeq: [3,0x77],
subseteqq: [3,0x6A],
Subset: [3,0x62],
sqsubset: [3,0x40],
preccurlyeq: [3,0x34],
curlyeqprec: [3,0x32],
precsim: [3,0x2D],
vartriangleleft: [3,0x43],
trianglelefteq: [3,0x45],
vDash: [3,0x0F],
Vvdash: [3,0x0E],
smallsmile: [3,0x60],
smallfrown: [3,0x61],
bumpeq: [3,0x6C],
Bumpeq: [3,0x6D],
varpropto: [3,0x5F],
blacktriangleleft: [3,0x4A],
therefore: [3,0x29],
geqq: [3,0x3D],
geqslant: [3,0x3E],
eqslantgtr: [3,0x31],
gtrsim: [3,0x26],
gtrapprox: [3,0x27],
ggg: [3,0x6F],
gggtr: [3,0x6F],
gtrless: [3,0x3F],
gtreqless: [3,0x52],
gtreqqless: [3,0x54],
eqcirc: [3,0x50],
circeq: [3,0x24],
triangleq: [3,0x2C],
supseteqq: [3,0x6B],
Supset: [3,0x63],
sqsupset: [3,0x41],
succcurlyeq: [3,0x3C],
curlyeqsucc: [3,0x33],
succsim: [3,0x25],
vartriangleright: [3,0x42],
trianglerighteq: [3,0x44],
Vdash: [3,0x0D],
between: [3,0x47],
pitchfork: [3,0x74],
blacktriangleright: [3,0x49],
because: [3,0x2A],
// Arrows
leftleftarrows: [3,0x12],
leftrightarrows: [3,0x1C],
Lleftarrow: [3,0x57],
twoheadleftarrow: [3,0x11],
leftarrowtail: [3,0x1B],
looparrowleft: [3,0x22],
leftrightharpoons: [3,0x0B],
circlearrowleft: [3,0x09],
Lsh: [3,0x1E],
upuparrows: [3,0x14],
upharpoonleft: [3,0x18],
downharpoonleft: [3,0x19],
multimap: [3,0x28],
leftrightsquigarrow:[3,0x21],
rightrightarrows: [3,0x13],
rightleftarrows: [3,0x1D],
Rrightarrow: [3,0x56],
twoheadrightarrow: [3,0x10],
rightarrowtail: [3,0x1A],
looparrowright: [3,0x23],
rightleftharpoons: [3,0x0A],
circlearrowright: [3,0x08],
Rsh: [3,0x1F],
downdownarrows: [3,0x15],
upharpoonright: [3,0x16],
downharpoonright: [3,0x17],
rightsquigarrow: [3,0x20]
});
jsMath.Extension.MathChar("msbm10",{
// Lowercase Greek letters
digamma: [0,0x7A],
varkappa: [0,0x7B],
// Hebrew letters
beth: [0,0x69],
daleth: [0,0x6B],
gimel: [0,0x6A],
// Miscellaneous symbols
hbar: [0,0x7E],
hslash: [0,0x7D],
nexists: [0,0x40],
mho: [0,0x66],
Finv: [0,0x60],
Game: [0,0x61],
Bbbk: [0,0x7C],
varnothing: [0,0x3F],
eth: [0,0x67],
diagup: [0,0x1E],
diagdown: [0,0x1F],
// Binary operators
smallsetminus: [2,0x72],
divideontimes: [2,0x3E],
ltimes: [2,0x6E],
rtimes: [2,0x6F],
// Binary relations
approxeq: [3,0x75],
lessdot: [3,0x6C],
precapprox: [3,0x77],
gtrdot: [3,0x6D],
thicksim: [3,0x73],
thickapprox: [3,0x74],
succapprox: [3,0x76],
shortmid: [3,0x70],
shortparallel: [3,0x71],
backepsilon: [3,0x7F],
// Negated relations
nless: [3,0x04],
nleq: [3,0x02],
nleqslant: [3,0x0A],
nleqq: [3,0x14],
lneq: [3,0x0C],
lneqq: [3,0x08],
lvertneqq: [3,0x00],
lnsim: [3,0x12],
lnapprox: [3,0x1A],
nprec: [3,0x06],
npreceq: [3,0x0E],
precneqq: [3,0x16],
precnsim: [3,0x10],
precnapprox: [3,0x18],
nsim: [3,0x1C],
nshortmid: [3,0x2E],
nmid: [3,0x2D],
nvdash: [3,0x30],
nVdash: [3,0x31],
ntriangleleft: [3,0x36],
ntrianglelefteq: [3,0x35],
nsubseteq: [3,0x2A],
nsubseteqq: [3,0x22],
subsetneq: [3,0x28],
varsubsetneq: [3,0x20],
subsetneqq: [3,0x24],
varsubsetneqq: [3,0x26],
ngtr: [3,0x05],
ngeq: [3,0x03],
ngeqslant: [3,0x0B],
ngeqq: [3,0x15],
gneq: [3,0x0D],
gneqq: [3,0x09],
gvertneqq: [3,0x01],
gnsim: [3,0x13],
gnapprox: [3,0x1B],
nsucc: [3,0x07],
nsucceq: [3,0x0F],
succneqq: [3,0x17],
succnsim: [3,0x11],
succnapprox: [3,0x19],
ncong: [3,0x1D],
nshortparallel: [3,0x2F],
nparallel: [3,0x2C],
nvDash: [3,0x32],
nVDash: [3,0x33],
ntriangleright: [3,0x37],
ntrianglerighteq: [3,0x34],
nsupseteq: [3,0x2B],
nsupseteqq: [3,0x23],
supsetneq: [3,0x29],
varsupsetneq: [3,0x21],
supsetneqq: [3,0x25],
varsupsetneqq: [3,0x27],
// Arrows
curvearrowleft: [3,0x78],
curvearrowright: [3,0x79],
// Negated arrows
nleftarrow: [3,0x38],
nLeftarrow: [3,0x3A],
nleftrightarrow: [3,0x3D],
nrightarrow: [3,0x39],
nRightarrow: [3,0x3B],
nLeftrightarrow: [3,0x3C]
});
jsMath.Macro('Bbb','{\\msbm #1}',1);
jsMath.Macro('mathbb','{\\msbm #1}',1);
jsMath.Extension.Font('msbm');
jsMath.Extension.Font('msam');

View File

@ -0,0 +1,122 @@
/*
* extensions/HTML.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file implements a number of HTML-specific extensions to TeX,
* including \color, \style, \class, \unicode, etc. It will be loaded
* automatically when needed, or can be loaded by
*
* jsMath.Extension.Require('HTML');
*
* ---------------------------------------------------------------------
*
* Copyright 2005-2006 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/********************************************************************/
jsMath.Package(jsMath.Parser,{
macros: {
color: 'Color',
href: 'Href',
'class': 'Class',
style: 'Style',
cssId: 'CSSId',
unicode: 'Unicode'
},
/*
* Show the argument in a particular color
*/
Color: function (name) {
var color = this.GetArgument(this.cmd+name); if (this.error) return;
this.CheckHTML(color,name); if (this.error) return;
// check that it looks like a color?
this.AddHTML(name,['<span style="color: '+color+'">','</span>']);
},
/*
* Make the argument be a link
*/
Href: function (name) {
var href = this.GetArgument(this.cmd+name); if (this.error) return;
this.CheckHTML(href,name); if (this.error) return;
this.AddHTML(name,['<a class="link" href="'+href+'">','</a>']);
},
/*
* Apply a CSS class to the argument
*/
Class: function (name) {
var clss = this.GetArgument(this.cmd+name); if (this.error) return;
this.CheckHTML(clss,name); if (this.error) return;
this.AddHTML(name,['<span class="'+clss+'">','</span>']);
},
/*
* Apply a CSS style to the argument
*/
Style: function (name) {
var style = this.GetArgument(this.cmd+name); if (this.error) return;
this.CheckHTML(style,name); if (this.error) return;
this.AddHTML(name,['<span style="'+style+'">','</span>']);
},
/*
* Add a CSS element ID to the argument
*/
CSSId: function (name) {
var id = this.GetArgument(this.cmd+name); if (this.error) return;
this.CheckHTML(id,name); if (this.error) return;
this.AddHTML(name,['<span id="'+id+'">','</span>']);
},
/*
* Insert some raw HTML around the argument (this will not affect
* the spacing or other TeX features)
*/
AddHTML: function (name,params) {
var data = this.mlist.data;
var arg = this.GetArgument(this.cmd+name); if (this.error) return;
arg = jsMath.Parse(arg,data.font,data.size,data.style);
if (arg.error) {this.Error(arg); return}
this.mlist.Add(jsMath.mItem.HTML(params[0]));
for (var i = 0; i < arg.mlist.Length(); i++) {this.mlist.Add(arg.mlist.Get(i))}
this.mlist.Add(jsMath.mItem.HTML(params[1]));
},
CheckHTML: function (data,name) {
if (data.match(/[<>&"]/))
{this.Error("Can't include raw HTML in first argument of "+this.cmd+name)}
},
/*
* Insert a unicode reference as an Ord atom. Its argument should
* be the unicode code point, e.g. \unicode{8211}, or \unicode{x203F}.
* You can also specify the height (offset from the x height) and depth
* in ems, together with a CSS class for the character, e.g.,
* \unicode{8211,class,.2,-.3}
*/
Unicode: function (name) {
var arg = this.GetArgument(this.cmd+name); if (this.error) return;
this.CheckHTML(arg,name); if (this.error) return;
arg = arg.split(','); arg[0] = '&#'+arg[0]+';';
if (!arg[1]) {arg[1] = 'normal'}
this.mlist.Add(jsMath.mItem.TextAtom('ord',arg[0],arg[1],arg[2],arg[3]));
}
});

View File

@ -0,0 +1,51 @@
/*
* extensions/autobold.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file causes jsMath to use \boldsymbol{...} around mathematics
* that appears within <B>...</B> tags or has font-weight:bold applied
* via CSS rule. You can activate it by calling
*
* jsMath.Extension.Require('autobold');
*
* once jsMath.js has been loaded, or by adding "extensions/autobold.js"
* to the loadFiles array in jsMath/easy/load.js.
*
* Note that you will need to install the cmmib10 and cmbsy10 fonts
* that are available from the jsMath extra font page at
*
* http://www.math.union.edu/locate/jsMath/download/extra-fonts/
*
* to make this work in image mode. Note that there is no unicode
* fallback for these fonts at the moment.
*
* ---------------------------------------------------------------------
*
* Copyright 2008 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/********************************************************************/
jsMath.Extension.Require("boldsymbol");
jsMath.Translate.OldParse = jsMath.Translate.Parse;
jsMath.Translate.Parse = function (style,text,noCache) {
if (jsMath.BBoxFor('</SPAN></SPAN><SPAN STYLE="font-family:Times,serif">MMMMMMMMMM</SPAN><SPAN><SPAN>').w >
jsMath.BBoxFor('</SPAN></SPAN><SPAN STYLE="font-family:Times,serif; font-weight:normal">MMMMMMMMMM</SPAN><SPAN><SPAN>').w) {
text = '\\boldsymbol{' + text + '}';
}
return jsMath.Translate.OldParse(style,text,noCache);
}

View File

@ -0,0 +1,113 @@
/*
* extensions/bbox.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file implements the \bbox macro, which creates an HTML box that
* can be styled (for background colors, and so on). You can include
* an optional dimension that tells how much extra padding to include
* around the bounding box for the mathematics. E.g.,
*
* \bbox[2pt]{x+y} % an invisible box around x+y with 2pt of extra space
* \bbox[green]{x+y} % a green box around x+y
* \bbox[green,2pt]{x+y} % a green box with 2pt of extra space
* \bbox[yellow,2pt,border:1px solid red]{x+y}
* % a yellow box with a red border and 2pt space
*
* This extension is loaded automatically when needed, or you can call
* it directly via
*
* jsMath.Extension.Require('bbox');
*
* ---------------------------------------------------------------------
*
* Copyright 2006 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/********************************************************************/
jsMath.Add(jsMath.HTML,{
/*
* Create a colored bbounding box
*/
BBox: function (w,h,d,c,s) {
if (w <= 0) {return ''}
if (d == null) {d = 0}
var style = (jsMath.Browser.msieInlineBlockFix ? '' : 'overflow:visible;');
style += 'width:'+this.Em(w)+'; height:'+this.Em(h+d)+';';
if (jsMath.Browser.mozInlineBlockBug) {d = -h}
if (jsMath.Browser.msieInlineBlockFix) {d -= jsMath.d}
if (d) {style += ' vertical-align:'+this.Em(-d)+';'}
if (c) {style += ' background-color:'+c+';'}
var html = '<span class="blank" style="'+style+s+'"></span>';
return html;
}
});
jsMath.Add(jsMath.mList.prototype.Atomize,{
/*
* Creates the box HTML
*/
bbox: function (style,size,mitem,prev,mlist) {
var box; var w; var h; var d;
var nuc = mitem.nuc = jsMath.Box.Set(mitem.nuc,style,size).Remeasured();
if (box == null) {w = nuc.w; h = nuc.h; d = nuc.d} // values before super/subs-cript
var nuc = mitem.nuc; nuc.Styled(); var pad = mitem.pad;
if (pad) {w += 2*pad; h += pad; d += pad; nuc.w += pad}
if (jsMath.Browser.msieCenterBugFix)
{nuc.html = '<span style="position:relative">'+nuc.html+'</span>'}
nuc.html =
jsMath.HTML.BBox(w,h,d,mitem.color,mitem.style) +
jsMath.HTML.Spacer(pad-w) +
nuc.html;
nuc.Remeasured();
if (pad && nuc.w < w) {
nuc.html += jsMath.HTML.Spacer(w-nuc.w);
nuc.w = w;
}
nuc.h = Math.max(nuc.h,h); nuc.d = Math.max(nuc.d,d);
nuc.bh = Math.max(nuc.bh,nuc.h); nuc.bd = Math.max(nuc.bd,nuc.d);
mitem.type = 'ord';
jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
}
});
jsMath.Package(jsMath.Parser,{
macros: {bbox: 'BBox'},
/*
* Implement \bbox[...]{...}
*/
BBox: function (name) {
var extra = this.GetBrackets(this.cmd+name); if (this.error) return;
var arg = this.GetArgument(this.cmd+name); if (this.error) return;
var nuc = this.Process(arg); if (this.error) return;
var color; var pad = 0; var style = '';
if (extra != '') {
var parts = extra.split(/,/);
for (var i in parts) {
if (parts[i].match(/^\s*([-+]?(\.\d+|\d+(\.\d*)?))(pt|em|ex|mu|px)\s*$/))
{pad = this.ParseDimen(parts[i],'',0,1)}
else if (parts[i].match(/:/)) {style = parts[i]}
else {color = parts[i]}
}
}
var atom = {nuc: nuc, atom: 1, pad: pad, color: color, style: style};
this.mlist.Add(new jsMath.mItem('bbox',atom));
}
});

View File

@ -0,0 +1,63 @@
/*
* extensions/boldsymbol.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file implements the \boldsymbol macro. You can activate it
* by calling
*
* jsMath.Extension.Macro('boldsymbol');
*
* which will cause the extension to be loaded only when it is
* needed, or you can force it to be loaded via
*
* jsMath.Extension.Require('boldsymbol');
*
* once jsMath.js has been loaded.
*
* Note that you will need to install the cmmib10 and cmbsy10 fonts
* that are available from the jsMath extra font page at
*
* http://www.math.union.edu/locate/jsMath/download/extra-fonts/
*
* to make this work in image mode. Note that there is no unicode
* fallback for these fonts at the moment.
*
* ---------------------------------------------------------------------
*
* Copyright 2006-2007 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/********************************************************************/
jsMath.Package(jsMath.Parser,{
macros: {boldsymbol: 'BoldSymbol'},
/*
* Implement \boldsymbol{...}
*/
BoldSymbol: function (name) {
var fam = jsMath.TeX.fam; var restart = 0;
var oldfam = [fam[0],fam[1],fam[2]];
fam[0] = "cmbx10"; fam[1] = "cmmib10"; fam[2] = "cmbsy10";
try{var box = this.ProcessArg(this.cmd+name)}
catch (e) {restart = (e == "restart")}
fam[0] = oldfam[0]; fam[1] = oldfam[1]; fam[2] = oldfam[2];
if (this.error) return; if (restart) {throw "restart"}
this.mlist.Add(jsMath.mItem.Atom('ord',box));
}
});

View File

@ -0,0 +1,250 @@
/*
* extensions/double-click.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file allows users to double click on typeset mathematics
* to view the TeX source for the given expression. It will be loaded
* automatically when needed, or can be loaded by
*
* jsMath.Extension.Require('double-click');
*
* ---------------------------------------------------------------------
*
* Copyright 2005-2008 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/********************************************************************/
if (jsMath.Click && jsMath.Click.styles)
{jsMath.Click.oldStyles = jsMath.Click.styles}
jsMath.Add(jsMath.Click,{
dragging: 0,
styles: {
// Floating windows for displaying TeX source
'#jsMath_float': {
position: 'absolute', top: '0px', left: '0px', 'z-index': '101',
'max-width': '80%', width: 'auto', height: 'auto',
padding: '0px', margin: '0px', 'font-size': '100%'
},
'#jsMath_float .drag': {
'background-color': '#DDDDDD',
border: 'outset 1px', padding: '0px', margin: '0px',
width: 'auto', height: '12px', 'font-size': '1px'
},
'#jsMath_float .close': {
'background-color': '#E6E6E6',
border: 'inset 1px', margin: '1px 2px', padding: '0px',
width: '8px', height: '8px'
},
'#jsMath_float .source': {
'background-color': '#E2E2E2',
border: 'outset 1px', margin: '0px', padding: '8px 15px',
width: 'auto', height: 'auto',
'font-family': 'courier, fixed', 'font-size': '90%'
}
},
/*
* Create the hidden DIV used for the tex source window
*/
Init: function () {
if (this.oldStyles) {jsMath.Insert(this.styles,this.oldStyles)}
jsMath.Setup.Styles(this.styles);
this.source = jsMath.Setup.DIV("float",{display:'none'});
this.source.innerHTML =
'<div class="drag"><div class="close"></div></div>'
+ '<div class="source"><span></span></div>';
this.drag = this.source.firstChild;
this.tex = this.drag.nextSibling.firstChild;
this.drag.firstChild.onclick = jsMath.Click.CloseSource;
this.drag.onmousedown = jsMath.Click.StartDragging;
this.drag.ondragstart = jsMath.Click.False;
this.drag.onselectstart = jsMath.Click.False;
this.source.onclick = jsMath.Click.CheckClose;
},
False: function () {return false},
/*
* Handle a double-click on an equation
*/
DblClick: function (data) {
var event = data[0]; var TeX = data[1];
var event = jsMath.Click.Event(event);
var source = jsMath.Click.source
var tex = jsMath.Click.tex;
source.style.visibility = 'hidden';
source.style.display = ''; source.style.width = '';
source.style.left = ''; source.style.top = '';
tex.innerHTML = '';
TeX = TeX.replace(/^\s+|\s+$/g,'');
TeX = TeX.replace(/&/g,'&amp;');
TeX = TeX.replace(/</g,'&lt;');
TeX = TeX.replace(/>/g,'&gt;');
TeX = TeX.replace(/\n/g,'<br/>');
tex.innerHTML = TeX;
var h = source.offsetHeight; var w;
if (jsMath.Browser.msieDivWidthBug) {
tex.className = 'source'; // Work around MSIE bug where
w = tex.offsetWidth + 5; // DIV's don't collapse to
tex.className = ''; // their natural widths
} else {
w = source.offsetWidth;
}
w = Math.max(50,Math.min(w,.8*event.W,event.W-40));
var x = Math.floor(event.x-w/2); var y = Math.floor(event.y-h/2);
x = event.X + Math.max(Math.min(x,event.W-w-20),20);
y = event.Y + Math.max(Math.min(y,event.H-h-5),5);
source.style.left = x+'px'; source.style.top = y+'px';
source.style.width = w+'px';
source.style.visibility = '';
jsMath.Click.left = x + event.X; jsMath.Click.top = y + event.Y;
jsMath.Click.w = w; jsMath.Click.h = source.offsetHeight;
jsMath.Click.DeselectText(x,y);
return false;
},
/*
* Get window width, height, and offsets plus
* position of pointer relative to the window
*/
Event: function (event) {
var W = jsMath.window.innerWidth || jsMath.document.body.clientWidth;
var H = jsMath.window.innerHeight || jsMath.document.body.clientHeight;
var X = jsMath.window.pageXOffset; var Y = jsMath.window.pageYOffset;
if (X == null) {
X = jsMath.document.body.clientLeft;
Y = jsMath.document.body.clientTop;
}
var x = event.pageX; var y = event.pageY;
if (x == null) {
x = event.clientX; y = event.clientY;
if (jsMath.browser == 'MSIE' && jsMath.document.compatMode == 'CSS1Compat') {
X = jsMath.document.documentElement.scrollLeft;
Y = jsMath.document.documentElement.scrollTop;
W = jsMath.document.documentElement.clientWidth;
H = jsMath.document.documentElement.clientHeight;
} else {
X = jsMath.document.body.scrollLeft;
Y = jsMath.document.body.scrollTop;
}
} else {x -= X; y -= Y}
return {x: x, y: y, W: W, H: H, X: X, Y: Y};
},
/*
* Unselect whatever text is selected (since double-clicking
* usually selects something)
*/
DeselectText: function (x,y) {
if (jsMath.window.getSelection && jsMath.window.getSelection().removeAllRanges)
{jsMath.window.getSelection().removeAllRanges()}
else if (jsMath.document.getSelection && jsMath.document.getSelection().removeAllRanges)
{jsMath.document.getSelection().removeAllRanges()}
else if (jsMath.document.selection && jsMath.document.selection.empty)
{jsMath.document.selection.empty()}
else {
/* Hack to deselect the text in Opera and Safari */
if (jsMath.browser == 'MSIE') return; // don't try it if MISE on Mac
jsMath.hiddenTop.innerHTML =
'<textarea style="visibility:hidden" rows="1" cols="1">a</textarea>';
jsMath.hiddenTop.firstChild.style.position = 'absolute';
jsMath.hiddenTop.firstChild.style.left = x+'px';
jsMath.hiddenTop.firstChild.style.top = y+'px';
setTimeout(jsMath.Click.SelectHidden,1);
}
},
SelectHidden: function () {
jsMath.hiddenTop.firstChild.focus();
jsMath.hiddenTop.firstChild.select();
jsMath.hiddenTop.innerHTML = '';
},
/*
* Close the TeX source window
*/
CloseSource: function () {
jsMath.Click.tex.innerHTML = '';
jsMath.Click.source.style.display = 'none';
jsMath.Click.source.style.visibility = 'hidden';
jsMath.Click.StopDragging();
return false;
},
CheckClose: function (event) {
if (!event) {event = jsMath.window.event}
if (event.altKey) {jsMath.Click.CloseSource(); return false}
},
/*
* Set up for dragging the source panel
*/
StartDragging: function (event) {
if (!event) {event = jsMath.window.event}
if (jsMath.Click.dragging) {jsMath.Click.StopDragging(event)}
var event = jsMath.Click.Event(event);
jsMath.Click.dragging = 1;
jsMath.Click.x = event.x + 2*event.X - jsMath.Click.left;
jsMath.Click.y = event.y + 2*event.Y - jsMath.Click.top;
jsMath.Click.oldonmousemove = jsMath.document.onmousemove;
jsMath.Click.oldonmouseup = jsMath.document.onmouseup;
jsMath.document.onmousemove = jsMath.Click.DragSource;
jsMath.document.onmouseup = jsMath.Click.StopDragging;
return false;
},
/*
* Stop dragging the source window
*/
StopDragging: function (event) {
if (jsMath.Click.dragging) {
jsMath.document.onmousemove = jsMath.Click.oldonmousemove;
jsMath.document.onmouseup = jsMath.Click.oldonmouseup;
jsMath.Click.oldonmousemove = null;
jsMath.Click.oldonmouseup = null;
jsMath.Click.dragging = 0;
}
return false;
},
/*
* Move the source window (but stay within the browser window)
*/
DragSource: function (event) {
if (!event) {event = jsMath.window.event}
if (jsMath.Browser.buttonCheck && !event.button) {return jsMath.Click.StopDragging(event)}
event = jsMath.Click.Event(event);
var x = event.x + event.X - jsMath.Click.x;
var y = event.y + event.Y - jsMath.Click.y;
x = Math.max(event.X,Math.min(event.W+event.X-jsMath.Click.w,x));
y = Math.max(event.Y,Math.min(event.H+event.Y-jsMath.Click.h,y));
jsMath.Click.source.style.left = x + 'px';
jsMath.Click.source.style.top = y + 'px';
jsMath.Click.left = x + event.X; jsMath.Click.top = y + event.Y;
return false;
}
});
jsMath.Click.Init();

View File

@ -0,0 +1,234 @@
/*
* extensions/eqn-number.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file causes jsMath to add equation numbers to displayed
* equations. These are displayed at the right, but the styles can
* be controlled through the jsMath.EqnNumber object. Equations
* are numbered if they include a \label{xxx} call, and the macro
* \ref{xxx} can be used to refer to the equation number elsewhere
* in the document (it must appear by itself in a math formula,
* e.g., $\ref{xxx}$). The "label-ref" CSS style can be used to
* style the references.
*
* If jsMath.EqnNumber.autonumber is set to 1, then ALL displayed
* equations will be numberd. Use the \nolabel macro to prevent
* equation numbering on an equation.
*
* You can activate eqn-numbering by calling
*
* jsMath.Extension.Require('eqn-number');
*
* once jsMath.js has been loaded, or by adding "extensions/eqn-number.js"
* to the loadFiles array in jsMath/easy/load.js.
*
* ---------------------------------------------------------------------
*
* Copyright 2008 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/********************************************************************/
if (jsMath.EqnNumber) {jsMath.EqnNumber_old = jsMath.EqnNumber}
jsMath.EqnNumber = {
styles: {
'.jsMath_displayBox, .tex2math_div': {position: 'relative'},
'.jsMath_number': {
position: 'absolute',
right: '2em', top: '50%', 'margin-top': '-.5em',
height: 'auto', width: 'auto'
},
'.jsMath_ref': {'text-decoration': 'none'}
},
autonumber: 0, // set to 1 to have ALL equations numbered
number: 0,
format: function (n) {return n},
formatLabel: function (n) {return '<A NAME="eqn-'+n+'">('+n+')</A>'},
formatRef: function (n) {return '(<A CLASS="jsMath_ref" HREF="#eqn-'+n+'">'+n+'</A>)'},
_label: null, // flag set when \label{x} is used
_labels: {}, // stores label-name => label-value pairs
_refs: {}, // stores elements referring to undefined labels
_nolabel: 0, // set by \nolabel
nextNumber: function () {
var ref = this.format(++this.number);
if (this._label) {
this._labels[this._label] = ref;
if (this._refs[this._label]) this.fixRefs(this._label);
}
return this.formatLabel(ref);
},
isRef: function (element) {
var tex = element.innerHTML;
var result = tex.match(/^\s*\\ref\s*\{([^\}]+)\}\s*$/);
if (!result) {return 0}
var ref = result[1];
if (this._labels[ref]) {
this.setRef(element,ref);
} else {
if (!this._refs[ref]) {this._refs[ref] = []}
this._refs[ref][this._refs[ref].length] = element;
}
return 1;
},
setRef: function (element,ref) {
element.innerHTML = this.formatRef(this._labels[ref]);
element.className = "label-ref";
},
fixRefs: function (label) {
for (var i = 0; i < this._refs[label].length; i++)
{this.setRef(this._refs[label][i],label)}
delete this._refs[label];
},
badRefs: function () {
for (var label in this._refs) {
for (var i = 0; i < this._refs[label].length; i++) {
var element = this._refs[label][i];
element.className = "typeset";
element.innerHTML = "<span class='error'>Reference '"+label+"' is undefined</span>";
}
}
},
makeDIV: function (element) {
var div = document.createElement('div');
div.className = 'jsMath_displayBox';
div.innerHTML = '<div class="jsMath_number">' + this.nextNumber() + '</div>';
element.parentNode.insertBefore(div,element);
element.parentNode.removeChild(element);
div.appendChild(element);
},
makeSPAN: function (element) {
var span = document.createElement('span');
span.className = 'jsMath_number';
span.style.display = 'inline-block';
span.innerHTML = jsMath.EqnNumber.nextNumber();
element.parentNode.insertBefore(span,element);
},
ConvertMath: function (style,element,nocache) {
var EqnNumber = jsMath.EqnNumber;
if (EqnNumber.isRef(element)) return;
EqnNumber._label = null; EqnNumber._nolabel = 0;
this.ConvertMath_old(style,element,nocache);
if (EqnNumber._label || (EqnNumber.autonumber && !EqnNumber._nolabel)) {
if (element.tagName.toLowerCase() == 'div') {
EqnNumber.makeDIV(element);
} else if (element.parentNode.className == 'tex2math_div') {
EqnNumber.makeSPAN(element);
}
}
},
ProcessComplete: function () {
jsMath.EqnNumber.badRefs();
this.ProcessComplete_old.apply(this,arguments);
},
Init: function () {
jsMath.Setup.Styles(this.styles);
jsMath.Translate.ConvertMath_old = jsMath.Translate.ConvertMath;
jsMath.Translate.ConvertMath = this.ConvertMath;
jsMath.Translate.ProcessComplete_old = jsMath.Translate.ProcessComplete;
jsMath.Translate.ProcessComplete = this.ProcessComplete;
},
environments: {
'equation*': 'Star',
'eqnarray*': 'Star',
'align*': 'Star',
'multline*': 'Star',
'gather*': 'Star',
align: ['StarExtension','AMSmath'],
multline: ['StarExtension','AMSmath'],
gather: ['StarExtension','AMSmath']
},
ResetStarEnvironments: function () {
var Nenv = jsMath.EqnNumber.environments;
var Penv = jsMath.Parser.prototype.environments;
for (var name in Nenv) {
if (name.match(/\*$/)) {Penv[name] = Nenv[name]}
}
}
};
if (jsMath.EqnNumber_old) {
jsMath.Insert(jsMath.EqnNumber,jsMath.EqnNumber_old);
delete jsMath.EqnNumber_old;
}
jsMath.Package(jsMath.Parser,{
macros: {
label: 'Label',
nolabel: 'NoLabel',
nonumber: 'NoLabel',
ref: 'Ref'
},
environments: jsMath.EqnNumber.environments,
Label: function (name) {
var label = this.GetArgument(this.cmd+name); if (this.error) return;
var EqnNumber = jsMath.EqnNumber;
if (!EqnNumber._label) {
if (!EqnNumber._labels[label]) {
EqnNumber._label = label;
EqnNumber._nolabel = 0;
} else {
this.Error("Label '"+label+"' is already defined");
}
} else {
this.Error(this.cmd+name+' can only be used once in an equation');
}
},
NoLabel: function (name) {
var EqnNumber = jsMath.EqnNumber;
EqnNumber._label = null; EqnNumber._nolabel = 1;
},
Ref: function (name) {
this.Error(this.cmd+name+' must be used by itself');
},
Star: function (name) {
this.NoLabel();
var cmd = this.environments[name.substr(0,name.length-1)];
if (typeof(cmd) === 'string') {cmd = [cmd]}
this[cmd[0]](name,cmd.slice(1));
},
StarExtension: function (name,data) {
try {this.Extension(name,data)} catch (e) {}
jsMath.Synchronize(jsMath.EqnNumber.ResetStarEnvironments);
throw "restart";
}
});
jsMath.EqnNumber.Init();

View File

@ -0,0 +1,71 @@
/*
* extensions/fbox.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file implements the \fbox macro. It will be loaded
* automatically when needed, or can be loaded by
*
* jsMath.Extension.Require('fbox');
*
* ---------------------------------------------------------------------
*
* Copyright 2005-2006 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/********************************************************************/
jsMath.Add(jsMath.HTML,{
/*
* Create a colored frame
*/
Frame: function (x,y,w,h,c,pos) {
h -= 2/jsMath.em; // use 2 pixels to compensate for border size
w -= 2/jsMath.em;
y -= 1/jsMath.em;
if (!c) {c = ''} else {c = ' '+c};
if (pos) {pos = 'absolute;'} else
{pos = 'relative; margin-right: '+this.Em(-(w+2/jsMath.em))+'; '}
return '<img src="'+jsMath.blank+'" style="position:' + pos
+ 'vertical-align: '+this.Em(y)+'; left: '+this.Em(x)+'; '
+ 'width:' +this.Em(w*jsMath.Browser.imgScale)+'; '
+ 'height:'+this.Em(h*jsMath.Browser.imgScale)+'; '
+ 'border: 1px solid'+c+';" />';
}
});
jsMath.Package(jsMath.Parser,{
macros: {fbox: 'FBox'},
/*
* Implement \fbox{...}
*/
FBox: function (name) {
var text = this.GetArgument(this.cmd+name); if (this.error) return;
var arg = jsMath.Box.InternalMath(text,this.mlist.data.size);
var f = 0.25 * jsMath.sizes[this.mlist.data.size]/100;
var box = jsMath.Box.Set(arg,this.mlist.data.style,this.mlist.data.size,1).Remeasured();
var frame = jsMath.HTML.Frame(-f,-box.d-f,box.w+2*f,box.h+box.d+2*f);
box.html = frame + box.html + jsMath.HTML.Spacer(f);
box.h += f; box.d += f; box.w +=2*f; box.x += f;
box.bh = Math.max(box.bh,box.h); box.bd = Math.max(box.bd,box.d);
this.mlist.Add(jsMath.mItem.Atom('ord',box));
}
});

View File

@ -0,0 +1,38 @@
jsMath.Package(jsMath.Parser,{
macros: {font: 'Font'},
fontCS: {},
/*
* Get a CS name or give an error
*/
GetCSname: function (cmd) {
var c = this.GetNext();
if (c != this.cmd) {this.Error(cmd+" must be followed by a control sequence"); return null}
var cs = this.trimSpaces(this.GetArgument(cmd)); if (this.error) {return null};
return cs.substr(1);
},
/*
* Handle the \font command
*/
Font: function (name) {
var cs = this.GetCSname(this.cmd+name); if (this.error) return;
while (this.nextIsSpace()) {this.i++}
if (this.string.charAt(this.i++) == '=') {
while (this.nextIsSpace()) {this.i++}
var font = this.string.slice(this.i).match(/^[a-z]+[0-9]+/i);
if (font) {
this.i += (new String(font)).length;
if (jsMath.TeX.famName[font] != null) {
this.macros[cs] = ['HandleFont',jsMath.TeX.famName[font]];
} else {
this.macros[cs] = ['Extension',jsMath.Font.URL(font),"fontCS"];
this.fontCS[cs] = 1; // so Extension has something to delete
}
} else {this.Error("Missing font name")}
} else {this.Error("Missing font definition")}
}
});

View File

@ -0,0 +1,124 @@
/*
* extensions/leaders.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file implements the \overbrace, \underbrace, \overrightarrow
* and \overleftarrow macros. It will be loaded automatically when needed,
* or can be loaded by
*
* jsMath.Extension.Require('leaders');
*
* ---------------------------------------------------------------------
*
* Copyright 2005-2006 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/********************************************************************/
jsMath.Add(jsMath.Box,{
/*
* Create a horizontally stretchable "delimiter" (like over- and
* underbraces).
*/
//### Add size?
Leaders: function (W,leader) {
var h; var d; var w; var html; var font;
if (leader.lmid) {// braces
font = jsMath.TeX.fam[leader.left[0]];
var left = this.GetCharCode(leader.left);
var right = this.GetCharCode(leader.right);
var lmid = this.GetCharCode(leader.lmid);
var rmid = this.GetCharCode(leader.rmid);
w = (W - left.w - right.w - lmid.w - rmid.w)/2 - .1; h = .4; d = .3;
if (w < 0) {w = 0}
html = this.AddClass(left.tclass,left.c,left.font)
+ jsMath.HTML.Rule(w,left.h)
+ this.AddClass(lmid.tclass,lmid.c+rmid.c,lmid.font)
+ jsMath.HTML.Rule(w,right.h)
+ this.AddClass(right.tclass,right.c,right.font);
} else { //arrows
font = jsMath.TeX.fam[leader.rep[0]];
var left = this.GetCharCode(leader.left? leader.left: leader.rep);
var rep = this.GetCharCode(leader.rep);
var right = this.GetCharCode(leader.right? leader.right: leader.rep);
var n = Math.ceil((W - left.w - right.w + .4)/(rep.w - .3));
w = (W - left.w - right.w + .4 - n*(rep.w - .3));
if (leader.left) {h = left.h; d = left.d} else {h = right.h; d = right.d}
if (d == null) {d = 0}; if (h == null) {h = 0}
var html = this.AddClass(left.tclass,left.c,left.font); var m = Math.floor(n/2);
var ext = jsMath.HTML.Place(rep.c,-.3,0);
var ehtml = ''; for (var i = 0; i < m; i++) {ehtml += ext};
html += this.AddClass(rep.tclass,ehtml,rep.font) + jsMath.HTML.Spacer(w);
ehtml = ''; for (var i = m; i < n; i++) {ehtml += ext};
html += this.AddClass(rep.tclass,ehtml,rep.font);
if (jsMath.Browser.msieFontBug) {html += '<span style="display: none">x</span>'}
html += jsMath.HTML.Place(this.AddClass(right.tclass,right.c,right.font),-.4,0);
}
w = jsMath.EmBoxFor(html).w;
if (w != W) {
w = jsMath.HTML.Spacer((W-w)/2);
html = w + html + w;
}
var box = new jsMath.Box('html',html,W,h,d);
box.bh = jsMath.TeX[font].h; box.bd = jsMath.TeX[font].d;
return box;
}
});
jsMath.Package(jsMath.Parser,{
macros: {
overbrace: ['HandleLeaders','downbrace',1],
underbrace: ['HandleLeaders','upbrace',1,1,-.05],
overrightarrow: ['HandleLeaders','rightarrow'],
underrightarrow: ['HandleLeaders','rightarrow',null,1,-.2],
overleftarrow: ['HandleLeaders','leftarrow'],
underleftarrow: ['HandleLeaders','leftarrow',null,1,-.2],
overleftrightarrow: ['HandleLeaders','leftrightarrow'],
underleftrightarrow: ['HandleLeaders','leftrightarrow',null,1,-.2]
},
/*
* The horizontally stretchable delimiters
*/
leaders: {
downbrace: {left: [3,0x7A], lmid: [3,0x7D], rmid: [3,0x7C], right: [3,0x7B]},
upbrace: {left: [3,0x7C], lmid: [3,0x7B], rmid: [3,0x7A], right: [3,0x7D]},
leftarrow: {left: [2,0x20], rep: [2,0x00]},
rightarrow: {rep: [2,0x00], right: [2,0x21]},
leftrightarrow: {left: [2,0x20], rep: [2, 0x00], right: [2,0x21]}
},
/*
* Implements \overbrace, \underbrace, etc.
*/
HandleLeaders: function (name,data) {
var box = this.ProcessArg(this.cmd+name); if (this.error) return;
box = jsMath.Box.Set(box,'D',this.mlist.data.size).Remeasured();
var leader = jsMath.Box.Leaders(box.w,this.leaders[data[0]]);
if (data[2]) {leader.y = -leader.h-box.d+(data[3]||0)}
else {leader.y = box.h + Math.max(0,leader.d)+(data[3]||0)}
box.x = -(leader.w + box.w)/2;
var space = jsMath.Box.Space((leader.w-box.w)/2);
box = jsMath.mItem.Atom(data[1]? 'op': 'ord',
jsMath.Box.SetList([leader,box,space],'T',this.mlist.data.size));
box.limits = (data[1]? 1: 0);
this.mlist.Add(box);
}
});

View File

@ -0,0 +1,70 @@
/*
* extensions/mathchoice.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file implements the 4-way math choice. It will be loaded
* automatically when needed, or can be loaded by
*
* jsMath.Extension.Require('mathchoice');
*
* ---------------------------------------------------------------------
*
* Copyright 2005-2006 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/********************************************************************/
jsMath.Add(jsMath.mList.prototype.Atomize,{
/*
* Handle a 4-way choice atom. (Rule 4)
*/
choice: function (style,mitem,i,mlist) {
if (style.charAt(style.length-1) == "'") {style = style.slice(0,style.length-1)}
var nlist = []; var M = mitem[style];
if (!M) {M = {type: 'mlist', mlist: {mlist: []}}}
if (M.type == 'mlist') {
M = M.mlist.mlist;
for (var k = 0; k < i; k++) {nlist[k] = mlist[k]}
for (k = 0; k < M.length; k++) {nlist[i+k] = M[k]}
for (k = i+1; k < mlist.length; k++) {nlist[nlist.length] = mlist[k]}
return nlist;
} else {
mlist[i] = jsMath.mItem.Atom('ord',M);
return mlist;
}
}
});
jsMath.Package(jsMath.Parser,{
macros: {mathchoice: 'MathChoice'},
/*
* Implements \mathchoice{}{}{}{}
*/
MathChoice: function (name) {
var D = this.ProcessArg(this.cmd+name); if (this.error) return;
var T = this.ProcessArg(this.cmd+name); if (this.error) return;
var S = this.ProcessArg(this.cmd+name); if (this.error) return;
var SS = this.ProcessArg(this.cmd+name); if (this.error) return;
var box = new jsMath.mItem('choice',{D: D, T: T, S: S, SS: SS});
this.mlist.Add(new jsMath.mItem('choice',{D: D, T: T, S: S, SS: SS}));
}
});

View File

@ -0,0 +1,36 @@
/*
* extensions/mimeTeX.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file loads the mimeTeX plugin, and can be called either
* by
*
* jsMath.Extension.Require('mimeTeX');
*
* or by using
*
* \require{mimeTeX}
*
* within a typeset equation.
*
* ---------------------------------------------------------------------
*
* Copyright 2005-2006 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/********************************************************************/
jsMath.Setup.Script('plugins/mimeTeX.js');

View File

@ -0,0 +1,68 @@
/*
* extensions/moreArrows.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file implements additional arrow macros with under- and
* overset labels. It can be loaded by
*
* jsMath.Extension.Require('moreArrows');
*
* or using \require{moreArrows} within a math formula.
*
* ---------------------------------------------------------------------
*
* Copyright 2005-2006 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/********************************************************************/
jsMath.Extension.Require('leaders');
jsMath.Package(jsMath.Parser,{
macros: {
xrightarrow: ['HandleArrows','rightarrow'],
xleftarrow: ['HandleArrows','leftarrow'],
xuprightharpoon: ['HandleArrows','uprightharpoon'],
xupleftharpoon: ['HandleArrows','upleftharpoon'],
xdownrightharpoon: ['HandleArrows','downrightharpoon'],
xdownleftharpoon: ['HandleArrows','downleftharpoon']
},
leaders: {
upleftharpoon: {left: [1,0x28], rep: [2,0x00]},
uprightharpoon: {rep: [2,0x00], right: [1,0x2A]},
downleftharpoon: {left: [1,0x29], rep: [2,0x00]},
downrightharpoon: {rep: [2,0x00], right: [1,0x2B]}
},
HandleArrows: function (name,data) {
var bot = this.GetBrackets(this.cmd+name); if (this.error) return;
var top = this.ProcessArg(this.cmd+name); if (this.error) return;
var box = jsMath.Box.Set(top,'S',this.mlist.data.size).Remeasured();
var w = box.w;
if (bot) {
bot = this.Process(bot); if (this.error) return;
var box = jsMath.Box.Set(bot,'S',this.mlist.data.size).Remeasured();
w = Math.max(w,box.w);
}
var leader = jsMath.Box.Leaders(w+.75,this.leaders[data[0]]);
box = jsMath.mItem.Atom('op',jsMath.Box.SetList([leader],'T',this.mlist.data.size));
box.limits = 1; box.sup = top; box.sub = bot;
this.mlist.Add(box);
}
});

View File

@ -0,0 +1,205 @@
/*
* extensions/newcommand.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file implements the \newcommand and \def macros. It will be
* loaded automatically when needed, or can be loaded by
*
* jsMath.Extension.Require('newcommand');
*
* ---------------------------------------------------------------------
*
* Copyright 2005-2006 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/********************************************************************/
jsMath.Package(jsMath.Parser,{
macros: {
newcommand: 'NewCommand',
newenvironment: 'NewEnvironment',
def: 'MacroDef'
},
/*
* Implement \newcommand{\name}[n]{...}
*/
NewCommand: function (name) {
var cs = this.trimSpaces(this.GetArgument(this.cmd+name)); if (this.error) return;
var n = this.trimSpaces(this.GetBrackets(this.cmd+name)); if (this.error) return;
var def = this.GetArgument(this.cmd+name); if (this.error) return;
if (n == '') {n = null}
if (cs.charAt(0) == this.cmd) {cs = cs.substr(1)}
if (!cs.match(/^(.|[a-z]+)$/i)) {this.Error("Illegal control sequence name for "+this.cmd+name); return}
if (n != null && !n.match(/^[0-9]+$/)) {this.Error("Illegal number of parameters specified in "+this.cmd+name); return}
jsMath.Parser.prototype.macros[cs] = ['Macro',def,n];
},
/*
* Implement \newenvironment{name}[n]{begincmd}{endcmd}
*/
NewEnvironment: function (name) {
var env = this.trimSpaces(this.GetArgument(this.cmd+name)); if (this.error) return;
var n = this.trimSpaces(this.GetBrackets(this.cmd+name)); if (this.error) return;
var bdef = this.GetArgument(this.cmd+name); if (this.error) return;
var edef = this.GetArgument(this.cmd+name); if (this.error) return;
if (n == '') {n = null}
if (n != null && !n.match(/^[0-9]+$/)) {this.Error("Illegal number of parameters specified in "+this.cmd+name); return}
jsMath.Parser.prototype.environments[env] = ['Environment',bdef,edef,n];
},
/*
* Implement \def command
*/
MacroDef: function (name) {
var cs = this.GetCSname(this.cmd+name); if (this.error) return;
var params = this.GetTemplate(this.cmd+name); if (this.error) return;
var def = this.GetArgument(this.cmd+name); if (this.error) return;
if (typeof(params) == 'number') {
jsMath.Parser.prototype.macros[cs] = ['Macro',def,params];
} else {
jsMath.Parser.prototype.macros[cs] = ['MacroWithTemplate',def,params[0],params[1]];
}
},
/*
* Get a CS name or give an error
*/
GetCSname: function (cmd) {
var c = this.GetNext();
if (c != this.cmd) {this.Error(cmd+" must be followed by a control sequence"); return null}
var cs = this.trimSpaces(this.GetArgument(cmd)); if (this.error) {return null};
return cs.substr(1);
},
/*
* Get a \def parameter template
*/
GetTemplate: function (cmd) {
var c; var params = []; var n = 0;
c = this.GetNext(); var i = this.i;
while (this.i < this.string.length) {
c = this.GetNext();
if (c == '#') {
if (i != this.i) {params[n] = this.string.substr(i,this.i-i)}
c = this.string.charAt(++this.i);
if (!c.match(/[1-9]/)) {this.Error("Illegal use of # in "+cmd); return null}
if (1*c != ++n) {this.Error("Parameters must be numbered sequentially"); return null}
i = this.i+1;
} else if (c == '{') {
if (i != this.i) {params[n] = this.string.substr(i,this.i-i)}
if (params.length > 0) {return [n,params]} else {return n}
}
this.i++;
}
this.Error("Missing replacement string for definition of "+cmd);
return null;
},
/*
* Process a macro with a parameter template
*/
MacroWithTemplate: function (name,data) {
var text = data[0];
var n = data[1]; var params = data[2];
if (n) {
var args = []; var c = this.GetNext();
if (params[0] && !this.MatchParam(params[0]))
{this.Error("Use of "+this.cmd+name+" doesn't match its definition"); return}
for (var i = 0; i < n; i++) {
args[args.length] = this.GetParameter(this.cmd+name,params[i+1]);
if (this.error) return;
}
text = this.SubstituteArgs(args,text);
}
this.string = this.AddArgs(text,this.string.slice(this.i));
this.i = 0;
},
/*
* Process a user-defined environment
*/
Environment: function (name,data) {
var bdef = data[0]; var edef = data[1]; var n = data[2];
if (n) {
var args = [];
for (var i = 0; i < n; i++) {
args[args.length] = this.GetArgument(this.cmd+"begin{"+name+"}"); if (this.error) return;
}
bdef = this.SubstituteArgs(args,bdef);
}
var text = this.GetEnd(name); if (this.error) return;
text = this.AddArgs(this.AddArgs(bdef,text),edef);
this.string = this.AddArgs(text,this.string.slice(this.i));
this.i = 0;
},
/*
* Find a single parameter delimited by a trailing template
*/
GetParameter: function (name,param) {
if (param == null) {return this.GetArgument(name)}
var i = this.i; var j = 0; var hasBraces = 0;
while (this.i < this.string.length) {
if (this.string.charAt(this.i) == '{') {
if (this.i == i) {hasBraces = 1}
this.GetArgument(name); j = this.i - i;
} else if (this.MatchParam(param)) {
if (hasBraces) {i++; j -= 2}
return this.string.substr(i,j);
} else {
this.i++; j++; hasBraces = 0;
}
}
this.Error("Runaway argument for "+name+"?");
return null;
},
/*
* Check if a template is at the current location.
* (The match must be exact, with no spacing differences. TeX is
* a little more forgiving about spaces after macro names)
*/
MatchParam: function (param) {
if (this.string.substr(this.i,param.length) != param) {return 0}
this.i += param.length;
return 1;
}
});
/*
* Define a jsMath.Environment() command similar to the
* jsMath.Macro() command.
*
* Usage: jsMath.Environment(name,begin,end[,n])
*
* where "name" is the name of the environment, "begin" is the
* text that replaces the \begin{name} and "end" is the text that
* replaces the \end{name}. If "n" is provided, it is the number
* of parameters that the \begin{name} accepts, and these are
* used to replace #1, #2, etc within the "begin" text.
*/
jsMath.Add(jsMath,{
Environment: function (name) {
var environments = jsMath.Parser.prototype.environments;
environments[name] = ['Environment'];
for (var i = 1; i < arguments.length; i++)
{environments[name][environments[name].length] = arguments[i]}
}
});

View File

@ -0,0 +1,53 @@
/*
* extensions/underset-overset.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file implements \underset and \overset macros. It will be loaded
* automatically when needed, or can be loaded by
*
* jsMath.Extension.Require('underset-overset');
*
* ---------------------------------------------------------------------
*
* Copyright 200-20065 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/********************************************************************/
jsMath.Package(jsMath.Parser,{
macros: {
overset: 'Overset',
underset: 'Underset'
},
Overset: function (name) {
var top = this.ProcessArg(this.cmd+name); if (this.error) return;
var bot = this.ProcessArg(this.cmd+name); if (this.error) return;
var op = jsMath.mItem.Atom('op',bot);
op.limits = 1; op.sup = top;
this.mlist.Add(op);
},
Underset: function (name) {
var bot = this.ProcessArg(this.cmd+name); if (this.error) return;
var top = this.ProcessArg(this.cmd+name); if (this.error) return;
var op = jsMath.mItem.Atom('op',top);
op.limits = 1; op.sub = bot;
this.mlist.Add(op);
}
});

View File

@ -0,0 +1,58 @@
/*
* extensions/verb.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file implements the \verb macro. You can activate it
* by calling
*
* jsMath.Extension.Macro('verb');
*
* which will cause the extension to be loaded only when it is
* needed, or you can force it to be loaded via
*
* jsMath.Extension.Require('verb');
*
* once jsMath.js has been loaded, or by adding "extensions/verb.js"
* to the loadFiles array in the easy/load.js file.
*
* ---------------------------------------------------------------------
*
* Copyright 2008 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/********************************************************************/
jsMath.Package(jsMath.Parser,{
macros: {verb: 'Verb'},
/*
* Implement \verb|...|
*/
Verb: function (name) {
var c = this.GetNext(); var start = ++this.i;
if (c == "" ) {this.Error(this.cmd+name+" requires an argument"); return}
while (this.i < this.string.length && this.string.charAt(this.i) != c) {this.i++}
if (this.i == this.string.length)
{this.Error("Can't find closing delimiter for "+this.cmd+name); return}
var text = this.string.slice(start,this.i); this.i++;
text = text.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
text = '<span style="font-family:monospace">'+text+'</span>';
var box = jsMath.Box.Text(text,'normal','T',this.mlist.data.size).Styled();
box.h = box.bh+box.bd -jsMath.d; box.d = jsMath.d;
this.mlist.Add(jsMath.mItem.Typeset(box));
}
});

View File

@ -0,0 +1,428 @@
/*
* jsMath-BaKoMa-fonts.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file makes changes needed to use the BaKoMa fonts and
* their encoding.
*
* ---------------------------------------------------------------------
*
* Copyright 2004-2007 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/********************************************************************
*
* The BaKoMa fonts have a different encoding, so change the characters
* to correspond to the their encoding.
*/
if (jsMath.browser == "Mozilla" && jsMath.platform != "mac") {
/*
* Mozilla/PC
*/
jsMath.Update.TeXfontCodes({
cmr10: [
'&#x0393;', '&#x0394;', '&#x0398;', '&#x039B;',
'&#x039E;', '&#x03A0;', '&#x03A3;', '&#x03A5;',
'&#x03A6;', '&#x03A8;', '&#x03A9;', '&#xFB00;',
'&#xFB01;', '&#xFB02;', '&#xFB03;', '&#xFB04;',
'&#x0131;', '&#xEEF0;', '&#x0300;', '&#x0301;',
'&#x030C;', '&#x0306;', '&#x0305;', '&#x030A;',
'&#x0327;', '&#x00DF;', '&#x00E6;', '&#x0153;',
'&#x00F8;', '&#x00C6;', '&#x0152;', '&#x00D8;',
'&#x337;', '&#x21;', '&#x201D;', '&#x23;',
'&#x24;', '&#x25;', '&#x26;', '&#x27;',
'&#x28;', '&#x29;', '&#x2A;', '&#x2B;',
'&#x2C;', '&#x2D;', '&#x2E;', '&#x2F;',
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', ':', ';', '&#xA1;', '&#x3D;', '&#xBf;', '&#x3F;',
'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z', '&#x5B;', '&#x201C;', '&#x5D;', '&#x302;', '&#x307;',
'&#x2018;', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', '&#x2013;', '&#x2014;', '&#x30B;', '&#x303;', '&#x308;'
],
cmmi10: [
'&#x393;', '&#x394;', '&#x398;', '&#x39B;',
'&#x39E;', '&#x3A0;', '&#x3A3;', '&#x3A5;',
'&#x3A6;', '&#x3A8;', '&#x3A9;', '&#x3B1;',
'&#x3B2;', '&#x3B3;', '&#x3B4;', '&#x3B5;',
'&#x3B6;', '&#x3B7;', '&#x3B8;', '&#x3B9;',
'&#x3BA;', '&#x3BB;', '&#x3BC;', '&#x3BD;',
'&#x3BE;', '&#x3C0;', '&#x3C1;', '&#x3C3;',
'&#x3C4;', '&#x3C5;', '&#x3C6;', '&#x3C7;',
'&#x3C8;', '&#x3C9;', '&#x25B;', '&#x3D1;',
'&#x3D6;', '&#x3F1;', '&#x3C2;', '&#x3D5;',
'&#x21BC;', '&#x21BD;', '&#x21C0;', '&#x21C1;',
'&#xEFBA;', '&#xEFBB;', '&#x25B9;', '&#x25C3;',
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', '&#x2E;', '&#x2C;', '&#x3C;', '&#x2F;', '&#x3E;', '&#x22C6;',
'&#x2202;', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z', '&#x266D;', '&#x266E;', '&#x266F;', '&#x2323;', '&#x2322;',
'&#x2113;', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', '&#x131;', '&#xEEF0;', '&#x2118;', '&#x20D7;', '&#x0311;'
],
cmsy10: [
'&#x2212;', '&#xB7;', '&#xD7;', '&#x22C6;',
'&#xF7;', '&#x22C4;', '&#xB1;', '&#x2213;',
'&#x2295;', '&#x2296;', '&#x2297;', '&#x2298;',
'&#x2299;', '&#x25CB;', '&#x2218;', '&#x2219;',
'&#x2243;', '&#x224D;', '&#x2286;', '&#x2287;',
'&#x2264;', '&#x2265;', '&#x227C;', '&#x227D;',
'&#x223C;', '&#x2245;', '&#x2282;', '&#x2283;',
'&#x226A;', '&#x226B;', '&#x227A;', '&#x227B;',
'&#x2190;', '&#x2192;', '&#x2191;', '&#x2193;',
'&#x2194;', '&#x2197;', '&#x2198;', '&#x2242;',
'&#x21D0;', '&#x21D2;', '&#x21D1;', '&#x21D3;',
'&#x21D4;', '&#x2196;', '&#x2199;', '&#x221D;',
'&#x2032;', '&#x221E;', '&#x2208;', '&#x220B;',
'&#x25B3;', '&#x25BD;', '&#x338;', '&#xEFB9;',
'&#x2200;', '&#x2203;', '&#xAC;', '&#x2205;',
'&#x211C;', '&#x2111;', '&#x22A4;', '&#x22A5;',
'&#x2135;', '&#xEF35;', '&#x212C;', '&#xEF36;',
'&#xEF37;', '&#x2130;', '&#x2131;', '&#xEF38;',
'&#x210B;', '&#x2110;', '&#xEF39;', '&#xEF3A;',
'&#x2112;', '&#x2133;', '&#xEF3B;', '&#xEF3C;',
'&#xEF3D;', '&#xEF3E;', '&#x211B;', '&#xEF3F;',
'&#xEF40;', '&#xEF41;', '&#xEF42;', '&#xEF43;',
'&#xEF44;', '&#xEF45;', '&#xEF46;', '&#x222A;',
'&#x2229;', '&#x228E;', '&#x2227;', '&#x2228;',
'&#x22A2;', '&#x22A3;', '&#x230A;', '&#x230B;',
'&#x2308;', '&#x2309;', '&#x7B;', '&#x7D;',
'&#x2329;', '&#x232A;', '&#x2223;', '&#x2225;',
'&#x2195;', '&#x21D5;', '&#x2216;', '&#x2240;',
'&#x221A;', '&#x2210;', '&#x2207;', '&#x222B;',
'&#x2294;', '&#x2293;', '&#x2291;', '&#x2292;',
'&#xA7;', '&#x2020;', '&#x2021;', '&#xB6;',
'&#x2663;', '&#x2662;', '&#x2661;', '&#x2660;'
],
cmex10: [
'&#xF006;', '&#xF007;', '&#xF008;', '&#xF009;',
'&#xF00A;', '&#xF00B;', '&#xF00C;', '&#xF00D;',
'&#xF00E;', '&#xF00F;', '&#xF02C;', '&#xF02D;',
'&#xF012;', '&#xF013;', '&#xF014;', '&#xF015;',
'&#xF016;', '&#xF017;', '&#xF018;', '&#xF019;',
'&#xF01A;', '&#xF01B;', '&#xF01C;', '&#xF01D;',
'&#xF01E;', '&#xF01F;', '&#xF020;', '&#xF021;',
'&#xF02E;', '&#xF02F;', '&#xF024;', '&#xF025;',
'&#xF026;', '&#xEFBC;', '&#xEFBD;', '&#xEFBE;',
'&#xEFBF;', '&#xEFC0;', '&#xEFC1;', '&#xEFC2;',
'&#xEFC3;', '&#xEFC4;', '&#xF028;', '&#xF029;',
'&#xEFC7;', '&#xEFC8;', '&#xEFC9;', '&#xEFCA;',
'&#xF8EB;', '&#xF8F6;', '&#xF8EE;', '&#xF8F9;',
'&#xF8F0;', '&#xF8FB;', '&#xF8EF;', '&#xF8FA;',
'&#xF8F1;', '&#xF8FC;', '&#xF8F3;', '&#xF8FE;',
'&#xF8F2;', '&#xF8FD;', '&#xF8F4;', '&#xF8E6;',
'&#xF8ED;', '&#xF8F8;', '&#xF8EC;', '&#xF8F7;',
'&#xF02A;', '&#xF02B;', '&#xEFCD;', '&#xEFCE;',
'&#xEFCF;', '&#xEFD0;', '&#xEFD1;', '&#xEFD2;',
'&#xEFD3;', '&#xEFD4;', '&#xEFD5;', '&#xEFD6;',
'&#xEFD7;', '&#xEFD8;', '&#xEFD9;', '&#xEFDA;',
'&#xEFDB;', '&#xEFDC;', '&#xEFDD;', '&#xEFDE;',
'&#xEFDF;', '&#xEFE0;', '&#xEFE1;', '&#xEFE2;',
'&#xEFE3;', '&#xEFE4;', '&#xEFE5;', '&#xEFE6;',
'&#xEFE7;', '&#xEFE8;', '&#xEFE9;', '&#xEFEA;',
'&#xEFEB;', '&#xEFEC;', '&#xEFED;', '&#xEFEE;',
'&#xEFEF;', '&#xEFF0;', '&#xEFF1;', '&#xEFF2;',
'&#xEFF3;', '&#xEFF4;', '&#xEFF5;', '&#xEFF6;',
'&#xEFF7;', '&#xEFF8;', '&#xEFF9;', '&#xEFFA;',
'&#xEFFB;', '&#xEFFC;', '&#xEFFD;', '&#xEFFE;',
'&#xEFFF;', '&#xF000;', '&#xF001;', '&#xF002;',
'&#xF003;', '&#xF004;', '&#xF005;', '&#xF027;'
]
});
/*
* Adjust a few other characters as well
*/
jsMath.Update.TeXfonts({
cmr10: {'20': {c: '&#x02C7;', tclass: 'normal', w: .3}},
cmmi10: {
'20': {c: '<i>&kappa</i>', tclass: 'normal'},
'58': {c: '.', tclass: 'normal'},
'59': {c: ',', tclass: 'normal'},
'61': {c: '&#x2F;', tclass: 'cmr10'}
},
cmsy10: {
'3': {c: '*', tclass: 'normal'},
'16': {c: '&#x224D;'},
'17': {c: '&equiv;', tclass: 'normal'},
'25': {c: '&#x2248;', tclass: 'normal'},
'39': {c: '&#x2243;'},
'20': {c: '&le;', tclass: 'normal'}
},
cmex10: {'20': {c: '<span style="font-size: 80%">&#xEFBD;</span>'}},
cmti10: {'10': {c: '<i>&Omega;</i>', tclass: 'normal'}},
cmbx10: {'10': {c: '<b>&Omega;</b>', tclass: 'normal'}}
});
} else {
jsMath.Font.BaKoMa = [
'&#xA1;', '&#xA2;', '&#xA3;', '&#xA4;', '&#xA5;', '&#xA6;', '&#xA7;', '&#xA8;',
'&#xA9;', '&#xAA;', '&#xAD;', '&#xAE;', '&#xAF;', '&#xB0;', '&#xB1;', '&#xB2;',
'&#xB3;', '&#xB4;', '&#xB5;', '&#xB6;', '&#x2219;', '&#xB8;', '&#xB9;', '&#xBA;',
'&#xBB;', '&#xBC;', '&#xBD;', '&#xBE;', '&#xBF;', '&#xC0;', '&#xC1;', '&#xC2;',
'&#xC3;', '!', '"', '#', '$', '%', '&#x26;', '\'',
'(', ')', '*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', ':', ';', '&#x3C;', '=', '&#x3E;', '?',
'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
'&#x60;', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', '&#x7B;', '&#x7C;', '&#x7D;', '&#x7E;', '&#xC4;'
];
jsMath.Update.TeXfontCodes({
cmr10: jsMath.Font.BaKoMa,
cmmi10: jsMath.Font.BaKoMa,
cmsy10: jsMath.Font.BaKoMa,
cmex10: jsMath.Font.BaKoMa,
cmti10: jsMath.Font.BaKoMa,
cmbx10: jsMath.Font.BaKoMa
});
/*
* MSIE corrections
*/
switch (jsMath.browser) {
case "MSIE":
if (jsMath.platform == "pc") {
/*
* MSIE/PC
*/
jsMath.Browser.msieFontBug = 1;
jsMath.Update.TeXfonts({
cmr10: {'10': {c: '&Omega;', tclass: 'normal'}},
cmmi10: {
'10': {c: '<i>&Omega;</i>', tclass: 'normal'},
'126': {c: '&#x7E;<span style="margin-left:.1em"></span>'}
},
cmsy10: {
'10': {c: '&#x2297;', tclass: 'arial'},
'55': {c: '<span style="margin-right:-.54em">7</span>'}
},
cmex10: {'10': {c: '<span style="font-size: 67%">D</span>'}},
cmti10: {'10': {c: '<i>&Omega;</i>', tclass: 'normal'}},
cmbx10: {'10': {c: '<b>&Omega;</b>', tclass: 'normal'}}
});
} else {
/*
* MSIE/Mac
*/
jsMath.Update.TeXfonts({
cmr10: {
'3': {c: '<font face="Symbol">L</font>', tclass: 'normal'},
'5': {c: '<font face="Symbol">P</font>', tclass: 'normal'},
'10': {c: '<font face="Symbol">W</font>', tclass: 'normal'},
'15': {c: 'ffl', tclass: 'normal'},
'16': {c: '&#x0131;', tclass: 'normal'},
'20': {c: '&#x02C7;', tclass: 'normal'},
'22': {c: '&#xAF;', tclass: 'normal', w: .3},
'25': {c: '&#xDF;', tclass: 'normal'},
'26': {c: '&#xE6;', tclass: 'normal'},
'27': {c: '&#x153;', tclass: 'normal'}
},
cmmi10: {
'3': {c: '<font face="Symbol">L</font>', tclass: 'italic'},
'5': {c: '<font face="Symbol">P</font>', tclass: 'italic'},
'10': {c: '<font face="Symbol">W</font>', tclass: 'italic'},
'15': {c: '<font face="Symbol">e</font>', tclass: 'italic'},
'16': {c: '<font face="Symbol">z</font>', tclass: 'italic'},
'20': {c: '<font face="Symbol">k</font>', tclass: 'italic'},
'22': {c: '<font face="Symbol">m</font>', tclass: 'italic'},
'25': {c: '<font face="Symbol">p</font>', tclass: 'italic'},
'26': {c: '<font face="Symbol">r</font>', tclass: 'italic'},
'27': {c: '<font face="Symbol">s</font>', tclass: 'italic'}
},
cmsy10: {
'3': {c: '<span style="vertical-align:-.3em">*</span>', tclass: 'normal'},
'5': {c: '&#x389;', tclass: 'normal'},
'10': {c: '&otimes;', tclass: 'normal'},
'15': {c: '&#x2022;', tclass: 'normal'},
'16': {c: '&#x224D;', tclass: 'normal'},
'20': {c: '&le;', tclass: 'normal'},
'22': {c: '&le;', tclass: 'normal'},
'25': {c: '&#x2248;', tclass: 'normal'},
'26': {c: '<font face="Symbol">&#xCC;</font>', tclass: 'normal'},
'27': {c: '<font face="Symbol">&#xC9;</font>', tclass: 'normal'}
},
cmex10: {
'3': {c: '<span style="font-size: 67%">&#x69;</span>'},
'5': {c: '<span style="font-size: 67%">&#x6B;</span>'},
'10': {c: '<span style="font-size: 67%">&#x44;</span>'},
'15': {c: '<span style="font-size: 55%">&#xC2;</span>'},
'16': {c: '<span style="font-size: 83%">&#xB5;</span>'},
'20': {c: '<span style="font-size: 83%">"</span>'},
'22': {c: '<span style="font-size: 83%">$</span>'},
'25': {c: '<span style="font-size: 83%">\'</span>'},
'26': {c: '<span style="font-size: 83%">(</span>'},
'27': {c: '<span style="font-size: 83%">)</span>'}
},
cmti10: {
'3': {c: '<font face="Symbol">L</font>', tclass: 'italic'},
'5': {c: '<font face="Symbol">P</font>', tclass: 'italic'},
'10': {c: '<font face="Symbol">W</font>', tclass: 'italic'},
'16': {c: '&#x0131;', tclass: 'italic'},
'20': {c: '&#xAD;', tclass: 'italic'},
'22': {c: '&#xAF;', tclass: 'italic', w: .3},
'25': {c: '&#xDF;', tclass: 'italic'},
'26': {c: '&#xE6;', tclass: 'italic'},
'27': {c: '&#x153;', tclass: 'italic'}
},
cmbx10: {
'3': {c: '<font face="Symbol">L</font>', tclass: 'bold'},
'5': {c: '<font face="Symbol">P</font>', tclass: 'bold'},
'10': {c: '<font face="Symbol">W</font>', tclass: 'bold'},
'16': {c: '&#x0131;', tclass: 'bold'},
'20': {c: '&#xAD;', tclass: 'bold'},
'22': {c: '&#xAF;', tclass: 'bold', w: .3},
'25': {c: '&#xDF;', tclass: 'bold'},
'26': {c: '&#xE6;', tclass: 'bold'},
'27': {c: '&#x153;', tclass: 'bold'}
}
});
}
break;
case "Mozilla":
if (jsMath.platform == "mac") {
/*
* Mozilla/Mac
*/
jsMath.Update.TeXfonts({
cmr10: {'10': {c: '&Omega;', tclass: 'normal'}},
cmmi10: {'10': {c: '<i>&Omega;</i>', tclass: 'normal'}},
cmsy10: {'10': {c: '&otimes;', tclass: 'normal'}},
cmex10: {'10': {c: '<span style="font-size: 67%">D</span>'}},
cmti10: {'10': {c: '<i>&Omega;</i>', tclass: 'normal'}},
cmbx10: {'10': {c: '<b>&Omega;</b>', tclass: 'normal'}}
});
}
break;
case "Opera":
jsMath.Update.TeXfonts({
cmr10: {
'10': {c: '&Omega;', tclass: 'normal'},
'20': {c: '&#x2C7;', tclass: 'normal'}
},
cmmi10: {
'10': {c: '<i>&Omega;</i>', tclass: 'normal'},
'20': {c: '&kappa;', tclass: 'normal'}
},
cmsy10: {
'10': {c: '&otimes;', tclass: 'normal'},
'20': {c: '&#x2264;', tclass: 'normal'}
},
cmex10: {
'10': {c: '<span style="font-size: 67%">D</span>'},
'20': {c: '<span style="font-size: 82%">"</span>'}
},
cmti10: {
'10': {c: '<i>&Omega;</i>', tclass: 'normal'},
'20': {c: '<i>&#x2C7;</i>', tclass: 'normal'}
},
cmbx10: {
'10': {c: '<b>&Omega;</b>', tclass: 'normal'},
'20': {c: '<b>&#x2C7;</b>', tclass: 'normal'}
}
});
break;
case "Konqueror":
jsMath.Update.TeXfonts({
cmr10: {'20': {c: '&#x2C7;', tclass: 'normal'}},
cmmi10: {'20': {c: '&kappa;', tclass: 'normal'}},
cmsy10: {'20': {c: '&#x2264;', tclass: 'normal'}},
cmex10: {'20': {c: '<span style="font-size: 84%">"</span>'}},
cmti10: {'20': {c: '<i>&#x2C7;</i>', tclass: 'normal'}},
cmbx10: {'20': {c: '<b>&#x2C7;</b>', tclass: 'normal'}}
});
break;
}
}
jsMath.Setup.Styles({
'.typeset .cmr10': 'font-family: CMR10, serif',
'.typeset .cmbx10': 'font-family: CMBX10, CMR10',
'.typeset .cmti10': 'font-family: CMTI10, CMR10',
'.typeset .cmmi10': 'font-family: CMMI10',
'.typeset .cmsy10': 'font-family: CMSY10',
'.typeset .cmex10': 'font-family: CMEX10',
'.typeset .arial': "font-family: 'Arial unicode MS'"
});

View File

@ -0,0 +1,53 @@
<html>
<head>
<!--
| jsMath-autoload.html
|
| Part of the jsMath package for mathematics on the web.
|
| This file is used for loading jsMath.js and other components
| when the "autoload" plugin is used.
|
| ---------------------------------------------------------------------
|
| Copyright 2004-2006 by Davide P. Cervone
|
| Licensed under the Apache License, Version 2.0 (the "License");
| you may not use this file except in compliance with the License.
| You may obtain a copy of the License at
|
| http://www.apache.org/licenses/LICENSE-2.0
|
| Unless required by applicable law or agreed to in writing, software
| distributed under the License is distributed on an "AS IS" BASIS,
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
| See the License for the specific language governing permissions and
| limitations under the License.
-->
</head>
<body>
<script>
var isOmniWeb4 = (document.readyState &&
document.readyState == 'loading' &&
navigator.accentColorName != null &&
navigator.omniWebString == null);
window.jsMath = window.parent.jsMath;
window.jsMathAutoload = 1;
if (isOmniWeb4) {
if (jsMath.Autoload.Script.url != jsMath.Autoload.Script.prevURL) {
jsMath.Autoload.Script.prevURL = jsMath.Autoload.Script.url;
document.write('<script src="'+jsMath.Autoload.Script.url+'"><'+'/script>');
document.write('<script src="jsMath-loader-omniweb4.js"><'+'/script>');
}
} else {
document.write('<script src="'+jsMath.Autoload.Script.url+'"><'+'/script>');
}
</script>
<script>
if (window.jsMath && !isOmniWeb4) {jsMath.Autoload.Script.endLoad()}
</script>
</body>
</html>

View File

@ -0,0 +1,467 @@
<html>
<head>
<!--
| jsMath-controls.html
|
| Part of the jsMath package for mathematics on the web.
|
| This file handles the details of the jsMath control panels
|
| ---------------------------------------------------------------------
|
| Copyright 2004-2007 by Davide P. Cervone
|
| Licensed under the Apache License, Version 2.0 (the "License");
| you may not use this file except in compliance with the License.
| You may obtain a copy of the License at
|
| http://www.apache.org/licenses/LICENSE-2.0
|
| Unless required by applicable law or agreed to in writing, software
| distributed under the License is distributed on an "AS IS" BASIS,
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
| See the License for the specific language governing permissions and
| limitations under the License.
-->
</head>
<body>
<script>
var showWarning = 0;
var domain = document.domain || "";
var mustPost = ((domain == "" || domain == "localhost") && window.postMessage);
while (!window.jsMath && !showWarning) {
try {
window.jsMath = window.parent.jsMath;
if (!window.jsMath) {throw "no jsMath";}
} catch (err) {
showWarning = 1; pageDomain = '';
try {pageDomain = document.domain} catch (err) {}
//
// MSIE on Mac can't change document.domain, and 'try' won't
// catch the error (Grrr!) so don't even attempt it.
//
if (pageDomain.match(/\..*\./) &&
(navigator.appName != 'Microsoft Internet Explorer' ||
!navigator.platform.match(/Mac/) || !navigator.userProfile || !document.all)) {
try {
document.domain = pageDomain.replace(/^[^.]*\./,'');
showWarning = 0;
} catch(err) {}
}
}
}
function Warning () {
alert(
"jsMath can't open the control panel, since jsMath was not " +
"obtained from a server that is in the same domain as the " +
"page that loaded it."
);
}
if (showWarning) {
if (!mustPost) setTimeout("Warning()",1);
} else {
var debug = window.parent.debug;
var show = window.parent.show;
}
</SCRIPT>
<SCRIPT ID="jsMath_script">
if (window.jsMath) {
jsMath.Add(jsMath.Controls,{
loaded: 1,
mainLabels: {
print: 'Print', reload: 'Reload', local: 'Go Local', global: 'Go Global',
ctrls: 'Controls', opts: 'Options', done: 'Done'
},
optionLabels: {back: 'Back', done: 'Done'},
Close: function () {
this.panel.style.display = "none";
jsMath.Element("button").style.display = (this.cookie.button ? "block" : "none");
if (jsMath.document.location.protocol == 'file:' && jsMath.Global.islocal) return;
for (var id in {scale:1, scaleImg:1, font:1, print:1, printwarn:1,
stayhires:1, autofont:1, alpha:1, tex2math:1, global:1}) {
if (this.cookie[id] && this.cookie[id] != this.oldCookie[id] &&
this.oldCookie[id] != null) {
this.Reload();
return;
}
}
},
Main: function () {
this.oldCookie = {}; jsMath.Add(this.oldCookie,this.cookie);
this.GetPanel("main");
jsMath.Element("_version").innerHTML = jsMath.version;
jsMath.Element("_fontType").innerHTML =
({tex:"TeX",
image:"Image",
symbol:"Image symbol",
unicode:"Unicode"})[this.cookie.font];
jsMath.Element("_mailto").href =
"mailto:dpvc@union.edu?subject=Bug Report for jsMath "
+ jsMath.version + " (using " + jsMath.browser
+ " in " + this.cookie.font + " mode)";
if (this.cookie.print ||
(this.cookie.font != 'image' && this.cookie.font != 'symbol'))
{jsMath.Element("_resolution").disabled = true}
if (jsMath.Global.isLocal) {
jsMath.Element("_ctrls").disabled = true;
} else {
this.cookie.hiddenGlobal = jsMath.Global.isHidden;
jsMath.Element("_global").style.display = "none";
jsMath.Element("_local").style.display = "";
if (!jsMath.Global.isHidden || jsMath.noShowGlobal)
{jsMath.Element("_ctrls").disabled = true}
}
if (jsMath.noChangeGlobal) {
for (var id in {global:1, local:1, ctrls: 1})
{jsMath.Element('_'+id).disabled = true}
}
if (!window.print) {jsMath.Element("_print").disabled = true}
if (jsMath.Browser.safariButtonBug) {
for (var id in this.mainLabels)
{jsMath.Element('_'+id).value = this.mainLabels[id]}
}
this.panel.style.display = "block";
this.openMain = 0;
},
Options: function () {
this.GetPanel("options");
jsMath.Element("_scale").value = this.cookie.scale;
jsMath.Element("_keep").value = this.cookie.keep;
jsMath.Element("_global").value = this.cookie.global;
for (var id in {autofont:1, scaleImg:1, alpha:1, warn:1, printwarn: 1,
stayhires: 1, button:1, progress:1, asynch:1, blank:1, tex2math:1}) {
if (this.cookie[id]) {jsMath.Element('_'+id).checked = true}
}
var font = jsMath.document.getElementsByName("jsMath__font");
for (var i = 0; i < font.length; i++) {
if ((font[i].value == 'tex' && jsMath.nofonts) ||
((font[i].value == 'symbol' || font[i].value == 'image') &&
jsMath.noImgFonts)) {
jsMath.Element('_'+font[i].value+"Text").className = "disabled";
font[i].disabled = true;
}
else if (this.cookie.font == font[i].value) {font[i].checked = true}
}
if (jsMath.noImgFonts) {
for (var id in {alpha:1, printwarn:1, stayhires:1}) {
var obj = jsMath.Element("_"+id);
obj.disabled = true;
obj.parentNode.className = "disabled";
}
} else if (jsMath.Browser.imgScale != 1) {
jsMath.Element("_alphaText").className = "disabled";
jsMath.Element("_alpha").disabled = true;
}
if (jsMath.tex2math.Convert) {
jsMath.Element("_separator").style.display = '';
jsMath.Element("_tex2mathRow").style.display = '';
}
if (jsMath.noChangeGlobal) {
jsMath.Element("_globalText").className = "disabled";
jsMath.Element("_global").disabled = true;
}
if (jsMath.isCHMmode) {
jsMath.Element("_asynchText").className = "disabled";
jsMath.Element("_asynch").disabled = true;
}
if (jsMath.Browser.safariButtonBug) {
for (var id in this.optionLabels)
{jsMath.Element('_'+id).value = this.optionLabels[id]}
}
this.panel.style.display = "block";
if (jsMath.Browser.msieMoveButtonHack) {
this.panel.style.left = "0px";
this.panel.style.top = "0px";
jsMath.Controls.MoveButton();
}
},
HTML: {}, // storage for panels for Firefox3 in local mode
GetPanel: function (name) {
this.panel.innerHTML = ""; // for MSIE on the Mac
var html = this.HTML[name];
if (html == null) {html = document.getElementById("jsMath_"+name).innerHTML}
this.panel.innerHTML = html;
},
SaveOptions: function (close) {
this.cookie.scale = jsMath.Element("_scale").value;
var font = jsMath.document.getElementsByName("jsMath__font");
for (var i = 0; i < font.length; i++)
{if (font[i].checked) {this.cookie.font = font[i].value}}
for (var id in {autofont:1, scaleImg:1, alpha:1, warn:1, printwarn: 1,
stayhires: 1, button:1, progress:1, asynch:1, blank:1, tex2math:1}) {
if (this.cookie[id] != null) {
this.cookie[id] = jsMath.Element('_'+id).checked ? 1: 0;
}
}
this.cookie.keep = jsMath.Element("_keep").value;
this.cookie.global = jsMath.Element("_global").value;
this.cookie.print = this.cookie.stayhires;
this.SetCookie(1);
if (close) {this.Close()} else {this.Main()}
},
PrintResolution: function () {
this.cookie.print = 1;
this.SetCookie(1);
this.Close();
},
Print: function () {
this.Close();
jsMath.window.print();
},
GoGlobal: function () {
this.cookie.global = "always";
jsMath.Global.GoGlobal(this.SetCookie(2));
},
GoLocal: function () {jsMath.Global.GoLocal()},
ShowControls: function () {
this.Close();
jsMath.Global.Show();
},
NoAuto: function () {jsMath.Element("_autofont").checked = false}
});
jsMath.Add(jsMath.Post.Commands,{
PAN: function (message) {jsMath.Controls.HTML.main = message},
OPT: function (message) {jsMath.Controls.HTML.options = message},
PST: function (message) {
jsMath.Controls.Main();
jsMath.Script.endLoad();
jsMath.Message.doClear();
}
});
}
</script>
<!------------------------------------------------------------>
<div id="jsMath_main">
<div style="text-align:center">
<b style="font-size:133%">jsMath v<span ID="jsMath__version"></span></b>
(<span id="jsMath__fontType">type</span> fonts)
[<a target="_blank" href="http://www.math.union.edu/locate/jsMath/users/main.html">help</a>]
<p style="margin-bottom:0px">
<table border="0" cellspacing="0" cellpadding="0" style="margin:0px">
<tr valign="middle"><td align="center">
<table border="0" cellspacing="0" cellpadding="0">
<tr><td class="infoLink" align="left">&#8226; <a target="_blank" href="http://www.math.union.edu/locate/jsMath/users/quickstart.html">Quick Start</a></td></tr>
<tr><td class="infoLink" align="left">&#8226; <a target="_blank" href="http://www.math.union.edu/locate/jsMath/users/fonts.html">Missing Fonts</a></td></tr>
<tr><td class="infoLink" align="left">&#8226; <a target="_blank" href="http://www.math.union.edu/locate/jsMath/users/printing.html">Printing Issues</a></td></tr>
<tr><td height="5"></td></tr>
<tr><td class="infoLink" align="left">&#8226; <a target="_blank" href="http://www.math.union.edu/locate/jsMath">Home Page</a></td></tr>
<tr><td class="infoLink" align="left">&#8226; <a target="_blank" href="http://www.math.union.edu/locate/jsMath/users/">Documentation</a></td></tr>
<tr><td class="infoLink" align="left">&#8226; <a target="_blank" href="https://sourceforge.net/forum/?group_id=172663">User Community</a></td></tr>
<tr><td height="5"></td></tr>
<tr><td class="infoLink" align="left">&#8226; <a target="_blank" href="http://www.math.union.edu/locate/jsMath/bugs.html">Known Bugs</a></td></tr>
<tr><td class="infoLink" align="left">&#8226; <a id="jsMath__mailto" href="mailto:dpvc@union.edu?subject=jsMath Bug Report">Report a Bug</a></td></tr>
<tr><td height="5"></td></tr>
<tr><td class="infoLink" align="left">&#8226; <a target="_blank" href="http://www.math.union.edu/locate/jsMath/jsMath/COPYING.txt">License</a></td></tr>
</table>
</td>
<td style="width:1em">&nbsp;</td>
<td align="center">
<table border="0" cellspacing="0" cellpadding="0">
<tr><td align="center" colspan="3">
<input type="button" id="jsMath__resolution" value="Hi-Res Fonts for Printing"
style="width:18em" onclick="jsMath.Controls.PrintResolution()" />
</td></tr>
<tr><td height="8"></td></tr>
<tr valign="bottom"><td align="left">
<input type="button" value="Print" id="jsMath__print" style="width:8em" onclick="jsMath.Controls.Print()" /><br />
<input type="button" value="Reload" id="jsMath__reload" style="width:8em" style="width:8em" onclick="jsMath.window.location.reload()" /><br />
</td><td>
&nbsp;
</td><td align="right">
<input type="button" value="Go Global" id="jsMath__global" style="width:8em" onclick="jsMath.Controls.GoGlobal()"a /><!--
--><input type="button" value="Go Local" id="jsMath__local" style="width:8em;display:none" onclick="jsMath.Controls.GoLocal()" /><br />
<input type="button" value="Controls" id="jsMath__ctrls" style="width:8em" onclick="jsMath.Controls.ShowControls()" /><br/>
</td></tr>
<tr><td height="8"></td></tr>
<tr valign="bottom"><td align="left">
<input type="button" value="Options" id="jsMath__opts" style="width:8em" onclick="jsMath.Controls.Options()" /><br/>
</td><td>
&nbsp;
</td><td align="right">
<input type="button" value="Done" id="jsMath__done" style="width:8em" onclick="jsMath.Controls.Close()" />
</td></tr>
</table></td></tr>
<tr><td height="10"></td></tr>
<tr>
<td colspan="3" align="center" style="width:26em">
<i style="font-size:75%">Click the jsMath button or <nobr>ALT-click</nobr>
on mathematics to reopen this panel.</i>
</td></tr>
</table></p>
</div>
</div>
<!------------------------------------------------------------>
<div id="jsMath_options">
<div style="text-align:center">
<b style="font-size:133%">jsMath Options</b>
[<a target="_blank" href="http://www.math.union.edu/locate/jsMath/users/help.html">help</a>]
<p>
<form action="javascript:" style="margin:0px">
<table border="0" cellspacing="0" cellpadding="0">
<tr valign="top"><td>
<table border="0" cellspacing="0" cellpadding="0" style="text-align:left">
<tr><td><input type="checkbox" id="jsMath__autofont" value="1" /> Autoselect best font</td></tr>
<tr><td><input type="checkbox" id="jsMath__warn" value="1" /> Show font warnings</td></tr>
<tr><td><input type="checkbox" id="jsMath__alpha" value="1" /> Use image alpha channels</td></tr>
<tr><td><input type="checkbox" id="jsMath__printwarn" value="1" /> Print image-font help</td></tr>
<tr><td><input type="checkbox" id="jsMath__stayhires" value="1" /> Always use hi-res fonts</td></tr>
<tr><td style="height:.8em"></td></tr>
<tr><td><input type="checkbox" id="jsMath__progress" value="1" /> Show progress messages</td></tr>
<tr><td><input type="checkbox" id="jsMath__asynch" value="1" /> <span id="jsMath__asynchText">Force asynchronous processing</span></td></tr>
<tr><td><input type="checkbox" id="jsMath__blank" value="1" /> Don't show page until complete</td></tr>
<tr><td><input type="checkbox" id="jsMath__button" value="1" /> Show jsMath button</td></tr>
<tr id="jsMath__separator" style="display:none"><td style="height:.8em"></td></tr>
<tr id="jsMath__tex2mathRow" style="display:none"><td><input type="checkbox" id="jsMath__tex2math" value="1" /> Enable <code>tex2math</code> plug-in</td></tr>
</td></tr>
</table>
</td>
<td style="width:2em"></td>
<td>
<table border="0" cellspacing="0" cellpadding="0" style="text-align:left">
<tr><td>Scale all mathematics to <input type="text" id="jsMath__scale" value="100" size="3" />%</td></tr>
<tr><td style="height:.5em"></td></tr>
<tr><td><input type="radio" name="jsMath__font" value="tex" onclick="jsMath.Controls.NoAuto()" />
<span id="jsMath__texText">Use native TeX fonts</span>
<small>(<a target="_blank" href="http://www.math.union.edu/locate/jsMath/download/jsMath-fonts.html">download</a>)</small>
</td></tr>
<tr><td><input type="radio" name="jsMath__font" value="image" onclick="jsMath.Controls.NoAuto()" />
<span id="jsMath__imageText">Use image fonts
<span id="jsMath__scaleImgText">(<input type="checkbox" id="jsMath__scaleImg" value="1" /> scalable)</span></span></td></tr>
<tr><td><input type="radio" name="jsMath__font" value="symbol" onclick="jsMath.Controls.NoAuto()" />
<span id="jsMath__symbolText">Use images for symbols only</span></td></tr>
<tr><td height="2"></td></tr>
<tr><td><input type="radio" name="jsMath__font" value="unicode" onclick="jsMath.Controls.NoAuto()" />
Use native Unicode fonts</td></tr>
<tr><td style="height:1em"></td></tr>
<tr><td align="center"><span id="jsMath__globalText">Use Global mode</span>
<select id="jsMath__global">
<option value="auto">when requested
<option value="always">always
<option value="never">never
</select>
</td></tr>
<tr><td height="3"></td></tr>
<tr><td>Save settings for
<select id="jsMath__keep">
<option value="0D">this session only
<option value="1D">1 day
<option value="2D">2 days
<option value="3D">3 days
<option value="1W">1 week
<option value="2W">2 weeks
<option value="1M">1 month
<option value="2M">2 months
<option value="3M">3 months
<option value="6M">6 months
<option value="1Y">1 year
<option value="5Y">5 years
</select>
</td></tr>
<tr><td style="height:1em"></td></tr>
</table>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td align="left">&nbsp;
<input type="button" value="Back" id="jsMath__back" style="width:8em" onclick="jsMath.Controls.SaveOptions(0)" />
&nbsp;&nbsp;
</td>
<td align="right">
<input type="button" value="Done" id="jsMath__done" style="width:8em" onclick="jsMath.Controls.SaveOptions(1)" />
&nbsp;
</td>
</tr>
</table>
</td></tr>
</table>
</form>
</div>
</div>
</p>
<!------------------------------------------------------------>
<script>
if (showWarning) {
if (mustPost) {
var scr = document.getElementById("jsMath_script");
window.parent.postMessage("jsMCP:SCR:"+scr.innerHTML,"*");
var main = document.getElementById("jsMath_main");
window.parent.postMessage("jsMCP:PAN:"+main.innerHTML,"*");
var options = document.getElementById("jsMath_options");
window.parent.postMessage("jsMCP:OPT:"+options.innerHTML,"*");
window.parent.postMessage("jsMCP:PST:","*");
}
} else {
jsMath.Controls.Main()
}
</script>
<script>
if (window.jsMath) {
jsMath.Script.endLoad();
jsMath.Message.doClear();
}
</script>
</body>
</html>

View File

@ -0,0 +1,157 @@
/*
* jsMath-easy-load.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file is used to load jsMath with one easy <SCRIPT>
* command in your HTML file. It is called by the files
* in the jsMath/easy/ directory. It expects that the jsMath.Easy
* array has been initialized before it is called.
*
* ---------------------------------------------------------------------
*
* Copyright 2007 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
if (!window.jsMath) {window.jsMath = {}}
if (!jsMath.Easy) {jsMath.Easy = {}}
if (!jsMath.tex2math) {jsMath.tex2math = {}}
jsMath.tex2math.doubleDollarsAreInLine = jsMath.Easy.doubleDollarsAreInLine;
jsMath.tex2math.allowDisableTag = jsMath.Easy.allowDisableTag;
jsMath.safeHBoxes = jsMath.Easy.safeHBoxes;
if (jsMath.Easy.scale) {
if (!jsMath.Controls) {jsMath.Controls = {}}
if (!jsMath.Controls.cookie) {jsMath.Controls.cookie = {}}
jsMath.Controls.cookie.scale = jsMath.Easy.scale;
}
if (!jsMath.Easy.allowDoubleClicks) {
if (!jsMath.Click) {jsMath.Click = {}}
jsMath.Click.CheckDblClick = function () {};
}
if (!jsMath.Easy.showFontWarnings) {
if (!jsMath.Font) {jsMath.Font = {}}
jsMath.Font.Message = function () {};
}
if (!jsMath.Easy.allowGlobal) {
if (!jsMath.Controls) {jsMath.Controls = {}}
if (!jsMath.Controls.cookie) {jsMath.Controls.cookie = {}}
jsMath.Controls.cookie.global = 'never';
jsMath.noGoGlobal = 1;
jsMath.noChangeGlobal = 1;
jsMath.noShowGlobal = 1;
}
if (jsMath.Easy.noImageFonts) {
jsMath.noImgFonts = 1;
if (!jsMath.Font) {jsMath.Font = {}}
jsMath.Font.extra_message =
'Extra TeX fonts not found: <b><span id="jsMath_ExtraFonts"></span></b><br/>'
+ 'Using unicode fonts instead. This may be slow and might not print well.<br/>\n'
+ 'Use the jsMath control panel to get additional information.';
}
if (jsMath.Easy.processSingleDollars ||
jsMath.Easy.processDoubleDollars ||
jsMath.Easy.processSlashParens ||
jsMath.Easy.processSlashBrackets ||
jsMath.Easy.fixEscapedDollars) {
jsMath.Easy.findCustomSettings = {
processSingleDollars: jsMath.Easy.processSingleDollars,
processDoubleDollars: jsMath.Easy.processDoubleDollars,
processSlashParens: jsMath.Easy.processSlashParens,
processSlashBrackets: jsMath.Easy.processSlashBrackets,
processLaTeXenvironments: jsMath.Easy.processLaTeXenvironments,
fixEscapedDollars: jsMath.Easy.fixEscapedDollars,
custom: 0
}
}
if (!jsMath.Autoload) {jsMath.Autoload = {}}
jsMath.Autoload.root = jsMath.Easy.root+'/';
if (jsMath.Easy.autoload) {
jsMath.Autoload.findTeXstrings = 0;
jsMath.Autoload.findLaTeXstrings = 0;
jsMath.Autoload.findCustomStrings = jsMath.Easy.customDelimiters;
jsMath.Autoload.findCustomSettings = jsMath.Easy.findCustomSettings;
jsMath.Autoload.loadFiles = jsMath.Easy.loadFiles;
jsMath.Autoload.loadFonts = jsMath.Easy.loadFonts;
jsMath.Autoload.macros = jsMath.Easy.macros;
jsMath.Autoload.delayCheck = 1;
jsMath.Easy.autoloadCheck = 1;
document.write('<script src="'+jsMath.Autoload.root+'plugins/autoload.js"></script>');
} else {
jsMath.Easy.tex2math =
(jsMath.Easy.processSingleDollars ||
jsMath.Easy.processDoubleDollars ||
jsMath.Easy.processSlashParens ||
jsMath.Easy.processSlashBrackets ||
jsMath.Easy.processLaTeXenvironments ||
jsMath.Easy.fixEscapedDollars ||
jsMath.Easy.customDelimiters);
if (!jsMath.Setup) {jsMath.Setup = {}}
if (!jsMath.Setup.UserEvent) {jsMath.Setup.UserEvent = {}}
jsMath.Setup.UserEvent.onload = function () {
var easy = jsMath.Easy;
if (easy.tex2math) jsMath.Setup.Script("plugins/tex2math.js");
var i;
if (easy.loadFiles) {
for (i = 0; i < easy.loadFiles.length; i++)
jsMath.Setup.Script(easy.loadFiles[i]);
}
if (easy.loadFonts) {
for (i = 0; i < easy.loadFonts.length; i++)
jsMath.Font.Load(easy.loadFonts[i]);
}
if (easy.macros) {
for (i in easy.macros) {
if (typeof(easy.macros[i]) == 'string') {
jsMath.Macro(i,easy.macros[i]);
} else {
jsMath.Macro(i,easy.macros[i][0],easy.macros[i][1]);
}
}
}
}
document.write('<script src="'+jsMath.Easy.root+'/jsMath.js"></script>'+"\n");
}
jsMath.Easy.onload = function () {
if (jsMath.Easy.loaded) {return} else {jsMath.Easy.loaded = 1}
if (jsMath.Easy.autoloadCheck) jsMath.Autoload.Check();
if (jsMath.Easy.tex2math) {
jsMath.Synchronize(function () {
if (jsMath.Easy.findCustomSettings)
jsMath.tex2math.Convert(document,jsMath.Easy.findCustomSettings);
if (jsMath.Easy.customDelimiters) {
var s = jsMath.Easy.customDelimiters;
jsMath.tex2math.CustomSearch(s[0],s[1],s[2],s[3]);
jsMath.tex2math.ConvertCustom();
}
});
}
(jsMath[jsMath.Easy.method])();
}
if (window.addEventListener) {window.addEventListener("load",jsMath.Easy.onload,false)}
else if (window.attachEvent) {window.attachEvent("onload",jsMath.Easy.onload)}
else {window.onload = jsMath.Easy.onload}

View File

@ -0,0 +1,107 @@
/*
* jsMath-fallback-mac-mozilla.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file makes changes needed by Mozilla-based browsers on the Mac
* for when the TeX fonts are not available.
*
* ---------------------------------------------------------------------
*
* Copyright 2004-2006 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/********************************************************************
*
* Fix the default non-TeX-font characters to work with Mozilla
*
*/
jsMath.Update.TeXfonts({
cmmi10: {
// '41': // leftharpoondown
// '43': // rightharpoondown
'44': {c: '<span style="position:relative; top:.15em; margin-right:-.1em; margin-left:-.2em">&#x02D3;</span>'},
'45': {c: '<span style="position:relative; top:.15em; margin-right:-.1em; margin-left:-.2em">&#x02D2;</span>'},
'47': {c: '<span style="font-size:60%">&#x25C1;</span>'},
// '92': // natural
'126': {c: '<span style="position:relative; left: .3em; top: -.7em; font-size: 50%">&#x2192;</span>'}
},
cmsy10: {
'0': {c: '&ndash;', tclass: 'normal'},
'11': {c: '<span style="font-size: 70%">&#x25EF;</span><span style="position:relative; margin-left:-.5em; top:.1em; margin-right:.3em">/</span>', tclass: 'normal'},
'42': {c: '&#x2963;'}, '43': {c: '&#x2965'},
'48': {c: '<span style="font-size: 133%; margin-right: -.75em; position: relative; top:.4em">&#x2032;</span>', tclass: 'normal'},
'93': {c: '&#x222A;<span style="font-size: 50%; margin-left:-1.3em; position: relative; top:-.3em; margin-right:.6em">+</span>'},
'104': {c: '<span style="position:relative; top:.15em; margin-left:-.6em">&#x3008;</span>'},
'105': {c: '<span style="position:relative; top:.15em; margin-right:-.6em">&#x3009;</span>'},
'109': {c: '&#x2963;<span style="position:relative; top:.1em; margin-left:-1em">&#x2965;</span>'}
//, '116': // sqcup
// '117': // sqcap
// '118': // sqsubseteq
// '119': // sqsupseteq
},
cmex10: {
'10': {c: '<span style="position:relative; top:.1em; margin-left:-.6em">&#x3008;</span>'},
'11': {c: '<span style="position:relative; top:.1em; margin-right:-.6em">&#x3009;</span>'},
'14': {c: '/'}, '15': {c: '\\'},
'28': {c: '<span style="position:relative; top:.1em; margin-left:-.6em">&#x3008;</span>'},
'29': {c: '<span style="position:relative; top:.1em; margin-right:-.6em">&#x3009;</span>'},
'30': {c: '/'}, '31': {c: '\\'},
'42': {c: '<span style="position:relative; top:.1em; margin-left:-.6em">&#x3008;</span>'},
'43': {c: '<span style="position:relative; top:.1em; margin-right:-.6em">&#x3009;</span>'},
'44': {c: '/'}, '45': {c: '\\'},
'46': {c: '/'}, '47': {c: '\\'},
'68': {c: '<span style="position:relative; top:.1em; margin-left:-.6em">&#x3008;</span>'},
'69': {c: '<span style="position:relative; top:.1em; margin-right:-.6em">&#x3009;</span>'},
// '70': // sqcup
// '71': // big sqcup
'72': {ic: .194}, '73': {ic: .444},
'82': {tclass: 'bigop1cx', ic: .15}, '90': {tclass: 'bigop2cx', ic:.6},
'85': {c: '&#x222A;<span style="font-size: 50%; margin-left:-1.3em; position: relative; top:-.3em; margin-right:.6em">+</span>'},
'93': {c: '&#x222A;<span style="font-size: 50%; margin-left:-1.3em; position: relative; top:-.3em; margin-right:.6em">+</span>'}
}
});
jsMath.Setup.Styles({
'.typeset .symbol': "font-family: Osaka",
'.typeset .arrow1': "font-family: Osaka; position: relative; top: .125em; margin: -1px",
'.typeset .arrow2': "font-family: AppleGothic; font-size: 100%; position:relative; top: .11em; margin:-1px",
'.typeset .bigop1': "font-family: AppleGothic; font-size: 110%; position:relative; top: .9em; margin:-.05em",
'.typeset .bigop1b': "font-family: Osaka; font-size: 140%; position: relative; top: .8em; margin:-.1em",
'.typeset .bigop1c': "font-family: AppleGothic; font-size: 125%; position:relative; top: .85em; margin:-.3em",
'.typeset .bigop1cx': "font-family: 'Apple Chancery'; font-size: 125%; position:relative; top: .7em; margin:-.1em",
'.typeset .bigop2': "font-family: AppleGothic; font-size: 175%; position:relative; top: .85em; margin:-.1em",
'.typeset .bigop2b': "font-family: Osaka; font-size: 200%; position: relative; top: .75em; margin:-.15em",
'.typeset .bigop2c': "font-family: AppleGothic; font-size: 300%; position:relative; top: .75em; margin:-.35em",
'.typeset .bigop2cx': "font-family: 'Apple Chancery'; font-size: 250%; position:relative; top: .7em; margin-left:-.1em; margin-right:-.2em",
'.typeset .delim1b': "font-family: Times; font-size: 150%; position:relative; top:.8em; margin:.01em",
'.typeset .delim2b': "font-family: Times; font-size: 210%; position:relative; top:.8em; margin:.01em",
'.typeset .delim3b': "font-family: Times; font-size: 300%; position:relative; top:.75em; margin:.01em",
'.typeset .delim4b': "font-family: Times; font-size: 400%; position:relative; top:.725em; margin:.01em"
});
/*
* replace \not and \joinrel with better dimensions
*/
jsMath.Macro('not','\\mathrel{\\rlap{\\kern 3mu/}}');
jsMath.Macro('joinrel','\\mathrel{\\kern-3mu}');

View File

@ -0,0 +1,200 @@
/*
* jsMath-fallback-mac-msie.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file makes changes needed by Internet Explorer on the Mac
* for when the TeX fonts are not available.
*
* ---------------------------------------------------------------------
*
* Copyright 2004-2006 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/********************************************************************
*
* Fix the default non-TeX-font characters to work with MSIE
*
*/
jsMath.Update.TeXfonts({
cmr10: {
'0': {c: 'G', tclass: 'greek'},
'1': {c: 'D', tclass: 'greek'},
'2': {c: 'Q', tclass: 'greek'},
'3': {c: 'L', tclass: 'greek'},
'4': {c: 'X', tclass: 'greek'},
'5': {c: 'P', tclass: 'greek'},
'6': {c: 'S', tclass: 'greek'},
'7': {c: '&#161;', tclass: 'greek'},
'8': {c: 'F', tclass: 'greek'},
'9': {c: 'Y', tclass: 'greek'},
'10': {c: 'W', tclass: 'greek'},
'22': {c: '<span style="position:relative; top:.1em">&#96;</span>', tclass: 'symbol3'}
},
cmti10: {
'0': {c: 'G', tclass: 'igreek'},
'1': {c: 'D', tclass: 'igreek'},
'2': {c: 'Q', tclass: 'igreek'},
'3': {c: 'L', tclass: 'igreek'},
'4': {c: 'X', tclass: 'igreek'},
'5': {c: 'P', tclass: 'igreek'},
'6': {c: 'S', tclass: 'igreek'},
'7': {c: '&#161;', tclass: 'igreek'},
'8': {c: 'F', tclass: 'igreek'},
'9': {c: 'Y', tclass: 'igreek'},
'10': {c: 'W', tclass: 'igreek'},
'22': {c: '<span style="position:relative; top:.1em">&#96;</span>', tclass: 'symbol3'}
},
cmbx10: {
'0': {c: 'G', tclass: 'bgreek'},
'1': {c: 'D', tclass: 'bgreek'},
'2': {c: 'Q', tclass: 'bgreek'},
'3': {c: 'L', tclass: 'bgreek'},
'4': {c: 'X', tclass: 'bgreek'},
'5': {c: 'P', tclass: 'bgreek'},
'6': {c: 'S', tclass: 'bgreek'},
'7': {c: '&#161;', tclass: 'bgreek'},
'8': {c: 'F', tclass: 'bgreek'},
'9': {c: 'Y', tclass: 'bgreek'},
'10': {c: 'W', tclass: 'bgreek'},
'22': {c: '<span style="position:relative; top:.1em">&#96;</span>', tclass: 'symbol3'}
},
cmmi10: {
'0': {c: 'G', tclass: 'igreek'},
'1': {c: 'D', tclass: 'igreek'},
'2': {c: 'Q', tclass: 'igreek'},
'3': {c: 'L', tclass: 'igreek'},
'4': {c: 'X', tclass: 'igreek'},
'5': {c: 'P', tclass: 'igreek'},
'6': {c: 'S', tclass: 'igreek'},
'7': {c: '&#161;', tclass: 'igreek'},
'8': {c: 'F', tclass: 'igreek'},
'9': {c: 'Y', tclass: 'igreek'},
'10': {c: 'W', tclass: 'igreek'},
'11': {c: 'a', tclass: 'greek'},
'12': {c: 'b', tclass: 'greek'},
'13': {c: 'g', tclass: 'greek'},
'14': {c: 'd', tclass: 'greek'},
'15': {c: 'e', tclass: 'greek'},
'16': {c: 'z', tclass: 'greek'},
'17': {c: 'h', tclass: 'greek'},
'18': {c: 'q', tclass: 'greek'},
'19': {c: 'i', tclass: 'greek'},
'20': {c: 'k', tclass: 'greek'},
'21': {c: 'l', tclass: 'greek'},
'22': {c: 'm', tclass: 'greek'},
'23': {c: 'n', tclass: 'greek'},
'24': {c: 'x', tclass: 'greek'},
'25': {c: 'p', tclass: 'greek'},
'26': {c: 'r', tclass: 'greek'},
'27': {c: 's', tclass: 'greek'},
'28': {c: 't', tclass: 'greek'},
'29': {c: 'u', tclass: 'greek'},
'30': {c: 'f', tclass: 'greek'},
'31': {c: 'c', tclass: 'greek'},
'32': {c: 'y', tclass: 'greek'},
'33': {c: 'w', tclass: 'greek'},
// '41': // leftharpoondown
// '43': // rightharpoondown
// '44': // hook left
// '45': // hook right
// '92': // natural
'94': {c: '<span style="position:relative; top:.3em">&#xFE36;</span>'},
'95': {c: '<span style="position:relative; top:-.2em">&#xFE35;</span>'}
// '127': // half-circle down accent?
},
cmsy10: {
'0': {c: '&ndash;', tclass: 'normal'},
'11': {c: '<span style="font-size: 70%">&#x25EF;</span><span style="position:relative; margin-left:-.5em; top:.1em; margin-right:.3em">/</span>', tclass: 'normal'},
'16': {c: '<span style="position:relative;top:-.1em; font-size: 67%">&#xFE35;</span><span style="position:relative;top:.1em;font-size:67%;margin-left:-1em">&#xFE36;</span>', tclass: 'normal'},
'48': {c: '<span style="font-size: 133%; margin-left:-.1em; margin-right: -.6em; position: relative; top:.4em">&#x2032;</span>'},
'93': {c: '&#x222A;<span style="font-size: 50%; margin-left:-1.3em; position: relative; top:-.3em; margin-right:.6em">+</span>'},
'96': {c: '<span style="font-size:67%; position:relative; top:-.3em;">|</span><span style="position:relative; top:-.15em; margin-left:-.1em">&ndash;</span>', tclass: 'normal'},
'104': {c: '<span style="position:relative; top:.2em; margin-left:-.6em">&#x3008;</span>'},
'105': {c: '<span style="position:relative; top:.2em; margin-right:-.6em">&#x3009;</span>'},
'109': {c: '&#x21D1;<span style="position:relative; top:.1em; margin-left:-1em">&#x21D3;</span>'},
'110': {c: '\\', d:0, tclass: 'normal'}
// '111': // wr
//, '113': // amalg
// '116': // sqcup
// '117': // sqcap
// '118': // sqsubseteq
// '119': // sqsupseteq
},
cmex10: {
'10': {c: '<span style="position:relative; top:.1em; margin-left:-.6em">&#x3008;</span>'},
'11': {c: '<span style="position:relative; top:.1em; margin-right:-.6em">&#x3009;</span>'},
'14': {c: '/'}, '15': {c: '\\'},
'28': {c: '<span style="position:relative; top:.05em; margin-left:-.6em">&#x3008;</span>'},
'29': {c: '<span style="position:relative; top:.05em; margin-right:-.6em">&#x3009;</span>'},
'30': {c: '/'}, '31': {c: '\\'},
'42': {c: '<span style="margin-left:-.6em">&#x3008;</span>'},
'43': {c: '<span style="margin-right:-.6em">&#x3009;</span>'},
'44': {c: '/'}, '45': {c: '\\'},
'46': {c: '/'}, '47': {c: '\\'},
'68': {c: '<span style="margin-left:-.6em">&#x3008;</span>'},
'69': {c: '<span style="margin-right:-.6em">&#x3009;</span>'},
// '70': // sqcup
// '71': // big sqcup
'72': {ic: 0}, '73': {ic: 0},
'82': {tclass: 'bigop1cx', ic: .15}, '90': {tclass: 'bigop2cx', ic:.6},
'85': {c: '&#x222A;<span style="font-size: 50%; margin-left:-1.25em; position: relative; top:-.3em; margin-right:.6em">+</span>'},
'93': {c: '&#x222A;<span style="font-size: 50%; margin-left:-1.25em; position: relative; top:-.3em; margin-right:.6em">+</span>'},
// '96': // coprod
// '97': // big coprod
'98': {c: '&#xFE3F;', h: 0.722, w: .58, tclass: 'wide1'},
'99': {c: '&#xFE3F;', h: 0.722, w: .58, tclass: 'wide2'},
'100': {c: '&#xFE3F;', h: 0.722, w: .58, tclass: 'wide3'},
'101': {c: '~', h: 0.722, w: .42, tclass: 'wide1a'},
'102': {c: '~', h: 0.8, w: .73, tclass: 'wide2a'},
'103': {c: '~', h: 0.8, w: 1.1, tclass: 'wide3a'}
}
});
jsMath.Setup.Styles({
'.typeset .arrow1': "font-family: Osaka; position: relative; top: .125em; margin: -1px",
'.typeset .arrow2': "font-family: Osaka; position: relative; top: .1em; margin:-1px",
'.typeset .bigop1': "font-family: Symbol; font-size: 110%; position:relative; top: .8em; margin:-.05em",
'.typeset .bigop1b': "font-family: Symbol; font-size: 140%; position: relative; top: .8em; margin:-.1em",
'.typeset .bigop1c': "font-family: Osaka; font-size: 125%; position:relative; top: .85em; margin:-.3em",
'.typeset .bigop1cx': "font-family: 'Apple Chancery'; font-size: 125%; position:relative; top: .7em; margin:-.1em",
'.typeset .bigop2': "font-family: Symbol; font-size: 175%; position:relative; top: .8em; margin:-.07em",
'.typeset .bigop2a': "font-family: Baskerville; font-size: 175%; position: relative; top: .65em",
'.typeset .bigop2b': "font-family: Symbol; font-size: 175%; position: relative; top: .8em; margin:-.07em",
'.typeset .bigop2c': "font-family: Osaka; font-size: 230%; position:relative; top: .85em; margin:-.35em",
'.typeset .bigop2cx': "font-family: 'Apple Chancery'; font-size: 250%; position:relative; top: .6em; margin-left:-.1em; margin-right:-.2em",
'.typeset .delim1b': "font-family: Times; font-size: 150%; position:relative; top:.8em",
'.typeset .delim2b': "font-family: Times; font-size: 210%; position:relative; top:.75em;",
'.typeset .delim3b': "font-family: Times; font-size: 300%; position:relative; top:.7em;",
'.typeset .delim4b': "font-family: Times; font-size: 400%; position:relative; top:.65em;",
'.typeset .symbol3': "font-family: Symbol",
'.typeset .wide1': "font-size: 50%; position: relative; top:-1.1em",
'.typeset .wide2': "font-size: 80%; position: relative; top:-.7em",
'.typeset .wide3': "font-size: 125%; position: relative; top:-.5em",
'.typeset .wide1a': "font-size: 75%; position: relative; top:-.5em",
'.typeset .wide2a': "font-size: 133%; position: relative; top: -.15em",
'.typeset .wide3a': "font-size: 200%; position: relative; top: -.05em",
'.typeset .greek': "font-family: Symbol",
'.typeset .igreek': "font-family: Symbol; font-style:italic",
'.typeset .bgreek': "font-family: Symbol; font-weight:bold"
});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,106 @@
<html>
<head>
<!--
| jsMath-global-controls.html
|
| Part of the jsMath package for mathematics on the web.
|
| This file by jsMath-global.html to open a small control panel
| at the top of the page. The panel shows the URL and allows the
| user to refresh the page, print it, and so on.
|
| ---------------------------------------------------------------------
|
| Copyright 2006 by Davide P. Cervone
|
| Licensed under the Apache License, Version 2.0 (the "License");
| you may not use this file except in compliance with the License.
| You may obtain a copy of the License at
|
| http://www.apache.org/licenses/LICENSE-2.0
|
| Unless required by applicable law or agreed to in writing, software
| distributed under the License is distributed on an "AS IS" BASIS,
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
| See the License for the specific language governing permissions and
| limitations under the License.
-->
<style>
body {border:0px; padding:0px; margin:0px}
div {padding:0px; background: #CCCCCC; border:1px outset}
table {border:0px; padding:0px; margin:0px; width:100%}
input {font-size:70%}
#url {margin-left:5px; padding:1px 0px 0px 2px}
#hide {margin-right:5px}
</style>
<script>
var jsMath;
if (window.location.search != '') {document.domain = window.location.search.substr(1)}
try {jsMath = parent.jsMath} catch (err) {}
</script>
</head>
<body>
<!----------------------------------->
<!--
| <script src="../../debug/console.js"></script>
| <script src="../../debug/show.js"></script>
-->
<!----------------------------------->
<div id="panel">
<table border="0">
<tr><td width="99%" nowrap>
<input type="text" style="width:75%" id="url">
<input type="button" value="Go" onclick="jsMath.SetURL()"></td>
<td width="1%" nowrap>
<!----------------------------------->
<!--<input type="button" value="Debug" onclick="debug()">-->
<!----------------------------------->
<input type="button" value="Print" id="print" onclick="jsMath.Print()">
<input type="button" value="Reload" id="reload" onclick="jsMath.Reload()">
<input type="button" value="Go Local" id="goLocal" onclick="jsMath.GoLocal()">
<input type="button" value="Empty" id="empty" onclick="jsMath.Empty()">
<input type="button" value="Hide" id="hide" onclick="setTimeout('jsMath.Hide()',10)"></small></td></tr>
</table>
</div>
<script>
if (jsMath) {
jsMath.url = document.getElementById("url");
jsMath.url.onkeypress = function (event) {
if (!event) {event = window.event}
var code = (event.which != null)? event.which:
(event.keyCode != null)? event.keyCode : event.charCode;
if (code == 13) {jsMath.SetURL(); return false}
return true;
};
if (jsMath.URL) {jsMath.url.value = jsMath.URL}
jsMath.print = document.getElementById("print");
jsMath.reload = document.getElementById("reload");
function Show() {
var div = document.all.panel;
var h = div.clientHeight + 2*div.clientTop;
if (h == 0 || h > 200 && attempts++ < 10)
{setTimeout("Show()",10*attempts); return}
parent.jsMath.SetControls(h+',*');
}
if (document.body.scrollHeight < 1) {
//
// MSIE/Mac doesn't get the right scrollHeight until the
// frame is fully renderred, which requires the frame
// to be visible, and there is no telling when the rendering
// is complete (it is AFTER the onload handler fires).
//
jsMath.print.disabled = true;
attempts = 0;
parent.document.body.rows = "50,*";
setTimeout("Show()",1);
} else {
parent.jsMath.SetControls(document.body.scrollHeight+',*');
}
}
</script>
</body>
</html>

View File

@ -0,0 +1,414 @@
<html>
<head>
<!--
| jsMath-global.html
|
| Part of the jsMath package for mathematics on the web.
|
| This file is used to store persistent data across multiple
| documents, for example, the cookie data when files are loaded
| locally, or cached typset math data.
|
| The file opens a frameset with one frame containing the
| actual document to view, and stores the global data in the
| outer document. That way, when the frame changes documents
| the global data is still available.
|
| ---------------------------------------------------------------------
|
| Copyright 2006 by Davide P. Cervone
|
| Licensed under the Apache License, Version 2.0 (the "License");
| you may not use this file except in compliance with the License.
| You may obtain a copy of the License at
|
| http://www.apache.org/licenses/LICENSE-2.0
|
| Unless required by applicable law or agreed to in writing, software
| distributed under the License is distributed on an "AS IS" BASIS,
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
| See the License for the specific language governing permissions and
| limitations under the License.
-->
<title>jsMath Global Frame</title>
<style></style>
<script>
var jsMath = {
isGlobal: 1, // to pervent FRAME from inheriting this jsMath
isOpera: (window.opera != null && window.Packages != null),
isSafari: (window.clientInformation && document.implementation.createCSSStyleSheet != null),
isMSIEmac: (screen.updateInterval != null && !window.SyntaxError && !window.print),
msieDelay: 1000, // MSIE/mac delay time for checking for offsite pages
/***************************************************************/
/*
* This will be shared with the jsMath in the frameset
*/
Global: {
isHidden: 0,
cookie: '',
cache: {T: {}, D: {}, R: {}, B: {}},
ClearCache: function () {jsMath.Global.cache = {T: {}, D: {}, R: {}, B: {}}},
Init: function () {}
},
/*
* Called by jsMath to attach to the Global data area.
*/
Register: function (w) {
w.jsMath.Global = jsMath.Global;
w.jsMath.Controls.localSetCookie = jsMath.localSetCookie;
w.jsMath.Controls.localGetCookie = jsMath.localGetCookie;
if (window.location.protocol != 'mk:') {
document.title = w.document.title;
this.ShowURL(w.location);
jsMath.SetUnload();
}
},
/***************************************************************/
/*
* Initialize the global data and load the contents of the frame
*/
Init: function () {
if (this.inited) return;
this.controls = document.getElementById('jsMath_controls');
this.frame = document.getElementById('jsMath_frame');
this.window = this.FrameWindow();
var URL;
if (!this.isOpera) {try {URL = this.window.document.URL} catch (err) {}}
if (!URL || URL == "about:blank" || URL.match(/jsMath-global.html$/))
{this.frame.src = this.src}
this.Global.frame = this.frame;
this.Global.Show = this.Show;
this.Global.GoLocal = this.GoLocal;
if (this.hide) {this.Hide()}
this.inited = 1;
},
GetURL: function () {
var src = unescape(document.location.search.substr(1));
if (src == '') {src = unescape(document.location.hash.substr(1))}
src = src.replace(/\?(.*)/,'');
if (RegExp.$1) {this.Global.cookie = unescape(RegExp.$1)}
return src;
},
FrameWindow: function (force) {
if (this.window && !force) {return this.window}
if (this.frame.contentWindow) {return this.frame.contentWindow}
if (document.frames && document.frames.jsMath_frame)
{return document.frames.jsMath_frame}
return null;
},
/*
* Called whenever the FRAME loads a new file.
* (Update the title, etc.)
*/
Loaded: function () {
if (!jsMath.inited) {jsMath.Init()}
if (!jsMath.window) {jsMath.window = jsMath.FrameWindow()}
if (!jsMath.window || window.location.protocol == 'mk:') return;
var URL; try {URL = jsMath.frame.src} catch (err) {}
var title; try {title = jsMath.window.document.title} catch (err) {}
if (URL != null && URL == jsMath.URL) return;
if (title != null) {
document.title = title;
jsMath.ShowURL(jsMath.window.location);
jsMath.SetUnload();
} else {
jsMath.Offsite();
}
},
/*
* Mark the page as offsite and can't be read
*/
Offsite: function () {
document.title = "jsMath Global: Offsite document -- can't read title";
jsMath.ShowURL("(Offsite document -- cant' read URL)");
if (jsMath.print && !jsMath.Global.isHidden) {
jsMath.print.disabled = true;
jsMath.reload.disabled = true;
}
jsMath.window = null;
},
//
// Safari doesn't fire onload for offsite URL's, so use in unload
// handler to look for these and mark them.
// MSIE/mac doesn't fire onload events at all, so use unload
// handler to simulate them.
//
SetUnload: function () {
if (jsMath.isMSIEmac || jsMath.isSafari) {
try {jsMath.oldUnload = jsMath.window.unload} catch (err) {}
try {jsMath.window.onunload = jsMath.Unload} catch (err) {}
}
},
Unload: function (event) {
if (jsMath.oldUnload) {jsMath.oldUnload(event)}
try {setTimeout('jsMath.StateChange(0)',1)} catch (err) {}
},
StateChange: function (i) {
jsMath.ShowURL(jsMath.window.location);
var state = 'unknown'; try {state = jsMath.window.document.readyState} catch (err) {};
if (state == 'unknown' || i++ == 20) {jsMath.Offsite(); return}
if (state != 'complete') {setTimeout('jsMath.StateChange('+i+')',50*i); return}
document.title = jsMath.window.document.title;
jsMath.ShowURL(jsMath.window.location);
if (window.location.host == jsMath.window.location.host)
{jsMath.SetUnload(); return}
if (jsMath.isMSIEmac) {
jsMath.oldLocation = jsMath.window.location;
setTimeout('jsMath.MSIEcheckDocument()',jsMath.msieDelay);
}
},
MSIEcheckDocument: function () {
if (window.location.host == jsMath.window.location.host) {
jsMath.StateChange(0)
} else {
if (jsMath.oldLocation != jsMath.window.location) {
jsMath.ShowURL(jsMath.window.location);
document.title = jsMath.window.document.title;
}
setTimeout('jsMath.MSIEcheckDocument()',jsMath.msieDelay);
}
},
/*
* Replacements for standard localSetCookie/localGetCookie that
* use the global cache for storing the cookie data rather than
* the document.location's search field.
*/
localSetCookie: function (cookie,warn) {
if (cookie != "") {cookie = 'jsMath='+cookie}
if (cookie == jsMath.Global.cookie) return;
jsMath.Global.cookie = cookie;
},
localGetCookie: function () {return (jsMath.Global.cookie || "")},
/*
* Set the URL in the controls window
*/
ShowURL: function (URL) {
try {
jsMath.URL = URL; if (jsMath.url) {jsMath.url.value = URL}
if (jsMath.print && !jsMath.Global.isHidden) {
jsMath.print.disabled = !window.print;
jsMath.reload.disabled = false;
}
} catch (err) {}
},
SetURL: function () {this.frame.src = jsMath.url.value},
/*
* Handle actions for the document frame
*/
Print: function () {if (this.window) {this.window.document.body.focus(); this.window.print()}},
Reload: function () {if (this.window) {this.window.location.reload()}},
GoLocal: function () {
if (jsMath.window) {
jsMath.UpdateCookie();
if (jsMath.isMSIEmac) {
alert("MSIE/Mac has a bug that causes it not to go local properly. "
+ "After you press OK below, your browser will appear to hang. "
+ "When this happens, press Command-. to cancel the action. "
+ "The window should clear and the page location will appear "
+ "in the address area at the top of the screen. Press the "
+ "REFRESH button to load the page correctly.");
}
jsMath.location = jsMath.window.location;
if (jsMath.window.location.protocol == 'file:' && jsMath.Global.cookie)
{jsMath.location += '?' + escape(jsMath.Global.cookie)}
setTimeout('window.location = jsMath.location',1);
return;
}
alert("You are viewing a web page from a site other than the "
+ "one where you loaded jsMath-Global, so jsMath can't read "
+ "its URL to load it locally.\n\n"
+ "Check to see if your browser has a contextual menu item to "
+ "open the active frame in a separate window.");
},
/*
* Read the cookie data, set the hiddenGlobal and global fields
* and save the cookie again.
*/
UpdateCookie: function () {
var cookie = []; var cookies = jsMath.window.document.cookie;
if (window.location.protocol == 'file:') {cookies = jsMath.Global.cookie}
if (cookies.match(/jsMath=([^;]+)/)) {
var data = RegExp.$1.split(/,/);
for (var i = 0; i < data.length; i++) {
var x = data[i].match(/(.*):(.*)/);
if (x[2].match(/^\d+$/)) {x[2] = 1*x[2]} // convert from string
cookie[x[1]] = x[2];
}
}
cookie.hiddenGlobal = jsMath.Global.isHidden;
cookie.global = "never"; cookies = [];
for (var id in cookie) {cookies[cookies.length] = id + ':' + cookie[id]}
cookies = cookies.join(',');
if (window.location.protocol == 'file:') {
jsMath.Global.cookie = 'jsMath='+cookies;
} else {
cookies += '; path=/';
if (cookie.keep && cookie.keep != '0D') {
var ms = {
D: 1000*60*60*24,
W: 1000*60*60*24*7,
M: 1000*60*60*24*30,
Y: 1000*60*60*24*365
};
var exp = new Date;
exp.setTime(exp.getTime() +
cookie.keep.substr(0,1) * ms[cookie.keep.substr(1,1)]);
cookies += '; expires=' + exp.toGMTString();
}
jsMath.window.document.cookie = 'jsMath='+cookies;
}
},
/*
* Check if the control panel should be hidden
*/
SetControls: function (rows) {
if (!jsMath.rows) {
jsMath.rows = rows;
var cookie = document.cookie;
if (String(window.location.protocol).match(/^(file|mk):$/))
{cookie = jsMath.Global.cookie}
if (cookie.match(/jsMath=([^;]+)/)) {cookie = RegExp.$1}
if (!cookie.match("hiddenGlobal:0")) {
if (this.inited) {setTimeout('jsMath.Hide()',1)} else {jsMath.hide = 1}
return;
}
}
document.body.rows = rows;
},
/*
* Remove the frame that holds the control panel
*/
Hide: function () {
if (jsMath.Global.isHidden) return;
if (this.isMSIEmac) {
//
// MSIE/Mac can't remove the frame, so hide it (and the drag bar)
//
document.body.rows = "-6,*";
} else if (this.isOpera) {
//
// Opera can remove it, but it is unstable for that, but
// setting the size to -1 seems to remove it as well.
//
document.body.rows = "-1,*";
} else {
document.body.removeChild(this.controls);
document.body.rows = "*";
jsMath.window = jsMath.FrameWindow(1);
}
this.Global.isHidden = 1;
},
/*
* Put back the control-panel frame
*/
Show: function (bubble) {
if (!jsMath.Global.isHidden) {
if (bubble && jsMath.window) {jsMath.window.jsMath.Controls.Panel()}
return;
}
if (!jsMath.isMSIEmac) {
document.body.insertBefore(jsMath.controls,jsMath.frame);
//
// Opera doesn't refresh the frames properly, so reload them
//
if (jsMath.isOpera) {
setTimeout(
'jsMath.controls.src = "about:blank";\n' +
'jsMath.controls.src = jsMath.root+"jsMath-global-controls.html"+jsMath.domain;\n' +
'jsMath.frame.src = jsMath.window.location;',1
);
}
}
document.body.rows = jsMath.rows;
jsMath.window = jsMath.FrameWindow(1);
jsMath.Global.isHidden = 0;
},
/*
* Empty the cache
*/
Empty: function () {
var OK = confirm('Really empty the equation cache?');
if (OK) {jsMath.Global.ClearCache()}
},
/*
* Find the largest common domain between the source file
* and the location of the jsMath files
*/
Domain: function () {
this.domain = '';
// MSIE/Mac can't do domain changes, so don't bother trying
if (navigator.appName == 'Microsoft Internet Explorer' &&
!navigator.platform.match(/Mac/) && navigator.userProfile != null) return;
if (this.src == '') {
if (window == parent) return;
var oldDomain = document.domain;
try {
while (true) {
try {if (parent.document.title != null) return} catch (err) {}
if (!document.domain.match(/\..*\./)) break;
document.domain = document.domain.replace(/^[^.]*\./,'');
}
} catch (err) {}
document.domain = oldDomain;
} else {
if (!this.src.match(new RegExp('^[^:]+:\/\/([^/]+)(:[0-9]+)?\/'))) return;
if (document.domain == RegExp.$1) return;
var src = RegExp.$1.split(/\./);
var loc = String(window.location.host).split(/\./);
var si, li; si = src.length-2; li = loc.length-2
while (si >= 0 && li >= 0 && src[si] == loc[li]) {li--; si--}
document.domain = src.slice(si+1).join('.');
this.domain = '?'+document.domain;
}
},
/*
* Create the document content based on whether this is the initial
* call to this file, or the secondary one
*/
Content: function () {
if (this.src != '') {
this.root = (!this.isOpera) ? '' :
String(window.location).replace(/\/jsMath-global.html\??.*/,'/');
document.writeln('<frameset rows="0,*" onload="jsMath.Init()">');
document.writeln('<frame src="'+this.root+'jsMath-global-controls.html'+this.domain+'" frameborder="0" scrolling="no" id="jsMath_controls" />');
document.writeln('<frame src="'+this.root+'jsMath-global.html" frameborder="0" onload="jsMath.Loaded()" id="jsMath_frame" />');
document.writeln('</frameset>');
} else {
document.writeln('<body><br/></body>');
}
}
};
</script>
</head>
<script>
jsMath.src = jsMath.GetURL();
jsMath.Domain();
jsMath.Content();
</script>
</html>

View File

@ -0,0 +1,39 @@
/*
* jsMath-loader-omniweb4.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file synchronizes the jsMath-loader.html file with
* the actual loading of the source javascript file.
* OmniWeb 4 has a serious bug where the loader file is run
* several times (and out of sequence), which plays havoc
* with the Start() and End() calls.
*
* ---------------------------------------------------------------------
*
* Copyright 2006 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
if (window.jsMath.Autoload) {
jsMath.Autoload.Script.endLoad();
} else {
if (!window.phase2) {
jsMath.Script.Start();
window.phase2 = 1;
} else {
jsMath.Script.End();
jsMath.Script.endLoad();
}
}

View File

@ -0,0 +1,78 @@
<html>
<head>
<!--
| jsMath-loader-post.html
|
| Part of the jsMath package for mathematics on the web.
|
| This file is used for loading jsMath components in Firefox3 when
| used in a file: url from a directory other than the one containing
| jsMath (gets around Firefox3's more restrictive same-origin policy.
|
| ---------------------------------------------------------------------
|
| Copyright 2008 by Davide P. Cervone
|
| Licensed under the Apache License, Version 2.0 (the "License");
| you may not use this file except in compliance with the License.
| You may obtain a copy of the License at
|
| http://www.apache.org/licenses/LICENSE-2.0
|
| Unless required by applicable law or agreed to in writing, software
| distributed under the License is distributed on an "AS IS" BASIS,
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
| See the License for the specific language governing permissions and
| limitations under the License.
-->
</head>
<body>
<script>
var isCheck = 0;
var url = location.search.substr(1); var ID = "jsMLD";
if (url.substr(0,9) == "autoload=") {url = url.substr(9); ID = "jsMAL"}
if (url == 'http://www.math.union.edu/locate/jsMath/jsMath/jsMath-version-check.js') {
//
// Handle version check separately
//
var jsMath = {Controls: {}}; isCheck = 1;
document.write('<script src="'+url+'"></'+'script>');
} else if (url != "" && url.match(/\.js$/) && !url.match('(^|[/\\?#=])[a-z]+://')) {
//
// Load the file and pass it to jsMath
//
var request = new XMLHttpRequest;
try {
request.open("GET",url,false);
request.send(null);
window.parent.postMessage(ID+":BGN:","*");
window.parent.postMessage(ID+":SCR:"+request.responseText,"*");
window.parent.postMessage(ID+":END:1","*");
} catch (err) {
window.parent.postMessage(ID+":ERR:Can't load "+url+": "+err.message,"*");
}
} else {
window.parent.postMessage(ID+":END:","*");
}
</script>
<script>
//
// If we are loading the version check, pass it to jsMath
// and run the check.
//
if (isCheck) {
var fn = jsMath.Controls.TestVersion.toString();
window.parent.postMessage(ID+":SCR:" +
"jsMath.Controls.TestVersion = "+fn+";" +
"jsMath.Message.Clear(); jsMath.Message.doClear();" +
"jsMath.Controls.TestVersion()","*"
);
window.parent.postMessage(ID+":END:","*");
}
</script>
</body>
</html>

View File

@ -0,0 +1,92 @@
<html>
<head>
<!--
| jsMath-loader.html
|
| Part of the jsMath package for mathematics on the web.
|
| This file is used for jsMath components when the browser doesn't
| handle the XmlHttpRequest function, or when they must be obtained
| from a server other than the one serving the page that is using jsMath.
|
| ---------------------------------------------------------------------
|
| Copyright 2004-2006 by Davide P. Cervone
|
| Licensed under the Apache License, Version 2.0 (the "License");
| you may not use this file except in compliance with the License.
| You may obtain a copy of the License at
|
| http://www.apache.org/licenses/LICENSE-2.0
|
| Unless required by applicable law or agreed to in writing, software
| distributed under the License is distributed on an "AS IS" BASIS,
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
| See the License for the specific language governing permissions and
| limitations under the License.
-->
</head>
<body>
<script>
var showWarning = 0;
while (!window.jsMath && !showWarning) {
try {
window.jsMath = window.parent.jsMath;
if (!window.jsMath) {throw "no jsMath";}
} catch (err) {
showWarning = 1; pageDomain = '';
try {pageDomain = document.domain} catch (err) {}
//
// MSIE on Mac can't change document.domain, and 'try' won't
// catch the error (Grrr!) so don't even attempt it.
//
if (pageDomain.match(/\..*\./) &&
(navigator.appName != 'Microsoft Internet Explorer' ||
!navigator.platform.match(/Mac/) || !navigator.userProfile || !document.all)) {
try {
document.domain = pageDomain.replace(/^[^.]*\./,'');
showWarning = 0;
} catch(err) {}
}
}
}
function Warning () {
alert(
"jsMath can't load one of its required components, because jsMath " +
"was not obtained from a server that is in the same domain as the " +
"page that loaded it."
);
}
isOmniWeb4 = (document.readyState == 'loading' &&
navigator.accentColorName != null &&
navigator.omniWebString == null);
if (showWarning) {setTimeout("Warning()",1)} else {
debug = window.parent.debug; show = window.parent.show;
jsMath.Script.window = window; url = jsMath.Script.url;
if (isOmniWeb4) {
if (url != jsMath.Script.prevURL) {
jsMath.Script.prevURL = url;
document.writeln('<script src="'+jsMath.root+'jsMath-loader-omniweb4.js"><'+'/script>');
document.writeln('<script src="'+url+'"><'+'/script>');
document.writeln('<script src="'+jsMath.root+'jsMath-loader-omniweb4.js"><'+'/script>');
}
} else {
jsMath.Script.Start();
document.writeln('<script src="'+url+'"><'+'/script>');
}
}
</script>
<script>
if (window.jsMath && !isOmniWeb4) {
jsMath.Script.End();
jsMath.Script.endLoad();
}
</script>
</body>
</html>

View File

@ -0,0 +1,53 @@
/*
* jsMath-msie-mac.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file makes changes needed for use with MSIE on the Mac.
*
* ---------------------------------------------------------------------
*
* Copyright 2004-2006 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* MSIE crashes if it changes the page too quickly, so we add a
* delay between processing math entries. Unfortunately, this really
* slows down math in MSIE on the mac.
*/
jsMath.Add(jsMath,{
msieProcess: jsMath.Process,
msieProcessBeforeShowing: jsMath.ProcessBeforeShowing,
Process: function () {
// we need to delay a bit before starting to process the page
// in order to avoid an MSIE display bug
jsMath.Message.Set("Processing Math: 0%");
setTimeout('jsMath.msieProcess()',jsMath.Browser.delay);
},
ProcessBeforeShowing: function () {
// we need to delay a bit before starting to process the page
// in order to avoid an MSIE display bug
setTimeout('jsMath.msieProcessBeforeShowing()',5*jsMath.Browser.delay);
}
});
jsMath.Browser.delay = 75; // hope this is enough of a delay!

View File

@ -0,0 +1,58 @@
/*
* jsMath-old-browsers.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file makes changes needed by older versions of some browsers
*
* ---------------------------------------------------------------------
*
* Copyright 2004-2006 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
jsMath.Add(jsMath.HTML,{
/*
* Use the blank GIF image for spacing and rules
*/
Blank: function (w,h,d,isRule) {
var style = '';
if (isRule) {
if (h*jsMath.em < 1.5) {h = '1px'} else {h = jsMath.HTML.Em(h)}
style = 'border-top:'+h+' solid;'; h = 0;
}
if (d == null) {d = 0}
style += 'width:'+this.Em(w)+'; height:'+this.Em(h+d)+';';
if (d) {style += 'vertical-align:'+this.Em(-d)}
return '<img src="'+jsMath.blank+'" style="'+style+'" />';
}
});
if (jsMath.browser == 'Konqueror') {
jsMath.Package(jsMath.Box,{Remeasured: function() {return this}});
jsMath.Add(jsMath.HTML,{
Spacer: function (w) {
if (w == 0) {return ''};
return '<span style="margin-left:'+this.Em(w-jsMath.Browser.spaceWidth)+'">'
+ '&nbsp;</span>';
}
});
jsMath.Browser.spaceWidth = this.EmBoxFor('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;').w/5;
}
jsMath.styles['.typeset .spacer'] = '';

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,17 @@
/*
* local/macros.js
*
* Use jsMath.Macro() to declare your own local macro definitions here,
* and add "local/macros.js" to the loadFiles array in easy/load.js so
* that they will be loaded automatically when jsMath is used.
*
* See http://www.math.union.edu/locate/jsMath/authors/macros.html
* for details on defining macros for jsMath.
*/
//
// Examples:
//
// jsMath.Macro('R','{\\bf R}');
// jsMath.Macro('red','\\color{red}{#1}',1);
//

View File

@ -0,0 +1,85 @@
/*
* CHMmode.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file makes jsMath work with MicroSoft's HTML Help system
* from within .chm files (compiled help archives).
*
* This file should be loaded BEFORE jsMath.js.
*
* ---------------------------------------------------------------------
*
* Copyright 2006-2007 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
if (!window.jsMath) {window.jsMath = {}}
if (!jsMath.Controls) {jsMath.Controls = {}}
if (!jsMath.Controls.cookie) {jsMath.Controls.cookie = {}}
jsMath.isCHMmode = 1;
jsMath.noChangeGlobal = 1;
jsMath.noShowGlobal = 1;
jsMath.noImgFonts = 1;
jsMath.Controls.cookie.global = 'always';
jsMath.Controls.cookie.hiddenGlobal = 1;
if (window.location.protocol == "mk:") {
/*
* Work around bug in hh.exe that causes it to run at 100% CPU
* and not exit if the page is reloaded after an IFRAME is used
* to load the controls file, so fake it using XMLHttpRequest.
* Load the data into a DIV instead of an IFRAME, and make sure
* that the styles are correct for it. Change the GetPanel()
* call to hide the other panel and open the correct one.
*/
jsMath.Controls.Init = function () {
this.controlPanels = jsMath.Setup.DIV("controlPanels");
if (!jsMath.Browser.msieButtonBug) {this.Button()}
else {setTimeout("jsMath.Controls.Button()",500)}
}
jsMath.Controls.Panel = function () {
jsMath.Translate.Cancel();
jsMath.Setup.AddStyleSheet({
'#jsMath_options': jsMath.styles['#jsMath_panel'],
'#jsMath_options .disabled': jsMath.styles['#jsMath_panel .disabled'],
'#jsMath_options .infoLink': jsMath.styles['#jsMath_panel .infoLink']
});
if (this.loaded) {this.panel = jsMath.Element("panel"); this.Main(); return}
var html = jsMath.Script.xmlRequest(jsMath.root+"jsMath-controls.html");
var body = (html.match(/<body>([\s\S]*)<\/body>/))[1];
this.controlPanels.innerHTML = body;
var script = (body.match(/<script>([\s\S]*?)<\/script>/))[1];
jsMath.window.eval(script);
jsMath.Controls.GetPanel = function (name) {
if (this.panel) {this.panel.style.display = "none"}
this.panel = jsMath.Element(name);
}
jsMath.Controls.oldClose = jsMath.Controls.Close;
jsMath.Controls.Close = function () {this.oldClose(); this.panel = null}
jsMath.Element("options").style.display = "none";
jsMath.Controls.Main();
if (!jsMath.Browser.IE7 || jsMath.Browser.quirks) {
jsMath.window.attachEvent("onscroll",jsMath.Controls.MoveButton);
if (jsMath.Browser.IE7) jsMath.window.attachEvent("onresize",jsMath.Controls.MoveButton);
}
}
}

View File

@ -0,0 +1,474 @@
/*
* autoload.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file is a plugin that checks if a page contains any math
* that must be processed by jsMath, and only loads jsMath.js
* when there is.
*
* You can control the items to look for via the variables
*
* jsMath.Autoload.findTeXstrings
* jsMath.Autoload.findLaTeXstrings
* jsMath.Autoload.findCustomStrings
* jsMath.Autoload.findCustomSettings
*
* which control whether to look for TeX strings that will be converted
* by jsMath.ConvertTeX(), or LaTeX strings that will be converted by
* jsMath.ConvertLaTeX(). By default, the first is true and the second
* and third are false. The findCustomStrings can be used to specify your
* own delimiters for in-line and display mathematics, e.g.
*
* jsMath.Autoload.findCustomStrings = [
* '[math],'[/math]', // start and end in-line math
* '[display]','[/display]' // start and end display math
* ];
*
* Finally, findCustomSettings can be set to an object reference whose
* name:value pairs control the individual search settings for tex2math.
* (See the plugins/tex2math.js file for more details).
*
* If any math strings are found, jsMath.js will be loaded automatically,
* but not loaded otherwise. If any of the last four are set and TeX math
* strings are found, then plugins/tex2ath.js will be loaded
* automatically. jsMath.Autoload.needsJsMath will be set to true or
* false depending on whether jsMath needed to be loaded.
*
* The value of jsMath.Autoload.checkElement controls the element to be
* searched by the autoload plug-in. If unset, the complete document will
* be searched. If set to a string, the element with that name will be
* searched. If set to a DOM object, that object and its children will
* be searched.
*
* Finally, there are two additional parameters that control files to
* be loaded after jsMath.js, should it be needed. These are
*
* jsMath.Autoload.loadFonts
* jsMath.Autoload.loadFiles
*
* If jsMath.js is loaded, the fonts contained in the loadFonts array
* will be loaded, and the JavaScript files listed in the loadFiles array
* will be run. Relative URL's are loaded based from the URL containing
* jsMath.js.
*
* The autoload plugin can be loaded in the document HEAD or in the BODY.
* If it is loaded in the HEAD, you will need to call jsMath.Autoload.Check()
* at the end of the BODY (say in the window.onload handler) in order to
* get it to check the page for math that needs to be tagged, otherwise load
* the file at the bottom of the BODY and it will run the check automatically.
*
* You can call jsMath.Autoload.Run() after the check has been performed
* in order to call the appropriate tex2math routines for the given Autoload
* settings. You can call jsMath.Autoload.Run() even when jsMath isn't loaded.
*
* ---------------------------------------------------------------------
*
* Copyright 2004-2006 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*************************************************************************/
/*
* Make sure jsMath.Autoload is available
*/
if (!window.jsMath) {window.jsMath = {}}
if (jsMath.Autoload == null) {jsMath.Autoload = {}}
jsMath.Add = function (dst,src) {for (var id in src) {dst[id] = src[id]}};
jsMath.document = document; // tex2math needs this
jsMath.Add(jsMath.Autoload,{
Script: {
request: null, // XMLHttpRequest object (if we can get it)
iframe: null, // the hidden iframe (if not)
operaXMLHttpRequestBug: (window.opera != null), // is Opera browser
/*
* Get XMLHttpRequest object, if possible, and look up the URL root
* (MSIE can't use xmlReuest to load local files, so avoid that)
*/
Init: function () {
this.Root();
if (window.XMLHttpRequest) {
try {this.request = new XMLHttpRequest} catch (err) {}
// MSIE and FireFox3 can't use xmlRequest on local files,
// but we don't have jsMath.browser yet to tell, so use this check
if (this.request && window.location.protocol == "file:") {
try {
this.request.open("GET",jsMath.Autoload.root+"plugins/autoload.js",false);
this.request.send(null);
} catch (err) {
this.request = null;
// Firefox3 has window.postMessage for inter-window communication.
// It can be used to handle the new file:// security model,
// so set up the listener.
if (window.postMessage && window.addEventListener) {
this.mustPost = 1;
window.addEventListener("message",jsMath.Autoload.Post.Listener,false);
}
}
}
}
if (!this.request && window.ActiveXObject && !this.mustPost) {
var xml = ["MSXML2.XMLHTTP.5.0","MSXML2.XMLHTTP.4.0","MSXML2.XMLHTTP.3.0",
"MSXML2.XMLHTTP","Microsoft.XMLHTTP"];
for (var i = 0; i < xml.length && !this.request; i++) {
try {this.request = new ActiveXObject(xml[i])} catch (err) {}
}
}
},
/*
* Load an external JavaScript file
*/
Load: function (url) {
if (this.request && !(this.operaXMLHttpRequestBug && url == 'jsMath.js')) {
setTimeout(function () {jsMath.Autoload.Script.xmlLoad(url)},1);
} else {
this.startLoad(url);
}
},
/*
* Load an external JavaScript file via XMLHttpRequest
*/
xmlLoad: function (url) {
try {
this.request.open("GET",jsMath.Autoload.root+url,false);
this.request.send(null);
} catch (err) {
throw Error("autoload: can't load the file '"+url+"'\n"
+ "Message: "+err.message);
}
if (this.request.status && this.request.status >= 400) {
throw Error("autoload: can't load the file '"+url+"'\n"
+ "Error status: "+this.request.status);
}
window.eval(this.request.responseText);
this.endLoad();
},
/*
* Load an external JavaScript file via jsMath-autoload.html
*/
startLoad: function (url) {
this.iframe = document.createElement('iframe');
this.iframe.style.visibility = 'hidden';
this.iframe.style.position = 'absolute';
this.iframe.style.width = '0px';
this.iframe.style.height = '0px';
if (document.body.firstChild) {
document.body.insertBefore(this.iframe,document.body.firstChild);
} else {
document.body.appendChild(this.iframe);
}
this.url = url; setTimeout('jsMath.Autoload.Script.setURL()',100);
},
endLoad: function () {setTimeout('jsMath.Autoload.Script.AfterLoad()',1)},
/*
* Use location.replace() to avoid browsers placing the file in
* the history (and messing up the BACK button action). Not
* completely effective in Firefox 1.0.x. Safari won't handle
* replace() if the document is local (not sure if that's really
* the issue, but that's the only time I see it).
*/
setURL: function () {
if (this.mustPost) {
this.iframe.src = jsMath.Autoload.Post.startLoad(this.url,this.iframe);
} else {
var url = jsMath.Autoload.root+"jsMath-autoload.html";
var doc = this.iframe.contentDocument;
if (!doc && this.iframe.contentWindow) {doc = this.iframe.contentWindow.document}
if (navigator.vendor == "Apple Computer, Inc." &&
document.location.protocol == 'file:') {doc = null}
if (doc) {doc.location.replace(url)} else {this.iframe.src = url}
}
},
/*
* Queue items that need to be postponed until jsMath has run
*/
queue: [],
Push: function (name,data) {this.queue[this.queue.length] = [name,data]},
RunStack: function () {
if (this.tex2math) {jsMath.Autoload.Check2(); return}
for (var i = 0; i < this.queue.length; i++) {
var name = this.queue[i][0];
var data = this.queue[i][1];
if (data.length == 1) {jsMath[name](data[0])}
else {jsMath[name](data[0],data[1],data[2],data[3])}
}
this.queue = [];
},
AfterLoad: function () {jsMath.Autoload.Script.RunStack()},
/*
* Look up the jsMath root directory, if it is not already supplied
*/
Root: function () {
if (jsMath.Autoload.root) return;
var script = document.getElementsByTagName('script');
if (script) {
for (var i = 0; i < script.length; i++) {
var src = script[i].src;
if (src && src.match('(^|/|\\\\)plugins/autoload.js$')) {
jsMath.Autoload.root = src.replace(/plugins\/autoload.js$/,'');
break;
}
}
}
}
},
/*
* Handle window.postMessage() events in Firefox3
*/
Post: {
window: null, // iframe we are ing to
Listener: function (event) {
if (event.source != jsMath.Autoload.Post.window) return;
var domain = event.origin.replace(/^file:\/\//,'');
var ddomain = document.domain.replace(/^file:\/\//,'');
if (domain == null || domain == "" || domain == "null") {domain = "localhost"}
if (ddomain == null || ddomain == "" || ddomain == "null") {ddomain = "localhost"}
if (domain != ddomain || event.data.substr(0,6) != "jsMAL:") return;
var type = event.data.substr(6,3).replace(/ /g,'');
var message = event.data.substr(10);
if (jsMath.Autoload.Post.Commands[type]) (jsMath.Autoload.Post.Commands[type])(message);
// cancel event?
},
/*
* Commands that can be performed by the listener
*/
Commands: {
SCR: function (message) {window.eval(message)},
ERR: function (message) {jsMath.Autoload.Script.endLoad()},
END: function (message) {jsMath.Autoload.Script.endLoad()}
},
startLoad: function (url,iframe) {
this.window = iframe.contentWindow;
return jsMath.Autoload.root+"jsMath-loader-post.html?autoload="+url;
},
endLoad: function () {
this.window = null;
}
},
/**************************************************************/
/*
* Load tex2math first (so we can call its search functions
* to look to see if anything needs to be turned into math)
* if it is needed, otherwise go on to the second check.
*/
Check: function () {
if (this.checked) return; this.checked = 1;
if ((this.findTeXstrings || this.findLaTeXstrings ||
this.findCustomStrings || this.findCustomSettings) &&
(!jsMath.tex2math || !jsMath.tex2math.loaded)) {
this.Script.tex2math = 1;
this.Script.Load('plugins/tex2math.js');
} else {
if (!jsMath.tex2math) {jsMath.tex2math = {}}
this.Check2();
}
},
ReCheck: function () {
if (jsMath.loaded) return;
this.InitStubs();
this.checked = 0;
this.Script.queue = [];
this.Check();
},
/*
* Once tex2math is loaded, use it to check for math that
* needs to be tagged for jsMath, and load jsMath if it is needed
*/
Check2: function () {
this.Script.tex2math = 0; this.needsJsMath = 0;
if (this.checkElement == null) {this.checkElement = null}
if (this.findTeXstrings) {jsMath.tex2math.ConvertTeX(this.checkElement)}
if (this.findLaTeXstrings) {jsMath.tex2math.ConvertLaTeX(this.checkElement)}
if (this.findCustomSettings) {jsMath.tex2math.Convert(this.checkElement,this.findCustomSettings)}
if (this.findCustomStrings) {
var s = this.findCustomStrings;
jsMath.tex2math.CustomSearch(s[0],s[1],s[2],s[3]);
jsMath.tex2math.ConvertCustom(this.checkElement);
}
this.needsJsMath = this.areMathElements(this.checkElement);
if (this.needsJsMath) {
this.LoadJsMath();
} else {
jsMath.Process = function () {};
jsMath.ProcessBeforeShowing = function () {};
jsMath.ProcessElement = function () {};
jsMath.ConvertTeX = function () {};
jsMath.ConvertTeX2 = function () {};
jsMath.ConvertLaTeX = function () {};
jsMath.ConvertCustom = function () {};
jsMath.CustomSearch = function () {};
jsMath.Macro = function () {};
jsMath.Synchronize = function (code,data) {
if (typeof(code) == 'string') {eval(code)} else {code(data)}
};
jsMath.Autoload.Script.RunStack(); // perform pending commands
jsMath.Autoload.setMessage();
}
},
/*
* A callback used in the tex2math searches to signal that
* some math has been found.
*/
tex2mathCallback: function () {
jsMath.Autoload.needsJsMath = 1;
return false;
},
/*
* jsMath.Autoload.Run() is now longer needed
*/
Run: function (data) {},
/*
* Look to see if there are SPAN or DIV elements of class "math".
*/
areMathElements: function (obj) {
if (!obj) {obj = document}
if (typeof(obj) == 'string') {obj = document.getElementById(obj)}
if (!obj.getElementsByTagName) {return false}
var math = obj.getElementsByTagName('div');
for (var k = 0; k < math.length; k++)
{if (math[k].className.match(/(^| )math( |$)/)) {return true}}
math = obj.getElementsByTagName('span');
for (var k = 0; k < math.length; k++)
{if (math[k].className.match(/(^| )math( |$)/)) {return true}}
return false;
},
/*
* When math tags are found, load the jsMath.js file,
* and afterward, load any auxiliary files or fonts,
* and then do any pending commands.
*/
LoadJsMath: function () {
if (this.loading) return;
if (jsMath.loaded) {this.afterLoad(); return}
if (this.root) {
this.loading = 1;
this.setMessage('Loading jsMath...');
this.Script.AfterLoad = this.afterLoad;
this.Script.Load('jsMath.js');
} else {
alert("Can't determine URL for jsMath.js");
}
},
afterLoad: function () {
jsMath.Autoload.loading = 0;
//
// Handle MSIE bug where jsMath.window both is and is not the actual window
//
if (jsMath.tex2math.window) {jsMath.tex2math.window.jsMath = jsMath}
if (jsMath.browser == 'MSIE') {window.onscroll = jsMath.window.onscroll};
var fonts = jsMath.Autoload.loadFonts;
if (fonts) {
if (typeof(fonts) != 'object') {fonts = [fonts]}
for (var i = 0; i < fonts.length; i++) {jsMath.Font.Load(fonts[i])}
}
var files = jsMath.Autoload.loadFiles;
if (files) {
if (typeof(files) != 'object') {files = [files]}
for (var i = 0; i < files.length; i++) {jsMath.Setup.Script(files[i])}
}
var macros = jsMath.Autoload.macros;
if (macros) {
for (var id in macros) {
if (typeof(macros[id]) == 'string') {
jsMath.Macro(id,macros[id]);
} else {
jsMath.Macro(id,macros[id][0],macros[id][1]);
}
}
}
jsMath.Synchronize(function () {jsMath.Autoload.Script.RunStack()});
jsMath.Autoload.setMessage();
},
/*
* Display a message in a small box at the bottom of the screen
*/
setMessage: function (message) {
if (message) {
this.div = document.createElement('div');
if (!document.body.hasChildNodes) {document.body.appendChild(this.div)}
else {document.body.insertBefore(this.div,document.body.firstChild)}
var style = {
position:'fixed', bottom:'1px', left:'2px',
backgroundColor:'#E6E6E6', border:'solid 1px #959595',
margin:'0px', padding:'1px 8px', zIndex:102,
color:'black', fontSize:'75%', width:'auto'
};
for (var id in style) {this.div.style[id] = style[id]}
this.div.id = "jsMath_message";
this.div.appendChild(jsMath.document.createTextNode(message));
} else if (this.div) {
this.div.firstChild.nodeValue = "";
this.div.style.visibility = 'hidden';
}
},
/*
* Queue these so we can do them after jsMath has been loaded
*/
stubs: {
Process: function (data) {jsMath.Autoload.Script.Push('Process',[data])},
ProcessBeforeShowing: function (data) {jsMath.Autoload.Script.Push('ProcessBeforeShowing',[data])},
ProcessElement: function (data) {jsMath.Autoload.Script.Push('ProcessElement',[data])},
ConvertTeX: function (data) {jsMath.Autoload.Script.Push('ConvertTeX',[data])},
ConvertTeX2: function (data) {jsMath.Autoload.Script.Push('ConvertTeX2',[data])},
ConvertLaTeX: function (data) {jsMath.Autoload.Script.Push('ConvertLaTeX',[data])},
ConvertCustom: function (data) {jsMath.Autoload.Script.Push('ConvertCustom',[data])},
CustomSearch: function (d1,d2,d3,d4) {jsMath.Autoload.Script.Push('CustomSearch',[d1,d2,d3,d4])},
Synchronize: function (data) {jsMath.Autoload.Script.Push('Synchronize',[data])},
Macro: function (cs,def,params) {jsMath.Autoload.Script.Push('Macro',[cs,def,params])}
},
InitStubs: function () {jsMath.Add(jsMath,jsMath.Autoload.stubs)}
});
/*
* Initialize
*/
if (jsMath.Autoload.findTeXstrings == null) {jsMath.Autoload.findTeXstrings = 0}
if (jsMath.Autoload.findLaTeXstrings == null) {jsMath.Autoload.findLaTeXstrings = 0}
jsMath.Autoload.Script.Init();
jsMath.Autoload.InitStubs();
if (document.body && !jsMath.Autoload.delayCheck) {jsMath.Autoload.Check()}

View File

@ -0,0 +1,52 @@
/*
* plugins/global.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file call up the global frame, if it is not already in place.
*
* This should be called BEFORE loading jsMath.js
*
* ---------------------------------------------------------------------
*
* Copyright 2006 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
if (!parent.jsMath || !parent.jsMath.isGlobal) {
var cookie = []; var cookies = document.cookies;
if (window.location.protocol == 'file:') {cookies = unescape(window.location.search.substr(1))}
else if (window.location.protocol == 'mk:') {cookies = unescape(window.location.hash.substr(1))}
if (cookies.match(/jsMath=([^;]+)/)) {
var data = RegExp.$1.split(/,/);
for (var i = 0; i < data.length; i++) {
var x = data[i].match(/(.*):(.*)/);
cookie[x[1]] = x[2];
}
}
if (cookie.global != "never" && !navigator.accentColorName) {
var script = document.getElementsByTagName('script');
if (script) {
for (var i = 0; i < script.length; i++) {
src = script[i].src;
if (src && src.match('(^|/)plugins/global.js$')) {
src = src.replace(/plugins\/global.js$/,'jsMath-global.html');
var sep = (window.location.protocol == 'mk:') ? '#' : '?';
window.location.replace(src + sep + escape(window.location));
break;
}
}
}
}
}

View File

@ -0,0 +1,221 @@
/*
* mimeTeX.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file makes jsMath more compatible with the mimeTeX program.
* It does not make everything work, but it goes a long way.
*
* ---------------------------------------------------------------------
*
* Copyright 2004-2006 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Treat ~ as space
*/
jsMath.Parser.prototype.nextIsSpace = function () {
return this.string.charAt(this.i) == ' ' ||
this.string.charAt(this.i) == '~';
}
jsMath.Parser.prototype.special['~'] = 'Space';
/*
* Implement \[ ... \], \( ... \), etc.
*/
jsMath.Macro('[','\\left['); jsMath.Macro(']','\\right]');
jsMath.Macro('(','\\left('); jsMath.Macro(')','\\right)');
jsMath.Macro('<','\\left<'); jsMath.Macro('>','\\right>');
// can't do \. in a reasonable way
jsMath.Parser.prototype.macros['|'] = ['HandleLR','|','|'];
jsMath.Parser.prototype.macros['='] = ['HandleLR','\\|','\\|'];
/*
* Make non-standard \left{ and \right} work
*/
jsMath.Parser.prototype.delimiter['}'] = [5,2,0x67,3,0x09];
jsMath.Parser.prototype.delimiter['{'] = [4,2,0x66,3,0x08];
/*
* Immitate mimeTeX \big... and \Big... ops
*/
// make the normal ones in text mode
jsMath.Macro('int','\\intop\\nolimits');
jsMath.Macro('oint','\\ointop\\nolimits');
jsMath.Macro('sum','\\sumop\\nolimits');
jsMath.Macro('prod','\\prodop\\nolimits');
jsMath.Macro('coprod','\\coprodop\\nolimits');
jsMath.Macro('bigint','\\bigintop\\nolimits');
jsMath.Macro('bigoint','\\bigointop\\nolimits');
jsMath.Macro('bigsum','\\bigsumop\\nolimits');
jsMath.Macro('bigprod','\\bigprodop\\nolimits');
jsMath.Macro('bigcoprod','\\bigcoprodop\\nolimits');
jsMath.Macro('Bigint','\\bigintop\\limits');
jsMath.Macro('Bigoint','\\bigointop\\limits');
jsMath.Macro('Bigsum','\\bigsumop\\limits');
jsMath.Macro('Bigprod','\\bigprodop\\limits');
jsMath.Macro('Bigcoprod','\\bigcoprod\\limits');
/*
* The characters needed for the macros above
*/
jsMath.Parser.prototype.mathchardef['coprodop'] = [1,3,0x60];
jsMath.Parser.prototype.mathchardef['prodop'] = [1,3,0x51];
jsMath.Parser.prototype.mathchardef['sumop'] = [1,3,0x50];
jsMath.Parser.prototype.mathchardef['bigintop'] = [1,3,0x5A];
jsMath.Parser.prototype.mathchardef['bigointop'] = [1,3,0x49];
jsMath.Parser.prototype.mathchardef['bigcoprodop'] = [1,3,0x61];
jsMath.Parser.prototype.mathchardef['bigprodop'] = [1,3,0x59];
jsMath.Parser.prototype.mathchardef['bigsumop'] = [1,3,0x58];
/*
* Unlink the small versions so they don't enlarge in display mode
*/
jsMath.TeX['cmex10'][0x48].n = null;
jsMath.TeX['cmex10'][0x50].n = null;
jsMath.TeX['cmex10'][0x51].n = null;
jsMath.TeX['cmex10'][0x52].n = null;
jsMath.TeX['cmex10'][0x60].n = null;
/*
* Some other missing items
*/
jsMath.Macro('/','{}'); // insert an empty box \/
jsMath.Macro('raisebox','\\raise #1px ',1); // convert to \raise
jsMath.Macro('hfill','\\quad ',1); // punt
jsMath.Macro('fbox','\\oldfbox{$#1$}',1); // do fbox in math mode
/*
* These get new JavaScript routines
*/
jsMath.Parser.prototype.macros['unitlength'] = 'unitlength';
jsMath.Parser.prototype.macros['hspace'] = 'hspace';
jsMath.Parser.prototype.macros['fs'] = 'fs';
jsMath.Parser.prototype.macros['oldfbox'] = 'FBox';
/*
* Add some JavaScript functions to the parser
*/
jsMath.Package(jsMath.Parser,{
/*
* Implement \left x ... \right x
*/
HandleLR: function (name,data) {
var arg = this.GetUpto(name,name); if (this.error) return;
this.string = '\\left'+data[0]+arg+'\\right'+data[1];
this.i = 0;
},
/*
* Hold the unit length in mlist.data
*/
unitlength: function (name) {
var n = this.GetArgument(this.cmd+name); if (this.error) return;
if (!n.match(/^-?(\d+(\.\d*)?|\.\d+)$/)) {
this.Error("Argument for "+this.cmd+name+" must be a number");
return;
}
this.mlist.data['unitlength'] = n;
},
/*
* Get the length (converted to ems) and multiply by the unit length
*/
hspace: function (name) {
var w = this.GetArgument(this.cmd+name); if (this.error) return;
if (!w.match(/^-?(\d+(\.\d*)?|\.\d+)$/)) {
this.Error("Argument for "+this.cmd+name+" must be a number");
return;
}
w /= jsMath.em
if (this.mlist.data['unitlength']) {w *= this.mlist.data['unitlength']}
this.mlist.Add(jsMath.mItem.Space(w));
},
/*
* Implement \fs{...} for font-size changing
*/
fs: function (name) {
var n = this.GetArgument(this.cmd+name); if (this.error) return;
if (!n.match(/^[-+]?\d+$/)) {
this.Error("Argument for "+this.cmd+name+" must be an integer");
return;
}
if (n.match(/[-+]/)) {n = n - 0; n += this.mlist.data.size}
this.mlist.data.size = n = Math.max(0,Math.min(9,n));
this.mlist.Add(new jsMath.mItem('size',{size: n}));
},
/*
* Repalce the Array function by one that accepts an optional
* parameter for the column types, and that handle's mimeTeX's
* "preamble" format.
*/
Array: function (name,delim) {
var columns = delim[2]; var cspacing = delim[3];
if (!columns && this.GetNext() == '{') {
columns = this.GetArgument(this.cmd+'begin{'+name+'}');
if (this.error) return;
} else {
columns = '';
}
columns = columns.replace(/[^clr]/g,'');
columns = columns.split('');
var data = this.mlist.data; var style = delim[5] || 'T';
var arg = this.GetEnd(name); if (this.error) return;
if (arg.match(/\$/)) {arg = arg.replace(/^([^$]*)\$/,''); columns = RegExp.$1}
var parse = new jsMath.Parser(arg+this.cmd+'\\',null,data.size,style);
parse.matrix = name; parse.row = []; parse.table = []; parse.rspacing = [];
parse.Parse(); if (parse.error) {this.Error(parse); return}
parse.HandleRow(name,1); // be sure the last row is recorded
var box = jsMath.Box.Layout(data.size,parse.table,columns,cspacing,parse.rspacing,delim[4]||null);
// Add parentheses, if needed
if (delim[0] && delim[1]) {
var left = jsMath.Box.Delimiter(box.h+box.d-jsMath.hd/4,this.delimiter[delim[0]],'T');
var right = jsMath.Box.Delimiter(box.h+box.d-jsMath.hd/4,this.delimiter[delim[1]],'T');
box = jsMath.Box.SetList([left,box,right],data.style,data.size);
}
this.mlist.Add(jsMath.mItem.Atom((delim[0]? 'inner': 'ord'),box));
},
/*
* Similarly for Matrix (used by \matrix and \array)
*/
Matrix: function (name,delim) {
var data = this.mlist.data;
var arg = this.GetArgument(this.cmd+name); if (this.error) return;
if (arg.match(/\$/)) {arg = arg.replace(/^([^$]*)\$/,''); delim[2] = RegExp.$1}
var parse = new jsMath.Parser(arg+this.cmd+'\\',null,data.size,delim[5] || 'T');
parse.matrix = name; parse.row = []; parse.table = []; parse.rspacing = [];
parse.Parse(); if (parse.error) {this.Error(parse); return}
parse.HandleRow(name,1); // be sure the last row is recorded
var box = jsMath.Box.Layout(data.size,parse.table,delim[2]||null,delim[3]||null,parse.rspacing,delim[4]||null);
// Add parentheses, if needed
if (delim[0] && delim[1]) {
var left = jsMath.Box.Delimiter(box.h+box.d-jsMath.hd/4,this.delimiter[delim[0]],'T');
var right = jsMath.Box.Delimiter(box.h+box.d-jsMath.hd/4,this.delimiter[delim[1]],'T');
box = jsMath.Box.SetList([left,box,right],data.style,data.size);
}
this.mlist.Add(jsMath.mItem.Atom((delim[0]? 'inner': 'ord'),box));
}
});

View File

@ -0,0 +1,71 @@
/*
* noCache.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file disables the equation cache that jsMath uses to
* store the typeset versions of TeX code so that common expressions
* won't need to be re-typeset.
*
* ---------------------------------------------------------------------
*
* Copyright 2006 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
jsMath.Add(jsMath,{
/*
* Get the width and height (in ems) of an HTML string
*/
EmBoxFor: function (s) {
var bbox = this.BBoxFor(s);
return {w: bbox.w/this.em, h: bbox.h/this.em};
},
/*
* For browsers that don't handle sizes of italics properly (MSIE)
*/
EmBoxForItalics: function (s) {
var bbox = this.BBoxFor(s);
if (s.match(/<i>|class=\"(icm|italic|igreek|iaccent)/i)) {
bbox.w = this.BBoxFor(s+jsMath.Browser.italicString).w
- jsMath.Browser.italicCorrection;
}
return {w: bbox.w/this.em, h: bbox.h/this.em};
}
});
jsMath.Add(jsMath.Translate,{
/*
* Typeset a string in \textstyle and return the HTML for it
*/
TextMode: function (s) {
var parse = jsMath.Parse(s,null,null,'T');
parse.Atomize();
return parse.Typeset();
},
/*
* Typeset a string in \displaystyle and return the HTML for it
*/
DisplayMode: function (s) {
var parse = jsMath.Parse(s,null,null,'D');
parse.Atomize();
return parse.Typeset();
}
});

View File

@ -0,0 +1,33 @@
/*
* noGlobal.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file disables the Go Global button. It should be loaded
* BEFORE jsMath.js.
*
* ---------------------------------------------------------------------
*
* Copyright 2006 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
if (!window.jsMath) {window.jsMath = {}}
if (!jsMath.Controls) {jsMath.Controls = {}}
if (!jsMath.Controls.cookie) {jsMath.Controls.cookie = {}}
jsMath.noGoGlobal = 1;
jsMath.noChangeGlobal = 1;
jsMath.noShowGlobal = 1;
jsMath.Controls.cookie.global = 'never';

View File

@ -0,0 +1,35 @@
/*
* noImageFonts.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file indicates that no image fonts are available.
* It should be loaded BEFORE jsMath.js is loaded.
*
* ---------------------------------------------------------------------
*
* Copyright 2004-2006 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
if (!window.jsMath) {window.jsMath = {}}
jsMath.noImgFonts = 1;
if (!jsMath.Font) {jsMath.Font = {}}
if (!jsMath.Font.extra_message) {
jsMath.Font.extra_message =
'Extra TeX fonts not found: <b><span id="jsMath_ExtraFonts"></span></b><br/>'
+ 'Using unicode fonts instead. This may be slow and might not print well.<br/>\n'
+ 'Use the jsMath control panel to get additional information.';
}

View File

@ -0,0 +1,70 @@
/*
* smallFonts.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file changes the sizes of fonts used in subscripts so that they
* are larger. This can be helpful if jsMath is used on a page with a
* small font size, where the subscripts may tend to disappear.
* It should be loaded BEFORE jsMath.js.
*
* ---------------------------------------------------------------------
*
* Copyright 2006 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
if (!window.jsMath) {window.jsMath = {}}
if (!jsMath.styles) {jsMath.styles = {}}
if (!jsMath.Img) {jsMath.Img = {}}
if (!jsMath.Box) {jsMath.Box = {}}
if (!jsMath.Typeset) {jsMath.Typeset = {}}
/*
* Replace the smaller font sizes
*/
jsMath.sizes = [70, 77, 85, 92, 100, 120, 144, 173, 207, 249];
jsMath.Img.fonts = [70, 70, 85, 85, 100, 120, 144, 173, 207, 249, 298, 358, 430];
jsMath.styles['.typeset .size0']['font-size'] = '70%';
jsMath.styles['.typeset .size1']['font-size'] = '77%';
jsMath.styles['.typeset .size2']['font-size'] = '85%';
jsMath.styles['.typeset .size3']['font-size'] = '92%';
/*
* Fix multiplication factors in these routines
*/
jsMath.Typeset.StyleValue = function (style,v) {
if (style == "S" || style == "S'") {return .85*v}
if (style == "SS" || style == "SS'") {return .70*v}
return v;
};
jsMath.Box.DelimBestFit = function (H,c,font,style) {
if (c == 0 && font == 0) return null;
var C; var h; font = jsMath.TeX.fam[font];
var isSS = (style.charAt(1) == 'S');
var isS = (style.charAt(0) == 'S');
while (c != null) {
C = jsMath.TeX[font][c];
if (C.h == null) {C.h = jsMath.Box.defaultH}; if (C.d == null) {C.d = 0}
h = C.h+C.d;
if (C.delim) {return [c,font,'',H]}
if (isSS && .70*h >= H) {return [c,font,'SS',.7*h]}
if (isS && .85*h >= H) {return [c,font,'S',.85*h]}
if (h >= H || C.n == null) {return [c,font,'T',h]}
c = C.n;
}
return null;
};

View File

@ -0,0 +1,372 @@
/*
* plugins/spriteImageFonts.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file makes jsMath use single files for the image fonts
* rather than individual images for each character.
*
* ---------------------------------------------------------------------
*
* Copyright 2006 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
if (!window.jsMath) {window.jsMath = {}}
jsMath.spriteImageFonts = {version: "1.1"};
if (!jsMath.styles) {jsMath.styles = []}
jsMath.styles['.typeset .img'] = {
position: 'relative',
display: 'inline-block',
overflow: 'hidden',
'background-repeat': 'no-repeat'
};
jsMath.styles['.typeset .img .xy'] = {
position: 'relative',
left: '0px', top: '0px'
};
// for Mozilla
jsMath.styles['.typeset .mimg'] = {position: 'relative'};
jsMath.styles['.typeset .mimg .size'] = {display: '-moz-inline-box'};
jsMath.styles['.typeset .mimg .wh'] = {
position: 'absolute',
left: '0px', top: '0px',
overflow: 'hidden'
};
jsMath.styles['.typeset .mimg .xy'] = {
position: 'relative',
left: '0px', top: '0px'
};
// for MSIE
jsMath.styles['.typeset .mimg .h'] = {
position: 'relative',
display: 'inline-block',
width: '0px'
};
/*
* Replace the TeXIMG function with one that uses the sprite fonts
*/
if (!jsMath.Box) {jsMath.Box = {}}
jsMath.Box.TeXIMG = function (font,C,size) {
var c = jsMath.TeX[font][C];
if (c.img.reload && jsMath.Img[c.img.reload][font].loaded == 1)
{delete c.img.reload; c.img.size = null}
if (c.img.size != null && c.img.size == size &&
c.img.best != null && c.img.best == jsMath.Img.best) return;
var mustScale = (jsMath.Img.scale != 1);
var id = jsMath.Img.best + size - 4;
if (id < 0) {id = 0; mustScale = 1} else
if (id >= jsMath.Img.fonts.length) {id = jsMath.Img.fonts.length-1; mustScale = 1}
var imgFont = jsMath.Img[jsMath.Img.fonts[id]][font];
if (!imgFont.loaded && jsMath.Browser.waitForImages) {
// store information so several fonts can be loaded at once
jsMath.Img.mustLoad[jsMath.Img.mustLoad.length] = [font,jsMath.Img.fonts[id]];
imgFont.loaded = -1;
}
var img = imgFont[C];
var scale = 1/jsMath.Img.w[jsMath.Img.fonts[id]];
if (id != jsMath.Img.best + size - 4) {
if (c.w != null) {scale = c.w/img[0]} else {
scale *= jsMath.Img.fonts[size]/jsMath.Img.fonts[4]
* jsMath.Img.fonts[jsMath.Img.best]/jsMath.Img.fonts[id];
}
}
// get the metrics for the character glyph
var bScale = jsMath.Browser.imgScale;
if (img[3] == null) {img[3] = 0}
var w = (img[0]-img[3])*scale; var h = img[1]*scale; var d = -img[2]*scale;
var x = img[3]-imgFont.x[C%16]; var y = img[1]-img[2]-imgFont.y[Math.floor(C/16)];
var wh; var xy; var v;
var ladjust = ""; var resize = ""; var vadjust; var wadjust;
if ((mustScale || jsMath.Controls.cookie.scaleImg) && !jsMath.Browser.operaImageFonts) {
w += 2/jsMath.em; h += 2/jsMath.em; d -= 1/jsMath.em; y += 1; x += 1; // try to adjust for rounding errors
resize = "width:"+jsMath.HTML.Em(imgFont.wh[0]*scale*bScale)+";";
wh = "width:"+jsMath.HTML.Em(w*bScale)+";height:"+jsMath.HTML.Em(h*bScale)+";";
xy = "left:"+jsMath.HTML.Em(x*scale*bScale)+";top:"+jsMath.HTML.Em(y*scale*bScale)+";";
vadjust = "vertical-align:"+jsMath.HTML.Em(d*bScale)+";";
v = jsMath.HTML.Em(h+d);
if (img[3]) {ladjust = "margin-left:"+jsMath.HTML.Em(-img[3]*scale*bScale)+";"}
} else {
if (jsMath.Browser.msieAlphaBug && jsMath.Controls.cookie.alpha) {
resize = "height:"+(imgFont.wh[1]*jsMath.Browser.imgScale)+"px;"
+ "width:"+(imgFont.wh[0]*jsMath.Browser.imgScale)+"px;";
}
wh = "width:"+img[0]+"px; height:"+img[1]+"px;";
xy = "left:"+x+"px; top:"+y+"px;";
vadjust = "vertical-align:"+(-img[2])+"px;"; v = (img[1]-img[2])+"px";
if (img[3]) {ladjust = "margin-left:"+(-img[3])+"px;"}
}
wadjust = (c.w == null || Math.abs(c.w-w) < .01)? "" : " margin-right:"+jsMath.HTML.Em(c.w-w)+';';
if (img[2] == 0 || jsMath.Browser.valignBug) {vadjust = ""}
// get the image
var URL = jsMath.Img.URL(font,jsMath.Img.fonts[id],C); var IMG;
if (jsMath.Browser.msieAlphaBug && jsMath.Controls.cookie.alpha) {
IMG = '<span class="xy" style="'+xy+'">'
+ '<img src="'+jsMath.blank+'" style="' + resize
+ 'filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='
+ "'" + URL + "', sizingMethod='scale'" + ');" />'
+ '</span>';
} else {
IMG = '<img src="'+URL+'" class="xy" style="'+xy+resize+'" />';
}
if (imgFont.loaded == -1) {IMG = ""; c.img.reload = jsMath.Img.fonts[id]}
// get the HTML for cropping the image
c.c = this.IMG(IMG,wh,vadjust,wadjust,ladjust,v,x,y,URL);
c.tclass = "normal";
c.img.bh = h+d; c.img.bd = -d;
c.img.size = size; c.img.best = jsMath.Img.best;
};
/*
* Default uses inline-box containing an image
*/
jsMath.Box.IMG = function (IMG,wh,vadjust,wadjust,ladjust,v,x,y,URL) {
return '<span class="img" style="'+wh+vadjust+wadjust+ladjust+'">'
+ IMG + '</span>' + jsMath.Browser.msieImgFontBBoxFix;
};
/*
* Opera bug in inline-block alignment forces use of background image
*/
jsMath.Box.IMG_opera = function (IMG,wh,vadjust,wadjust,ladjust,v,x,y,URL) {
var html = '<span class="img" style="background-image: url('+URL+');'
+ wh + vadjust + 'background-position: '+x+'px '+y+'px"></span>';
if (wadjust || ladjust)
{html = '<span style="'+wadjust+ladjust+'">' + html + '</span>'}
return html;
};
/*
* Mozilla's -moz-inline-box has top aligned with baseline, so adjust
*/
jsMath.Box.IMG_mozilla = function (IMG,wh,vadjust,wadjust,ladjust,v,x,y,URL) {
vadjust = "vertical-align:"+v+";";
var html = '<span class="mimg" style="'+vadjust+'">'
+ '<span class="size" style="'+wh+'"></span>'
+ '<span class="wh" style="'+wh+'">' + IMG + '</span>'
+ '</span>';
if (wadjust || ladjust)
{html = '<span style="'+wadjust+ladjust+'">' + html + '</span>'}
return html;
};
/*
* MSIE screws up vadjust on inline-box elements, so use absolute
* positioning and an extra span to set the width and height
*/
jsMath.Box.IMG_msie = function (IMG,wh,vadjust,wadjust,ladjust,v,x,y,URL) {
var html = '<span class="mimg">'
+ '<span class="h" style="height:'+v+'">'
+ '<span class="wh" style="'+wh+'">' + IMG + '</span>'
+ '</span>'
+ '<span class="img" style="'+wh+vadjust+'"></span>'
+ '</span>';
if (wadjust || ladjust) {
html = jsMath.Browser.msieSpaceFix
+ '<span style="'+wadjust+ladjust+'">' + html + '</span>';
}
return html;
};
if (!jsMath.Img) {jsMath.Img = {}}
/*
* Called by the extra-font definition files to add an image font
* into the mix (save offset data and image size)
*/
jsMath.Img.AddFont = function (size,def) {
if (!jsMath.Img[size]) {jsMath.Img[size] = {}};
for (var font in def) {
def[font].x = def[font][128]; def[font].y = def[font][129];
def[font].wh = def[font][130];
delete def[font][128]; delete def[font][129]; delete def[font][130];
}
jsMath.Add(jsMath.Img[size],def);
};
/*
* Get URL to directory for given font and size, based on the
* user's alpha/plain setting
*/
jsMath.Img.URL = function (name,size) {
if (size == null) {return this.root+name+'/font.js'}
var type = (jsMath.Controls.cookie.alpha) ? '/alpha/': '/plain/';
return this.root+name+type+size+'.png';
};
/*
* Laod the data for an image font
*/
jsMath.Img.LoadFont = function (name) {
if (jsMath.browser == 'OmniWeb' && !jsMath.Browser.hasInlineBlock) {
jsMath.noImgFonts = 1;
jsMath.Font.Check();
return;
}
if (!this.loaded) this.Init();
jsMath.Setup.Script(this.URL(name));
};
/*
* Setup for print mode
*/
jsMath.Img.Init = function () {
if ((jsMath.Controls.cookie.print || jsMath.Controls.cookie.stayhires) && !jsMath.Browser.operaImgFonts) {
jsMath.Controls.cookie.print = jsMath.Controls.cookie.stayhires;
this.factor *= 3;
if (!jsMath.Controls.isLocalCookie || !jsMath.Global.isLocal) {jsMath.Controls.SetCookie(0)}
if (jsMath.Browser.alphaPrintBug) {jsMath.Controls.cookie.alpha = 0}
}
this.loaded = 1;
jsMath.Img.root = jsMath.root + "fonts-sprite/";
jsMath.version += "-sp" + jsMath.spriteImageFonts.version;
};
if (!jsMath.Browser) {jsMath.Browser = {}}
/*
* Hook into initialization routine
*/
jsMath.Browser.Init = function () {
jsMath.browser = 'unknown';
this.TestInlineBlock();
this.TestSpanHeight();
this.TestRenameOK();
this.TestStyleChange();
this.MSIE();
this.Mozilla();
this.Opera();
this.OmniWeb();
this.Safari();
this.Konqueror();
this.ImgFontInit();
//
// Change some routines depending on the browser
//
if (this.allowAbsoluteDelim) {
jsMath.Box.DelimExtend = jsMath.Box.DelimExtendAbsolute;
jsMath.Box.Layout = jsMath.Box.LayoutAbsolute;
} else {
jsMath.Box.DelimExtend = jsMath.Box.DelimExtendRelative;
jsMath.Box.Layout = jsMath.Box.LayoutRelative;
}
if (this.separateSkips) {
jsMath.HTML.Place = jsMath.HTML.PlaceSeparateSkips;
jsMath.Typeset.prototype.Place = jsMath.Typeset.prototype.PlaceSeparateSkips;
}
},
/*
* These should be part of the regular browser
* test functions
*/
jsMath.Browser.ImgFontInit = function () {
this.msieImgFontBBoxFix = '';
if (jsMath.browser == 'Mozilla') {
if (!jsMath.Browser.VersionAtLeast("3.0")) {jsMath.Box.IMG = jsMath.Box.IMG_mozilla}
} else if (jsMath.browser == 'Opera') {
if (!jsMath.Browser.VersionAtLeast("9.50")) {
this.operaImageFonts = 1;
jsMath.Box.IMG = jsMath.Box.IMG_opera;
}
} else if (jsMath.browser == 'MSIE') {
if (jsMath.platform == 'mac') {
this.msieImgFontBBoxFix = '<span style="display:none">x</span>'
} else {
jsMath.Parser.prototype.oldTypeset = jsMath.Parser.prototype.Typeset;
jsMath.Parser.prototype.Typeset = jsMath.Parser.prototype.msieTypeset;
jsMath.Img.mustLoad = [];
this.msieImageFonts = 1;
jsMath.Controls.defaults.alpha = 0;
if (!jsMath.Controls.userSet.alpha) {jsMath.Controls.cookie.alpha = 0}
jsMath.Box.IMG = jsMath.Box.IMG_msie;
}
}
};
if (!jsMath.Parser) {jsMath.Parser = {}}
if (!jsMath.Parser.prototype) {jsMath.Parser.prototype = {}}
/*
* Handle loading of image files needed for this equation
* (avoids MSIE bug where it will request the image more
* than once if it is used more than once before it is
* loaded.)
*/
jsMath.Parser.prototype.msieTypeset = function () {
var HTML = this.oldTypeset();
if (jsMath.Img.mustLoad.length > 0) {
for (var i = 0; i < jsMath.Img.mustLoad.length; i++) {
var IMG = jsMath.Img.URL(jsMath.Img.mustLoad[i][0],jsMath.Img.mustLoad[i][1]);
jsMath.Script.WaitForImage(IMG);
jsMath.Img[jsMath.Img.mustLoad[i][1]][jsMath.Img.mustLoad[i][0]].loaded = 1;
}
jsMath.Img.mustLoad = [];
jsMath.Translate.restart = 1;
throw "restart";
}
return HTML;
};
/*
* Override the control panel calls in order to
* disable scaling in Opera.
*/
if (!jsMath.Controls) {jsMath.Controls = {}}
/*
* Add Opera calls to loading of control panel
*/
jsMath.Controls.Panel = function () {
jsMath.Translate.Cancel();
if (this.loaded) {
this.Main();
} else {
jsMath.Script.delayedLoad(jsMath.root+"jsMath-controls.html");
jsMath.Script.Push(this,"OperaInit");
}
};
/*
* Disable hi-res fonts and image scaling in Opera
*/
jsMath.Controls.OperaMain = function (init) {
if (!init) {this.OldMain()}
jsMath.Element("_resolution").disabled = true;
};
jsMath.Controls.OperaOptions = function () {
this.OldOptions();
jsMath.Element("_scaleImg").disabled = true;
jsMath.Element("_scaleImgText").className = "disabled";
};
jsMath.Controls.OperaInit = function () {
if (!jsMath.Browser.operaImageFonts) return;
this.OldMain = this.Main; this.Main = this.OperaMain;
this.OldOptions = this.Options; this.Options = this.OperaOptions;
this.OperaMain(1);
};

View File

@ -0,0 +1,406 @@
/*
* tex2math.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file is a plugin that searches text within a web page
* for \(...\), \[...\], $...$ and $$...$$ and converts them to
* the appropriate <SPAN CLASS="math">...</SPAN> or
* <DIV CLASS="math">...</DIV> tags.
*
* ---------------------------------------------------------------------
*
* Copyright 2004-2007 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
if (!jsMath.tex2math) {jsMath.tex2math = {}} // make sure jsMath.tex2math is defined
if (!jsMath.tex2math.loaded) { // only load it once
if (!jsMath.Controls) {jsMath.Controls = {}}
if (!jsMath.Controls.cookie) {jsMath.Controls.cookie = {}}
jsMath.Add(jsMath.tex2math,{
loaded: 1,
window: window,
/*
* Call the main conversion routine with appropriate flags
*/
ConvertTeX: function (element) {
this.Convert(element,{
processSingleDollars: 1, processDoubleDollars: 1,
processSlashParens: 1, processSlashBrackets: 1,
processLaTeXenvironments: 0,
custom: 0, fixEscapedDollars: 1
});
},
ConvertTeX2: function (element) {
this.Convert(element,{
processSingleDollars: 0, processDoubleDollars: 1,
processSlashParens: 1, processSlashBrackets: 1,
processLaTeXenvironments: 0,
custom: 0, fixEscapedDollars: 0
});
},
ConvertLaTeX: function (element) {
this.Convert(element,{
processSingleDollars: 0, processDoubleDollars: 0,
processSlashParens: 1, processSlashBrackets: 1,
processLaTeXenvironments: 1,
custom: 0, fixEscapedDollars: 0
});
},
ConvertCustom: function (element) {
this.Convert(element,{custom: 1, fixEscapedDollars: 0});
},
/*******************************************************************/
/*
* Define a custom search by indicating the
* strings to use for starting and ending
* in-line and display mathematics
*/
CustomSearch: function (iOpen,iClose,dOpen,dClose) {
this.inLineOpen = iOpen; this.inLineClose = iClose;
this.displayOpen = dOpen; this.displayClose = dClose;
this.createPattern('customPattern',new RegExp(
'('+this.patternQuote(dOpen)+'|'
+this.patternQuote(iOpen)+'|'
+this.patternQuote(dClose)+'|'
+this.patternQuote(iClose)+'|\\\\.)','g'
));
},
patternQuote: function (s) {
s = s.replace(/([\^$(){}+*?\-|\[\]\:\\])/g,'\\$1');
return s;
},
/*
* MSIE on the Mac doesn't handle lastIndex correctly, so
* override it and implement it correctly.
*/
createPattern: function (name,pattern) {
jsMath.tex2math[name] = pattern;
if (this.fixPatterns) {
pattern.oldExec = pattern.exec;
pattern.exec = this.msiePatternExec;
}
},
msiePatternExec: function (string) {
if (this.lastIndex == null) (this.lastIndex = 0);
var match = this.oldExec(string.substr(this.lastIndex));
if (match) {this.lastIndex += match.lastIndex}
else {this.lastIndex = null}
return match;
},
/*******************************************************************/
/*
* Set up for the correct type of search, and recursively
* convert the mathematics. Disable tex2math if the cookie
* isn't set, or of there is an element with ID of 'tex2math_off'.
*/
Convert: function (element,flags) {
this.Init();
if (!element) {element = jsMath.document.body}
if (typeof(element) == 'string') {element = jsMath.document.getElementById(element)}
if (jsMath.Controls.cookie.tex2math &&
(!jsMath.tex2math.allowDisableTag || !jsMath.document.getElementById('tex2math_off'))) {
this.custom = 0; for (var i in flags) {this[i] = flags[i]}
if (this.custom) {
this.pattern = this.customPattern;
this.ProcessMatch = this.customProcessMatch;
} else {
this.pattern = this.stdPattern;
this.ProcessMatch = this.stdProcessMatch;
}
if (this.processDoubleDollars || this.processSingleDollars ||
this.processSlashParens || this.processSlashBrackets ||
this.processLaTeXenvironments || this.custom) this.ScanElement(element);
}
},
/*
* Recursively look through a document for text nodes that could
* contain mathematics.
*/
ScanElement: function (element,ignore) {
if (!element) {element = jsMath.document.body}
if (typeof(element) == 'string') {element = jsMath.document.getElementById(element)}
while (element) {
if (element.nodeName == '#text') {
if (!ignore) {element = this.ScanText(element)}
} else {
if (element.className == null) {element.className = ''}
if (element.firstChild && element.className != 'math') {
var off = ignore || element.className.match(/(^| )tex2math_ignore( |$)/) ||
(element.tagName && element.tagName.match(/^(script|noscript|style|textarea|pre)$/i));
off = off && !element.className.match(/(^| )tex2math_process( |$)/);
this.ScanElement(element.firstChild,off);
}
}
if (element) {element = element.nextSibling}
}
},
/*
* Looks through a text element for math delimiters and
* process them. If <BR> tags are found in the middle, they
* are ignored (this is for BBS systems that have editors
* that insert these automatically).
*/
ScanText: function (element) {
if (element.nodeValue.replace(/\s+/,'') == '') {return element}
var match; var prev; this.search = {};
while (element) {
this.pattern.lastIndex = 0;
while (element && element.nodeName == '#text' &&
(match = this.pattern.exec(element.nodeValue))) {
this.pattern.match = match;
element = this.ProcessMatch(match[0],match.index,element);
}
if (this.search.matched) {element = this.EncloseMath(element)}
if (!element) {return null}
prev = element; element = element.nextSibling;
while (element && (element.nodeName.toLowerCase() == 'br' ||
element.nodeName.toLowerCase() == "#comment"))
{prev = element; element = element.nextSibling}
if (!element || element.nodeName != '#text') {return prev}
}
return element;
},
/*
* If a matching end tag has been found, process the mathematics.
* Otherwise, update the search data for the given delimiter,
* or ignore it, as the item dictates.
*/
stdProcessMatch: function (match,index,element) {
if (match == this.search.end) {
this.search.close = element;
this.search.cpos = this.pattern.lastIndex;
this.search.clength = (match.substr(0,4) == '\\end' ? 0 : match.length);
element = this.EncloseMath(element);
} else {
switch (match) {
case '\\(':
if ((this.search.end == null ||
(this.search.end != '$' && this.search.end != '$$')) &&
this.processSlashParens) {
this.ScanMark('span',element,'\\)');
}
break;
case '\\[':
if ((this.search.end == null ||
(this.search.end != '$' && this.search.end != '$$')) &&
this.processSlashBrackets) {
this.ScanMark('div',element,'\\]');
}
break;
case '$$':
if (this.processDoubleDollars) {
var type = (this.doubleDollarsAreInLine? 'span': 'div');
this.ScanMark(type,element,'$$');
}
break;
case '$':
if (this.search.end == null && this.processSingleDollars) {
this.ScanMark('span',element,'$');
}
break;
case '\\$':
if (this.search.end == null && this.fixEscapedDollars) {
element.nodeValue = element.nodeValue.substr(0,index)
+ element.nodeValue.substr(index+1);
this.pattern.lastIndex--;
}
break;
default:
if (match.substr(0,6) == '\\begin' && this.search.end == null &&
this.processLaTeXenvironments) {
this.ScanMark('div',element,'\\end'+match.substr(6));
this.search.olength = 0;
}
break;
}
}
return element;
},
/*
* If a matching end tag has been found, process the mathematics.
* Otherwise, update the search data for the given delimiter,
* or ignore it, as the item dictates.
*/
customProcessMatch: function (match,index,element) {
if (match == this.search.end) {
this.search.close = element;
this.search.clength = match.length;
this.search.cpos = this.pattern.lastIndex;
if (match == this.inLineOpen || match == this.displayOpen) {
element = this.EncloseMath(element);
} else {this.search.matched = 1}
} else if (match == this.inLineOpen) {
if (this.search.matched) {element = this.EncloseMath(element)}
this.ScanMark('span',element,this.inLineClose);
} else if (match == this.displayOpen) {
if (this.search.matched) {element = this.EncloseMath(element)}
this.ScanMark('div',element,this.displayClose);
}
return element;
},
/*
* Return a structure that records the starting location
* for the math element, and the end delimiter we want to find.
*/
ScanMark: function (type,element,end) {
var len = this.pattern.match[1].length;
this.search = {
type: type, end: end, open: element, olength: len,
pos: this.pattern.lastIndex - len
};
},
/*******************************************************************/
/*
* Surround the mathematics by an appropriate
* SPAN or DIV element marked as CLASS="math".
*/
EncloseMath: function (element) {
var search = this.search; search.end = null;
var close = search.close;
if (search.cpos == close.length) {close = close.nextSibling}
else {close = close.splitText(search.cpos)}
if (!close) {close = jsMath.document.createTextNode("")}
if (element == search.close) {element = close}
var math = search.open.splitText(search.pos);
while (math.nextSibling && math.nextSibling != close) {
if (math.nextSibling.nodeValue !== null) {
if (math.nextSibling.nodeName.toLowerCase() === "#comment") {
math.nodeValue += math.nextSibling.nodeValue.replace(/^\[CDATA\[(.*)\]\]$/,"$1");
} else {
math.nodeValue += math.nextSibling.nodeValue;
}
} else {
math.nodeValue += ' ';
}
math.parentNode.removeChild(math.nextSibling);
}
var TeX = math.nodeValue.substr(search.olength,
math.nodeValue.length-search.olength-search.clength);
math.parentNode.removeChild(math);
math = this.createMathTag(search.type,TeX);
//
// This is where older, buggy browsers can fail under unpredicatble
// circumstances, so we trap errors and at least get to continue
// with the rest of the math. (## should add error message ##)
//
try {
if (close && close.parentNode) {
close.parentNode.insertBefore(math,close);
} else if (search.open.nextSibling) {
search.open.parentNode.insertBefore(math,search.open.nextSibling);
} else {
search.open.parentNode.appendChild(math);
}
} catch (err) {}
this.search = {}; this.pattern.lastIndex = 0;
return math;
},
/*
* Create an element for the mathematics
*/
createMathTag: function (type,text) {
var tag = jsMath.document.createElement(type); tag.className = "math";
var math = jsMath.document.createTextNode(text);
tag.appendChild(math);
return tag;
},
//
// MSIE won't let you insert a DIV within tags that are supposed to
// contain in-line data (like <P> or <SPAN>), so we have to fake it
// using SPAN tags that force the formatting to work like DIV. We
// use a separate SPAN that is the full width of the containing
// item, and that has the margins and centering from the div.typeset
// style.
//
MSIEcreateMathTag: function (type,text) {
var tag = jsMath.document.createElement("span");
tag.className = "math";
text = text.replace(/</g,'&lt;').replace(/>/g,'&gt;');
if (type == 'div') {
tag.className = "tex2math_div";
text = '<span class="math">\\displaystyle{'+text+'}</span>';
}
tag.innerHTML = text;
return tag;
},
/*******************************************************************/
Init: function () {
if (!jsMath.browser && document.all && !window.opera) {
jsMath.browser = 'MSIE';
jsMath.platform = (navigator.platform.match(/Mac/) ? "mac" :
navigator.platform.match(/Win/) ? "pc" : "unix");
}
if (this.inited || !jsMath.browser) return;
/*
* MSIE can't handle the DIV's properly, so we need to do it by
* hand. Use an extra SPAN that uses CSS to act like a DIV.
*/
if (jsMath.browser == 'MSIE' && jsMath.platform == 'pc')
{this.createMathTag = this.MSIEcreateMathTag}
this.inited = 1;
},
/*
* Test to see if we need to override the pattern exec() call
* (for MSIE on the Mac).
*/
TestPatterns: function () {
var pattern = /a/g;
var match = pattern.exec("xax");
this.fixPatterns = (pattern.lastIndex != 2 && match.lastIndex == 2);
}
});
/*
* Initialize
*/
if (jsMath.Controls.cookie.tex2math == null) {jsMath.Controls.cookie.tex2math = 1}
if (jsMath.tex2math.allowDisableTag == null) {jsMath.tex2math.allowDisableTag = 1}
jsMath.tex2math.TestPatterns();
jsMath.tex2math.createPattern('stdPattern',/(\\[\(\)\[\]$]|\$\$|\$|\\(begin|end)\{[^}]+\})/g);
}

View File

@ -0,0 +1,111 @@
<HTML>
<HEAD>
<TITLE>jsMath (Test): jsMath Image Mode Test Page</TITLE>
<!-- Copyright (c) 2007 by Davide P. Cervone. All rights reserved. -->
<!-- *Document-Format: jsMath -->
<!-- *Navigation-Data:-->
</HEAD>
<BODY>
<!-- *Navigation-links -->
<TABLE WIDTH="100%" BORDER="1" CELLPADDING="2" CELLSPACING="1">
<TR><TD BGCOLOR="#B8B8B8"><TABLE WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0">
<TR><TD WIDTH="20%" ALIGN="LEFT" NOWRAP></TD>
<TD ALIGN="CENTER" WIDTH="60%"><!
><NOBR><B><SMALL><A HREF="../welcome.html">jsMath</A> (Test)</SMALL></B></NOBR><!
></TD>
<TD ALIGN="RIGHT" WIDTH="20%" HEIGHT="25" NOWRAP><!
></TD></TR></TABLE>
</TD></TR></TABLE>
<p>
<!BR>
<!-- *Begin-Document-Body -->
<SCRIPT>
jsMath = {
Controls: {cookie: {scale: 133, font:'image', autofont:0}},
Parser: {prototype: {
macros: {warning: ["Macro","\\color{##00CC00}{\\rm jsMath\\ image\\ mode\\ appears\\ to\\ be\\ working!}",1]}
}}
}
</SCRIPT>
<SCRIPT SRC="../jsMath.js"></SCRIPT>
<NOSCRIPT>
<DIV STYLE="color:#CC0000; text-align:center">
<B>Warning: <A HREF="http://www.math.union.edu/locate/jsMath">jsMath</A>
requires JavaScript to process the mathematics on this page.<BR>
If your browser supports JavaScript, be sure it is enabled.<B>
</DIV>
<HR>
</NOSCRIPT>
<BLOCKQUOTE>
<H1>jsMath Image Mode Test Page</H1>
If you see typeset mathematics below, then jsMath Image Mode is working. If you see
TeX code instead, jsMath Image Mode is not working for you.
<p>
<!------------------------------------------------------------------------>
<HR>
<DIV CLASS="math">
\left(\, \sum_{k=1}^n a_k b_k \right)^2 \le
\left(\, \sum_{k=1}^n a_k^2 \right) \left(\, \sum_{k=1}^n b_k^2 \right)
</DIV>
<p>
<DIV CLASS="math" STYLE="color:red">
\warning{ &nbsp; &nbsp; &nbsp; jsMath image mode is not working! &nbsp; &nbsp; &nbsp; }
</DIV>
<!------------------------------------------------------------------------>
<HR>
<p>
If the mathematics does not show up properly, you may not have not
installed the <A
HREF="http://www.math.union.edu/locate/jsMath/download/jsMath.html">jsMath
image fonts</A> file correctly. Follow the instructions on the linked
page.
<p>
Once you have jsMath working, go on to the <A HREF="sample.html">sample
page</A> to see if <CODE>easy/load.js</CODE> is configured properly.
</BLOCKQUOTE>
<SCRIPT>
jsMath.Controls.cookie.autofont = 0;
jsMath.Controls.cookie.font = "image";
jsMath.Process(document);
</SCRIPT>
<!-- *End-Document-Body -->
<!-- *jsMath-Common-Footer -->
<!BR><p>
<HR SIZE="3">
<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0" WIDTH="98%" ALIGN="CENTER">
<TR VALIGN="MIDDLE"><TD BGCOLOR="#B8B8B8" WIDTH="50%">
<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="8" ALIGN="CENTER">
<TR VALIGN="MIDDLE">
<TD><IMG SRC="jsMath40.jpg" ALT="[HOME]" BORDER="1" WIDTH="40" HEIGHT="40" HSPACE="5"></TD>
<TD><SMALL>jsMath web pages<BR>
Created: 14 Feb 2007<BR>
<!-- hhmts start -->
Last modified: Jun 16, 2007 8:56:17 AM
<!-- hhmts end -->
<BR>
Comments to: <A HREF="mailto:dpvc@union.edu"><CODE>dpvc@union.edu</CODE></A><BR>
</SMALL></TD>
</TR></TABLE></TD>
<TD WIDTH="100%" BGCOLOR="#B8B8B8">&nbsp;</TD>
</TR></TABLE>
<HR SIZE="3">
</BODY>
</HTML>

View File

@ -0,0 +1,114 @@
<HTML>
<HEAD>
<TITLE>jsMath (Test): jsMath Test Page</TITLE>
<!-- Copyright (c) 2007 by Davide P. Cervone. All rights reserved. -->
<!-- *Document-Format: jsMath -->
<!-- *Navigation-Data:-->
</HEAD>
<BODY>
<!-- *Navigation-links -->
<TABLE WIDTH="100%" BORDER="1" CELLPADDING="2" CELLSPACING="1">
<TR><TD BGCOLOR="#B8B8B8"><TABLE WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0">
<TR><TD WIDTH="20%" ALIGN="LEFT" NOWRAP></TD>
<TD ALIGN="CENTER" WIDTH="60%"><!
><NOBR><B><SMALL><A HREF="../welcome.html">jsMath</A> (Test)</SMALL></B></NOBR><!
></TD>
<TD ALIGN="RIGHT" WIDTH="20%" HEIGHT="25" NOWRAP><!
></TD></TR></TABLE>
</TD></TR></TABLE>
<p>
<!BR>
<!-- *Begin-Document-Body -->
<SCRIPT>
jsMath = {
Controls: {
cookie: {scale: 133},
CheckVersion: function () {
jsMath.Script.delayedLoad('http://www.math.union.edu/locate/jsMath/jsMath/jsMath-version-check.js');
}
},
Parser: {prototype: {
macros: {warning: ["Macro","\\color{##00CC00}{\\rm jsMath\\ appears\\ to\\ be\\ working!}",1]}
}}
}
</SCRIPT>
<SCRIPT SRC="../plugins/noImageFonts.js"></SCRIPT>
<SCRIPT SRC="../jsMath.js"></SCRIPT>
<NOSCRIPT>
<DIV STYLE="color:#CC0000; text-align:center">
<B>Warning: <A HREF="http://www.math.union.edu/locate/jsMath">jsMath</A>
requires JavaScript to process the mathematics on this page.<BR>
If your browser supports JavaScript, be sure it is enabled.<B>
</DIV>
<HR>
</NOSCRIPT>
<BLOCKQUOTE>
<DIV STYLE="float:right; width:auto; margin-top:.5em">
<INPUT TYPE="button" VALUE="Check for Updates" ONCLICK="jsMath.Controls.CheckVersion()">
</DIV>
<H1>jsMath Test Page</H1>
If you see typeset mathematics below, then jsMath is working. If you see
TeX code instead, jsMath is not working for you.
<p>
<!------------------------------------------------------------------------>
<HR>
<DIV CLASS="math">
\left(\, \sum_{k=1}^n a_k b_k \right)^2 \le
\left(\, \sum_{k=1}^n a_k^2 \right) \left(\, \sum_{k=1}^n b_k^2 \right)
</DIV>
<p>
<DIV CLASS="math" STYLE="color:red">
\warning{ &nbsp; &nbsp; &nbsp; jsMath is not working! &nbsp; &nbsp; &nbsp; }
</DIV>
<!------------------------------------------------------------------------>
<HR>
<p>
Once you have jsMath working properly, view the <A
HREF="index-images.html">image mode test page</A> to make sure that the
image fallback mode is working as well.
</BLOCKQUOTE>
<SCRIPT>
jsMath.Process(document);
</SCRIPT>
<!-- *End-Document-Body -->
<!-- *jsMath-Common-Footer -->
<!BR><p>
<HR SIZE="3">
<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0" WIDTH="98%" ALIGN="CENTER">
<TR VALIGN="MIDDLE"><TD BGCOLOR="#B8B8B8" WIDTH="50%">
<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="8" ALIGN="CENTER">
<TR VALIGN="MIDDLE">
<TD><IMG SRC="jsMath40.jpg" ALT="[HOME]" BORDER="1" WIDTH="40" HEIGHT="40" HSPACE="5"></TD>
<TD><SMALL>jsMath web pages<BR>
Created: 14 Feb 2007<BR>
<!-- hhmts start -->
Last modified: Feb 12, 2009 6:14:47 PM
<!-- hhmts end -->
<BR>
Comments to: <A HREF="mailto:dpvc@union.edu"><CODE>dpvc@union.edu</CODE></A><BR>
</SMALL></TD>
</TR></TABLE></TD>
<TD WIDTH="100%" BGCOLOR="#B8B8B8">&nbsp;</TD>
</TR></TABLE>
<HR SIZE="3">
</BODY>
</HTML>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,165 @@
<HTML>
<HEAD>
<TITLE>jsMath (Test): jsMath Sample Page</TITLE>
<!-- Copyright (c) 2007 by Davide P. Cervone. All rights reserved. -->
<!--
| -----------------------------------------------------------
| The following line loads and initializes jsMath.
| You may need to edit the load.js file to set the
| root URL for your site before this file will
| display properly
| -----------------------------------------------------------
-->
<SCRIPT SRC="../easy/load.js"></SCRIPT>
</HEAD>
<BODY>
<!--
| -----------------------------------------------------------
| Include this NOSCRIPT block to inform users that JavaScript
| is required if they don't have it enabled.
| -----------------------------------------------------------
-->
<NOSCRIPT>
<DIV STYLE="color:#CC0000; text-align:center">
<B>Warning: <A HREF="http://www.math.union.edu/locate/jsMath">jsMath</A>
requires JavaScript to process the mathematics on this page.<BR>
If your browser supports JavaScript, be sure it is enabled.<B>
</DIV>
<HR>
</NOSCRIPT>
<BLOCKQUOTE>
<H1>jsMath Sample Page</H1>
This is a sample file showing you how to use jsMath to display mathematics
in your web pages. Be sure you have followed the <A
HREF="http://www.math.union.edu/locate/jsMath/authors/installation.html">installation
instructions</A> before loading this file. Also, you may need to edit the
<CODE>jsMath/easy/load.js</CODE> file to set the root URL for where jsMath
can be found on your web site. The rest of this document gives examples of
how to enter mathematics in your pages. Depending on the settings in
<CODE>jsMath/easy/load.js</CODE>, not all of the mathematics below will be
processed by jsMath. Experiment with the settings in that file to see how
they work.
<p>
<HR>
<p>
<H2>Some mathematics using <CODE>tex2math</CODE></H2>
The easiest way to enter mathematics is to use jsMath's <A
HREF="http://www.math.union.edu/locate/jsMath/authors/tex2math.html">tex2math</A>
plugin to identify the mathematics in your document by looking for <SPAN
class="math">\rm\TeX</SPAN>-like math delimiters. Here are some math
equations using those markers. Some inline math: $\sqrt{1-x^2}$ or \(ax^2+bx+c\),
and some displayed math:
$$\int {1\over x}\,dx = \ln(x)+C$$
and
\[\sum_{i=1}^n i = {n(n+1)\over 2}.\]
Note that the first of these will not be processed unless you have enabled
<CODE>processSingleDollars</CODE> in <CODE>jsMath/easy/load.js</CODE>,
which is disabled by default. That is because a single dollar sign can
appear in normal text (as in "That will cost from <SPAN>$</SPAN>3.50 to
<SPAN>$</SPAN>5.00 to repair"), and you don't want jsMath to try to typeset
the "3.50 to " as mathematics.
<p>
If you enable <CODE>processSingleDollars</CODE>, you might also want to
enable <CODE>fixEscapedDollars</CODE>, so that it is possible to enter
dollar signs by preceding them with a backslash. Here's one that you can
use to see the results of these settings: \$ (an escaped dollar) and $x+1$
(not escaped).
<p>
It is also possible to use your own custom delimiters for marking the
mathematics within your pages. If you uncomment the <CODE>customDelimiters</CODE>
array in <CODE>jsMath/easy/load.js</CODE>, then the following math will be
typeset by jsMath: some inline math [math]\sin(2\pi x)[/math] and some
display math [display]x={-b\pm \sqrt{b^2-4ac}\over 2a}.[/display]
You may change the delimiters to nearly anything you want, but they can not
look like HTML tags, since some browsers will eliminate unknown tags, and
jsMath doesn't get to look for the custom delimiters until <I>after</I> the
browser has interpreted the page.
<p>
<DIV CLASS="tex2math_ignore">
You can prevent the <CODE>tex2math</CODE> plugin from processing a portion
of a page by enclosing it in a tag that is of
<CODE>CLASS="tex2math_ignore"</CODE>. Often, that tag will be a
<CODE>DIV</CODE> or <CODE>SPAN</CODE>, but it can be anything. This
paragraph is wrapped in a DIV tag with
<CODE>CLASS="tex2math_ignore"</CODE>, and so no math delimiters will be
processed: $f\colon X\to Y$, \(x^2 \gt 5\), $$1\over 1+x^2$$ and
\[\matrix{a& b\cr c& d}.\]
Note that this includes the processing of escaped dollars (\$) and
custom delimiters ([math]a \mapsto a^2[/math]) as well.
This makes it possible to produce examples of how to enter mathematics on
your site, for instance.
</DIV>
<P>
JsMath will automatically ignore the text within
<CODE>PRE</CODE> tags, so you can easily enter examples that way as well:
<PRE>
$f\colon X\to Y$, \(x^2 \gt 5\),
$$1\over 1+x^2$$ and \[\matrix{a& b\cr c& d}.\]
</PRE>
<P>
Note that since the &lt; and &gt; symbols are used to denote HTML tags,
these can be hard to incorporate into your <SPAN CLASS="math">\rm\TeX</SPAN>
code. Often, putting spaces around the &lt; or &gt; will make it work, but
it is probably better to use <CODE>\lt</CODE> and <CODE>\gt</CODE> instead.
Also note that the <CODE>tex2math</CODE> plugin does not allow any HTML
tags to be within the math delimiters, with the exception of
<CODE>&lt;BR&gt;</CODE>, which is ignored.
<p>
See the <A
HREF="http://www.math.union.edu/locate/jsMath/authors/tex2math.html">tex2math
documentation</A> for more information.
<p>
<HR>
<p>
<H2>Mathematics without <CODE>tex2math</CODE></H2>
<p>
If you are not using <CODE>tex2math</CODE>, then you will need to enclose
your mathematics within <CODE>SPAN</CODE> or <CODE>DIV</CODE> tags that
are of <CODE>CLASS="math"</CODE>. Use a <CODE>SPAN</CODE> for in-line math
and a <CODE>DIV</CODE> for displayed math. For instance, <SPAN
CLASS="math">P = (x_1,\ldots,x_n)</SPAN> and
<DIV CLASS="math">
A = \left\lgroup\matrix{a_{11}& \cdots& a_{1m}\cr
\vdots& \ddots& \vdots\cr
a_{n1}& \cdots& a_{nm}\cr}\right\rgroup.
</DIV>
<p>
<HR>
<P>
<H2>More information</H2>
<p>
See the <A HREF="http://www.math.union.edu/locate/jsMath/examples">jsMath
example files</A> for more examples of using jsMath. There are several <A
HREF="http://www.math.union.edu/locate/jsMath/examples/extensions.html">extensions</A>
to <SPAN CLASS="math">\rm\TeX</SPAN> that allow jsMath to interact better
with HTML. These provide features such as colored text, tagging mathematics
with CSS styles, and so on.
<p>
More information is available from the <A
HREF="http://www.math.union.edu/locate/jsMath/authors">jsMath author's
documentation</A> site. JsMath also has a <A
HREF="http://sourceforge.net/projects/jsmath/">home page at
SourceForge</A>, and that includes <A
HREF="http://sourceforge.net/forum/?group_id=172663">public forums</A>
for jsMath where you can ask the jsMath user community for help.
</BLOCKQUOTE>
</BODY>
</HTML>

View File

@ -0,0 +1,977 @@
/*
* jsMath-fallback-pc.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file makes changes needed for when the TeX fonts are not available
* with a browser on the PC.
*
* ---------------------------------------------------------------------
*
* Copyright 2004-2006 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/********************************************************************
*
* Here we replace the TeX character mappings by equivalent unicode
* points when possible, and adjust the character dimensions
* based on the fonts we hope we get them from (the styles are set
* to try to use the best characters available in the standard
* fonts).
*/
jsMath.Add(jsMath.TeX,{
cmr10: [
// 00 - 0F
{c: '&Gamma;', tclass: 'greek'},
{c: '&Delta;', tclass: 'greek'},
{c: '&Theta;', tclass: 'greek'},
{c: '&Lambda;', tclass: 'greek'},
{c: '&Xi;', tclass: 'greek'},
{c: '&Pi;', tclass: 'greek'},
{c: '&Sigma;', tclass: 'greek'},
{c: '&Upsilon;', tclass: 'greek'},
{c: '&Phi;', tclass: 'greek'},
{c: '&Psi;', tclass: 'greek'},
{c: '&Omega;', tclass: 'greek'},
{c: 'ff', ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 14, '108': 15}, tclass: 'normal'},
{c: 'fi', tclass: 'normal'},
{c: 'fl', tclass: 'normal'},
{c: 'ffi', tclass: 'normal'},
{c: 'ffl', tclass: 'normal'},
// 10 - 1F
{c: '&#x131;', a:0, tclass: 'normal'},
{c: 'j', d:.2, tclass: 'normal'},
{c: '&#x2CB;', tclass: 'accent'},
{c: '&#x2CA;', tclass: 'accent'},
{c: '&#x2C7;', tclass: 'accent'},
{c: '&#x2D8;', tclass: 'accent'},
{c: '&#x2C9;', tclass: 'accent'},
{c: '&#x2DA;', tclass: 'accent'},
{c: '&#x0327;', tclass: 'normal'},
{c: '&#xDF;', tclass: 'normal'},
{c: '&#xE6;', a:0, tclass: 'normal'},
{c: '&#x153;', a:0, tclass: 'normal'},
{c: '&#xF8;', tclass: 'normal'},
{c: '&#xC6;', tclass: 'normal'},
{c: '&#x152;', tclass: 'normal'},
{c: '&#xD8;', tclass: 'normal'},
// 20 - 2F
{c: '?', krn: {'108': -0.278, '76': -0.319}, tclass: 'normal'},
{c: '!', lig: {'96': 60}, tclass: 'normal'},
{c: '&#x201D;', tclass: 'normal'},
{c: '#', tclass: 'normal'},
{c: '$', tclass: 'normal'},
{c: '%', tclass: 'normal'},
{c: '&amp;', tclass: 'normal'},
{c: '&#x2019;', krn: {'63': 0.111, '33': 0.111}, lig: {'39': 34}, tclass: 'normal'},
{c: '(', d:.2, tclass: 'normal'},
{c: ')', d:.2, tclass: 'normal'},
{c: '*', tclass: 'normal'},
{c: '+', a:.1, tclass: 'normal'},
{c: ',', a:-.3, d:.2, w: 0.278, tclass: 'normal'},
{c: '-', a:0, lig: {'45': 123}, tclass: 'normal'},
{c: '.', a:-.25, tclass: 'normal'},
{c: '/', tclass: 'normal'},
// 30 - 3F
{c: '0', tclass: 'normal'},
{c: '1', tclass: 'normal'},
{c: '2', tclass: 'normal'},
{c: '3', tclass: 'normal'},
{c: '4', tclass: 'normal'},
{c: '5', tclass: 'normal'},
{c: '6', tclass: 'normal'},
{c: '7', tclass: 'normal'},
{c: '8', tclass: 'normal'},
{c: '9', tclass: 'normal'},
{c: ':', tclass: 'normal'},
{c: ';', tclass: 'normal'},
{c: '&#xA1;', tclass: 'normal'},
{c: '=', a:0, d:-.1, tclass: 'normal'},
{c: '&#xBF;', tclass: 'normal'},
{c: '?', lig: {'96': 62}, tclass: 'normal'},
// 40 - 4F
{c: '@', tclass: 'normal'},
{c: 'A', krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}, tclass: 'normal'},
{c: 'B', tclass: 'normal'},
{c: 'C', tclass: 'normal'},
{c: 'D', krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}, tclass: 'normal'},
{c: 'E', tclass: 'normal'},
{c: 'F', krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'normal'},
{c: 'G', tclass: 'normal'},
{c: 'H', tclass: 'normal'},
{c: 'I', krn: {'73': 0.0278}, tclass: 'normal'},
{c: 'J', tclass: 'normal'},
{c: 'K', krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'normal'},
{c: 'L', krn: {'84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}, tclass: 'normal'},
{c: 'M', tclass: 'normal'},
{c: 'N', tclass: 'normal'},
{c: 'O', krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}, tclass: 'normal'},
// 50 - 5F
{c: 'P', krn: {'65': -0.0833, '111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}, tclass: 'normal'},
{c: 'Q', d:.2, tclass: 'normal'},
{c: 'R', krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}, tclass: 'normal'},
{c: 'S', tclass: 'normal'},
{c: 'T', krn: {'121': -0.0278, '101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}, tclass: 'normal'},
{c: 'U', tclass: 'normal'},
{c: 'V', ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'normal'},
{c: 'W', ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'normal'},
{c: 'X', krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'normal'},
{c: 'Y', ic: 0.025, krn: {'101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}, tclass: 'normal'},
{c: 'Z', tclass: 'normal'},
{c: '[', d:.1, tclass: 'normal'},
{c: '&#x201C;', tclass: 'normal'},
{c: ']', d:.1, tclass: 'normal'},
{c: '&#x2C6;', tclass: 'accent'},
{c: '&#x2D9;', tclass: 'accent'},
// 60 - 6F
{c: '&#x2018;', lig: {'96': 92}, tclass: 'normal'},
{c: 'a', a:0, krn: {'118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'normal'},
{c: 'b', krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'normal'},
{c: 'c', a:0, krn: {'104': -0.0278, '107': -0.0278}, tclass: 'normal'},
{c: 'd', tclass: 'normal'},
{c: 'e', a:0, tclass: 'normal'},
{c: 'f', ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 12, '102': 11, '108': 13}, tclass: 'normal'},
{c: 'g', a:0, d:.2, ic: 0.0139, krn: {'106': 0.0278}, tclass: 'normal'},
{c: 'h', krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}, tclass: 'normal'},
{c: 'i', tclass: 'normal'},
{c: 'j', d:.2, tclass: 'normal'},
{c: 'k', krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}, tclass: 'normal'},
{c: 'l', tclass: 'normal'},
{c: 'm', a:0, krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}, tclass: 'normal'},
{c: 'n', a:0, krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}, tclass: 'normal'},
{c: 'o', a:0, krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'normal'},
// 70 - 7F
{c: 'p', a:0, d:.2, krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'normal'},
{c: 'q', a:0, d:.2, tclass: 'normal'},
{c: 'r', a:0, tclass: 'normal'},
{c: 's', a:0, tclass: 'normal'},
{c: 't', krn: {'121': -0.0278, '119': -0.0278}, tclass: 'normal'},
{c: 'u', a:0, krn: {'119': -0.0278}, tclass: 'normal'},
{c: 'v', a:0, ic: 0.0139, krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}, tclass: 'normal'},
{c: 'w', a:0, ic: 0.0139, krn: {'101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}, tclass: 'normal'},
{c: 'x', a:0, tclass: 'normal'},
{c: 'y', a:0, d:.2, ic: 0.0139, krn: {'111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}, tclass: 'normal'},
{c: 'z', a:0, tclass: 'normal'},
{c: '&#x2013;', a:.1, ic: 0.0278, lig: {'45': 124}, tclass: 'normal'},
{c: '&#x2014;', a:.1, ic: 0.0278, tclass: 'normal'},
{c: '&#x2DD;', tclass: 'accent'},
{c: '&#x2DC;', tclass: 'accent'},
{c: '&#xA8;', tclass: 'accent'}
],
cmmi10: [
// 00 - 0F
{c: '&Gamma;', ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0833}, tclass: 'igreek'},
{c: '&Delta;', krn: {'127': 0.167}, tclass: 'igreek'},
{c: '&Theta;', ic: 0.0278, krn: {'127': 0.0833}, tclass: 'igreek'},
{c: '&Lambda;', krn: {'127': 0.167}, tclass: 'igreek'},
{c: '&Xi;', ic: 0.0757, krn: {'127': 0.0833}, tclass: 'igreek'},
{c: '&Pi;', ic: 0.0812, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}, tclass: 'igreek'},
{c: '&Sigma;', ic: 0.0576, krn: {'127': 0.0833}, tclass: 'igreek'},
{c: '&Upsilon;', ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0556}, tclass: 'igreek'},
{c: '&Phi;', krn: {'127': 0.0833}, tclass: 'igreek'},
{c: '&Psi;', ic: 0.11, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}, tclass: 'igreek'},
{c: '&Omega;', ic: 0.0502, krn: {'127': 0.0833}, tclass: 'igreek'},
{c: '&alpha;', a:0, ic: 0.0037, krn: {'127': 0.0278}, tclass: 'greek'},
{c: '&beta;', d:.2, ic: 0.0528, krn: {'127': 0.0833}, tclass: 'greek'},
{c: '&gamma;', a:0, d:.2, ic: 0.0556, tclass: 'greek'},
{c: '&delta;', ic: 0.0378, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0556}, tclass: 'greek'},
{c: '&epsilon;', a:0, krn: {'127': 0.0556}, tclass: 'lucida'},
// 10 - 1F
{c: '&zeta;', d:.2, ic: 0.0738, krn: {'127': 0.0833}, tclass: 'greek'},
{c: '&eta;', a:0, d:.2, ic: 0.0359, krn: {'127': 0.0556}, tclass: 'greek'},
{c: '&theta;', ic: 0.0278, krn: {'127': 0.0833}, tclass: 'greek'},
{c: '&iota;', a:0, krn: {'127': 0.0556}, tclass: 'greek'},
{c: '&kappa;', a:0, tclass: 'greek'},
{c: '&lambda;', tclass: 'greek'},
{c: '&mu;', a:0, d:.2, krn: {'127': 0.0278}, tclass: 'greek'},
{c: '&nu;', a:0, ic: 0.0637, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0278}, tclass: 'greek'},
{c: '&xi;', d:.2, ic: 0.046, krn: {'127': 0.111}, tclass: 'greek'},
{c: '&pi;', a:0, ic: 0.0359, tclass: 'greek'},
{c: '&rho;', a:0, d:.2, krn: {'127': 0.0833}, tclass: 'greek'},
{c: '&sigma;', a:0, ic: 0.0359, krn: {'59': -0.0556, '58': -0.0556}, tclass: 'greek'},
{c: '&tau;', a:0, ic: 0.113, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0278}, tclass: 'greek'},
{c: '&upsilon;', a:0, ic: 0.0359, krn: {'127': 0.0278}, tclass: 'greek'},
{c: '&phi;', a:.1, d:.2, krn: {'127': 0.0833}, tclass: 'greek'},
{c: '&chi;', a:0, d:.2, krn: {'127': 0.0556}, tclass: 'greek'},
// 20 - 2F
{c: '&psi;', a:.1, d:.2, ic: 0.0359, krn: {'127': 0.111}, tclass: 'greek'},
{c: '&omega;', a:0, ic: 0.0359, tclass: 'greek'},
{c: '&epsilon;', a:0, krn: {'127': 0.0833}, tclass: 'greek'},
{c: '&#x3D1;', krn: {'127': 0.0833}, tclass: 'lucida'},
{c: '&#x3D6;', a:0, ic: 0.0278, tclass: 'lucida'},
{c: '&#x3F1;', a:0, d:.2, krn: {'127': 0.0833}, tclass: 'lucida'},
{c: '&#x3C2;', a:0, d:.2, ic: 0.0799, krn: {'127': 0.0833}, tclass: 'lucida'},
{c: '&#x3D5;', a:.1, d:.2, krn: {'127': 0.0833}, tclass: 'lucida'},
{c: '&#x21BC;', a:0, d:-.2, tclass: 'arrows'},
{c: '&#x21BD;', a:0, d:-.1, tclass: 'arrows'},
{c: '&#x21C0;', a:0, d:-.2, tclass: 'arrows'},
{c: '&#x21C1;', a:0, d:-.1, tclass: 'arrows'},
{c: '<span style="position:relative; top:-.1em">&#x02D3;</span>', a:.1, tclass: 'symbol'},
{c: '<span style="position:relative; top:-.1em">&#x02D2;</span>', a:.1, tclass: 'symbol'},
{c: '&#x25B9;', tclass: 'symbol'},
{c: '&#x25C3;', tclass: 'symbol'},
// 30 - 3F
{c: '0', tclass: 'normal'},
{c: '1', tclass: 'normal'},
{c: '2', tclass: 'normal'},
{c: '3', tclass: 'normal'},
{c: '4', tclass: 'normal'},
{c: '5', tclass: 'normal'},
{c: '6', tclass: 'normal'},
{c: '7', tclass: 'normal'},
{c: '8', tclass: 'normal'},
{c: '9', tclass: 'normal'},
{c: '.', a:-.3, tclass: 'normal'},
{c: ',', a:-.3, d:.2, tclass: 'normal'},
{c: '&lt;', a:.1, tclass: 'normal'},
{c: '<span style="font-size:133%; position:relative; top:.1em">/</span>', d:.1, krn: {'1': -0.0556, '65': -0.0556, '77': -0.0556, '78': -0.0556, '89': 0.0556, '90': -0.0556}, tclass: 'normal'},
{c: '&gt;', a:.1, tclass: 'normal'},
{c: '&#x22C6;', a:0, tclass: 'arial'},
// 40 - 4F
{c: '&#x2202;', ic: 0.0556, krn: {'127': 0.0833}, tclass: 'normal'},
{c: 'A', krn: {'127': 0.139}, tclass: 'italic'},
{c: 'B', ic: 0.0502, krn: {'127': 0.0833}, tclass: 'italic'},
{c: 'C', ic: 0.0715, krn: {'61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'},
{c: 'D', ic: 0.0278, krn: {'127': 0.0556}, tclass: 'italic'},
{c: 'E', ic: 0.0576, krn: {'127': 0.0833}, tclass: 'italic'},
{c: 'F', ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0833}, tclass: 'italic'},
{c: 'G', krn: {'127': 0.0833}, tclass: 'italic'},
{c: 'H', ic: 0.0812, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}, tclass: 'italic'},
{c: 'I', ic: 0.0785, krn: {'127': 0.111}, tclass: 'italic'},
{c: 'J', ic: 0.0962, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.167}, tclass: 'italic'},
{c: 'K', ic: 0.0715, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}, tclass: 'italic'},
{c: 'L', krn: {'127': 0.0278}, tclass: 'italic'},
{c: 'M', ic: 0.109, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'},
{c: 'N', ic: 0.109, krn: {'61': -0.0833, '61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'},
{c: 'O', ic: 0.0278, krn: {'127': 0.0833}, tclass: 'italic'},
// 50 - 5F
{c: 'P', ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0833}, tclass: 'italic'},
{c: 'Q', d:.2, krn: {'127': 0.0833}, tclass: 'italic'},
{c: 'R', ic: 0.00773, krn: {'127': 0.0833}, tclass: 'italic'},
{c: 'S', ic: 0.0576, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'},
{c: 'T', ic: 0.139, krn: {'61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'},
{c: 'U', ic: 0.109, krn: {'59': -0.111, '58': -0.111, '61': -0.0556, '127': 0.0278}, tclass: 'italic'},
{c: 'V', ic: 0.222, krn: {'59': -0.167, '58': -0.167, '61': -0.111}, tclass: 'italic'},
{c: 'W', ic: 0.139, krn: {'59': -0.167, '58': -0.167, '61': -0.111}, tclass: 'italic'},
{c: 'X', ic: 0.0785, krn: {'61': -0.0833, '61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'},
{c: 'Y', ic: 0.222, krn: {'59': -0.167, '58': -0.167, '61': -0.111}, tclass: 'italic'},
{c: 'Z', ic: 0.0715, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'},
{c: '&#x266D;', tclass: 'symbol'},
{c: '&#x266E;', tclass: 'symbol'},
{c: '&#x266F;', tclass: 'symbol'},
{c: '<span style="position: relative; top:-.3em; font-size:75%">&#x203F;</span>', a:0, d:-.1, tclass: 'arial'},
{c: '<span style="position: relative; top:.4em; font-size:75%">&#x2040;</span>', a:0, d:-.1, tclass: 'arial'},
// 60 - 6F
{c: '&#x2113;', krn: {'127': 0.111}, tclass: 'italic'},
{c: 'a', a:0, tclass: 'italic'},
{c: 'b', tclass: 'italic'},
{c: 'c', a:0, krn: {'127': 0.0556}, tclass: 'italic'},
{c: 'd', krn: {'89': 0.0556, '90': -0.0556, '106': -0.111, '102': -0.167, '127': 0.167}, tclass: 'italic'},
{c: 'e', a:0, krn: {'127': 0.0556}, tclass: 'italic'},
{c: 'f', d:.2, ic: 0.108, krn: {'59': -0.0556, '58': -0.0556, '127': 0.167}, tclass: 'italic'},
{c: 'g', a:0, d:.2, ic: 0.0359, krn: {'127': 0.0278}, tclass: 'italic'},
{c: 'h', krn: {'127': -0.0278}, tclass: 'italic'},
{c: 'i', tclass: 'italic'},
{c: 'j', d:.2, ic: 0.0572, krn: {'59': -0.0556, '58': -0.0556}, tclass: 'italic'},
{c: 'k', ic: 0.0315, tclass: 'italic'},
{c: 'l', ic: 0.0197, krn: {'127': 0.0833}, tclass: 'italic'},
{c: 'm', a:0, tclass: 'italic'},
{c: 'n', a:0, tclass: 'italic'},
{c: 'o', a:0, krn: {'127': 0.0556}, tclass: 'italic'},
// 70 - 7F
{c: 'p', a:0, d:.2, krn: {'127': 0.0833}, tclass: 'italic'},
{c: 'q', a:0, d:.2, ic: 0.0359, krn: {'127': 0.0833}, tclass: 'italic'},
{c: 'r', a:0, ic: 0.0278, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0556}, tclass: 'italic'},
{c: 's', a:0, krn: {'127': 0.0556}, tclass: 'italic'},
{c: 't', krn: {'127': 0.0833}, tclass: 'italic'},
{c: 'u', a:0, krn: {'127': 0.0278}, tclass: 'italic'},
{c: 'v', a:0, ic: 0.0359, krn: {'127': 0.0278}, tclass: 'italic'},
{c: 'w', a:0, ic: 0.0269, krn: {'127': 0.0833}, tclass: 'italic'},
{c: 'x', a:0, krn: {'127': 0.0278}, tclass: 'italic'},
{c: 'y', a:0, d:.2, ic: 0.0359, krn: {'127': 0.0556}, tclass: 'italic'},
{c: 'z', a:0, ic: 0.044, krn: {'127': 0.0556}, tclass: 'italic'},
{c: '&#x131;', a:0, krn: {'127': 0.0278}, tclass: 'italic'},
{c: 'j', d:.2, krn: {'127': 0.0833}, tclass: 'italic'},
{c: '&#x2118;', a:0, d:.2, krn: {'127': 0.111}, tclass: 'arial'},
{c: '<span style="position:relative; left: .3em; top: -.65em; font-size: 67%">&#x2192;</span>', ic: 0.154, tclass: 'symbol'},
{c: '&#x0311;', ic: 0.399, tclass: 'normal'}
],
cmsy10: [
// 00 - 0F
{c: '<span style="position:relative; top:.1em">&#x2212;</span>', a:.1, tclass: 'symbol'},
{c: '&#xB7;', a:0, d:-.2, tclass: 'normal'},
{c: '&#xD7;', a:0, tclass: 'normal'},
{c: '<span style="position:relative; top:.3em">&#x2A;</span>', a:0, tclass: 'normal'},
{c: '&#xF7;', a:0, tclass: 'normal'},
{c: '&#x25CA;', tclass: 'symbol'},
{c: '&#xB1;', a:.1, tclass: 'normal'},
{c: '&#x2213;', tclass: 'symbol'},
{c: '&#x2295;', tclass: 'symbol'},
{c: '&#x2296;', tclass: 'symbol'},
{c: '&#x2297;', tclass: 'symbol'},
{c: '&#x2298;', tclass: 'symbol'},
{c: '&#x2299;', tclass: 'symbol'},
{c: '&#x25EF;', tclass: 'arial'},
{c: '&#x2218;', a:0, d:-.1, tclass: 'symbol2'},
{c: '&#x2022;', a:0, d:-.2, tclass: 'symbol'},
// 10 - 1F
{c: '&#x224D;', a:.1, tclass: 'symbol2'},
{c: '&#x2261;', a:.1, tclass: 'symbol2'},
{c: '&#x2286;', tclass: 'symbol'},
{c: '&#x2287;', tclass: 'symbol'},
{c: '&#x2264;', tclass: 'symbol'},
{c: '&#x2265;', tclass: 'symbol'},
{c: '&#x227C;', tclass: 'symbol'},
{c: '&#x227D;', tclass: 'symbol'},
{c: '~', a:0, d: -.2, tclass: 'normal'},
{c: '&#x2248;', a:.1, d:-.1, tclass: 'symbol'},
{c: '&#x2282;', tclass: 'symbol'},
{c: '&#x2283;', tclass: 'symbol'},
{c: '&#x226A;', tclass: 'symbol'},
{c: '&#x226B;', tclass: 'symbol'},
{c: '&#x227A;', tclass: 'symbol'},
{c: '&#x227B;', tclass: 'symbol'},
// 20 - 2F
{c: '&#x2190;', a:-.1, tclass: 'arrow1'},
{c: '&#x2192;', a:-.1, tclass: 'arrow1'},
{c: '&#x2191;', a:.2, d:0, tclass: 'arrow1a'},
{c: '&#x2193;', a:.2, d:0, tclass: 'arrow1a'},
{c: '&#x2194;', a:-.1, tclass: 'arrow1'},
{c: '&#x2197;', a:.1, tclass: 'arrows'},
{c: '&#x2198;', a:.1, tclass: 'arrows'},
{c: '&#x2243;', a: .1, tclass: 'symbol2'},
{c: '&#x21D0;', a:-.1, tclass: 'arrow2'},
{c: '&#x21D2;', a:-.1, tclass: 'arrow2'},
{c: '&#x21D1;', a:.2, d:.1, tclass: 'arrow1a'},
{c: '&#x21D3;', a:.2, d:.1, tclass: 'arrow1a'},
{c: '&#x21D4;', a:-.1, tclass: 'arrow2'},
{c: '&#x2196;', a:.1, tclass: 'arrows'},
{c: '&#x2199;', a:.1, tclass: 'arrows'},
{c: '&#x221D;', a:.1, tclass: 'normal'},
// 30 - 3F
{c: '<span style="font-size: 133%; margin-right: -.1em; position: relative; top:.4em">&#x2032;</span>', a: 0, tclass: 'lucida'},
{c: '&#x221E;', a:.1, tclass: 'symbol'},
{c: '&#x2208;', tclass: 'symbol'},
{c: '&#x220B;', tclass: 'symbol'},
{c: '<span style="font-size: 150%; position:relative; top:.2em">&#x25B3;</span>', tclass: 'symbol'},
{c: '<span style="font-size: 150%; position:relative; top:.2em">&#x25BD;</span>', tclass: 'symbol'},
{c: '<span style="font-size: 133%; position:relative; top:.2em">/</span>', d:.2, tclass: 'normal'},
{c: '<span style="font-size: 67%; position: relative; top:-.15em; margin-right:-.3em">&#x22A2;</span>', tclass: 'symbol'},
{c: '&#x2200;', tclass: 'symbol'},
{c: '&#x2203;', tclass: 'symbol'},
{c: '&#xAC;', a:0, d:-.1, tclass: 'symbol'},
{c: '&#x2205;', tclass: 'symbol'},
{c: '&#x211C;', tclass: 'symbol'},
{c: '&#x2111;', tclass: 'symbol'},
{c: '&#x22A4;', tclass: 'symbol'},
{c: '&#x22A5;', tclass: 'symbol'},
// 40 - 4F
{c: '&#x2135;', tclass: 'symbol'},
{c: 'A', krn: {'48': 0.194}, tclass: 'cal'},
{c: 'B', ic: 0.0304, krn: {'48': 0.139}, tclass: 'cal'},
{c: 'C', ic: 0.0583, krn: {'48': 0.139}, tclass: 'cal'},
{c: 'D', ic: 0.0278, krn: {'48': 0.0833}, tclass: 'cal'},
{c: 'E', ic: 0.0894, krn: {'48': 0.111}, tclass: 'cal'},
{c: 'F', ic: 0.0993, krn: {'48': 0.111}, tclass: 'cal'},
{c: 'G', d:.2, ic: 0.0593, krn: {'48': 0.111}, tclass: 'cal'},
{c: 'H', ic: 0.00965, krn: {'48': 0.111}, tclass: 'cal'},
{c: 'I', ic: 0.0738, krn: {'48': 0.0278}, tclass: 'cal'},
{c: 'J', d:.2, ic: 0.185, krn: {'48': 0.167}, tclass: 'cal'},
{c: 'K', ic: 0.0144, krn: {'48': 0.0556}, tclass: 'cal'},
{c: 'L', krn: {'48': 0.139}, tclass: 'cal'},
{c: 'M', krn: {'48': 0.139}, tclass: 'cal'},
{c: 'N', ic: 0.147, krn: {'48': 0.0833}, tclass: 'cal'},
{c: 'O', ic: 0.0278, krn: {'48': 0.111}, tclass: 'cal'},
// 50 - 5F
{c: 'P', ic: 0.0822, krn: {'48': 0.0833}, tclass: 'cal'},
{c: 'Q', d:.2, krn: {'48': 0.111}, tclass: 'cal'},
{c: 'R', krn: {'48': 0.0833}, tclass: 'cal'},
{c: 'S', ic: 0.075, krn: {'48': 0.139}, tclass: 'cal'},
{c: 'T', ic: 0.254, krn: {'48': 0.0278}, tclass: 'cal'},
{c: 'U', ic: 0.0993, krn: {'48': 0.0833}, tclass: 'cal'},
{c: 'V', ic: 0.0822, krn: {'48': 0.0278}, tclass: 'cal'},
{c: 'W', ic: 0.0822, krn: {'48': 0.0833}, tclass: 'cal'},
{c: 'X', ic: 0.146, krn: {'48': 0.139}, tclass: 'cal'},
{c: 'Y', ic: 0.0822, krn: {'48': 0.0833}, tclass: 'cal'},
{c: 'Z', ic: 0.0794, krn: {'48': 0.139}, tclass: 'cal'},
{c: '&#x22C3;', tclass: 'symbol'},
{c: '&#x22C2;', tclass: 'symbol'},
{c: '&#x228E;', tclass: 'symbol'},
{c: '&#x22C0;', tclass: 'symbol'},
{c: '&#x22C1;', tclass: 'symbol'},
// 60 - 6F
{c: '&#x22A2;', tclass: 'symbol'},
{c: '&#x22A3;', tclass: 'symbol'},
{c: '&#x230A;', a:.3, d:.2, tclass: 'arial'},
{c: '&#x230B;', a:.3, d:.2, tclass: 'arial'},
{c: '&#x2308;', a:.3, d:.2, tclass: 'arial'},
{c: '&#x2309;', a:.3, d:.2, tclass: 'arial'},
{c: '{', d:.2, tclass: 'normal'},
{c: '}', d:.2, tclass: 'normal'},
{c: '&#x2329;', a:.3, d:.2, tclass: 'symbol'},
{c: '&#x232A;', a:.3, d:.2, tclass: 'symbol'},
{c: '&#x2223;', d:.1, tclass: 'symbol'},
{c: '&#x2225;', d:.1, tclass: 'symbol'},
{c: '&#x2195;', a:.2, d:0, tclass: 'arrow1a'},
{c: '&#x21D5;', a:.3, d:0, tclass: 'arrow1a'},
{c: '&#x2216;', a:.3, d:.1, tclass: 'symbol'},
{c: '&#x2240;', tclass: 'symbol'},
// 70 - 7F
{c: '<span style="position:relative; top: .8em">&#x221A;</span>', h:.04, d:.8, tclass: 'symbol'},
{c: '&#x2210;', a:.4, tclass: 'symbol'},
{c: '&#x2207;', tclass: 'symbol'},
{c: '<span style="font-size: 85%; left:-.1em; margin-right:-.2em">&#x222B;</span>', a:.4, d:.1, ic: 0.111, tclass: 'lucida'},
{c: '&#x2294;', tclass: 'symbol'},
{c: '&#x2293;', tclass: 'symbol'},
{c: '&#x2291;', tclass: 'symbol'},
{c: '&#x2292;', tclass: 'symbol'},
{c: '&#xA7;', d:.1, tclass: 'normal'},
{c: '&#x2020;', d:.1, tclass: 'normal'},
{c: '&#x2021;', d:.1, tclass: 'normal'},
{c: '&#xB6;', a:.3, d:.1, tclass: 'lucida'},
{c: '&#x2663;', tclass: 'arial'},
{c: '&#x2662;', tclass: 'arial'},
{c: '&#x2661;', tclass: 'arial'},
{c: '&#x2660;', tclass: 'arial'}
],
cmex10: [
// 00 - 0F
{c: '(', h: 0.04, d: 1.16, n: 16, tclass: 'delim1'},
{c: ')', h: 0.04, d: 1.16, n: 17, tclass: 'delim1'},
{c: '[', h: 0.04, d: 1.16, n: 104, tclass: 'delim1'},
{c: ']', h: 0.04, d: 1.16, n: 105, tclass: 'delim1'},
{c: '&#x2308;', h: 0.04, d: 1.16, n: 106, tclass: 'delim1a'},
{c: '&#x2309;', h: 0.04, d: 1.16, n: 107, tclass: 'delim1a'},
{c: '&#x230A;', h: 0.04, d: 1.16, n: 108, tclass: 'delim1a'},
{c: '&#x230B;', h: 0.04, d: 1.16, n: 109, tclass: 'delim1a'},
{c: '<span style="margin-left:-.1em">{</span>', h: 0.04, d: 1.16, n: 110, tclass: 'delim1'},
{c: '<span style="margin-right:-.1em">}</span>', h: 0.04, d: 1.16, n: 111, tclass: 'delim1'},
{c: '&#x2329;', h: 0.04, d: 1.16, n: 68, tclass: 'delim1b'},
{c: '&#x232A;', h: 0.04, d: 1.16, n: 69, tclass: 'delim1b'},
{c: '&#x2223;', h:.7, d:.1, delim: {rep: 12}, tclass: 'symbol'},
{c: '&#x2225;', h:.7, d:.1, delim: {rep: 13}, tclass: 'symbol'},
{c: '/', h: 0.04, d: 1.16, n: 46, tclass: 'delim1a'},
{c: '&#x2216;', h: 0.04, d: 1.16, n: 47, tclass: 'delim1a'},
// 10 - 1F
{c: '(', h: 0.04, d: 1.76, n: 18, tclass: 'delim2'},
{c: ')', h: 0.04, d: 1.76, n: 19, tclass: 'delim2'},
{c: '(', h: 0.04, d: 2.36, n: 32, tclass: 'delim3'},
{c: ')', h: 0.04, d: 2.36, n: 33, tclass: 'delim3'},
{c: '[', h: 0.04, d: 2.36, n: 34, tclass: 'delim3'},
{c: ']', h: 0.04, d: 2.36, n: 35, tclass: 'delim3'},
{c: '&#x2308;', h: 0.04, d: 2.36, n: 36, tclass: 'delim3a'},
{c: '&#x2309;', h: 0.04, d: 2.36, n: 37, tclass: 'delim3a'},
{c: '&#x230A;', h: 0.04, d: 2.36, n: 38, tclass: 'delim3a'},
{c: '&#x230B;', h: 0.04, d: 2.36, n: 39, tclass: 'delim3a'},
{c: '<span style="position:relative; left:-.1em; margin-right:-.1em">{</span>', h: 0.04, d: 2.36, n: 40, tclass: 'delim3'},
{c: '<span style="position:relative; left:-.05em; margin-right:-.1em">}</span>', h: 0.04, d: 2.36, n: 41, tclass: 'delim3'},
{c: '&#x2329;', h: 0.04, d: 2.36, n: 42, tclass: 'delim3b'},
{c: '&#x232A;', h: 0.04, d: 2.36, n: 43, tclass: 'delim3b'},
{c: '/', h: 0.04, d: 2.36, n: 44, tclass: 'delim3a'},
{c: '&#x2216;', h: 0.04, d: 2.36, n: 45, tclass: 'delim3a'},
// 20 - 2F
{c: '(', h: 0.04, d: 2.96, n: 48, tclass: 'delim4'},
{c: ')', h: 0.04, d: 2.96, n: 49, tclass: 'delim4'},
{c: '[', h: 0.04, d: 2.96, n: 50, tclass: 'delim4'},
{c: ']', h: 0.04, d: 2.96, n: 51, tclass: 'delim4'},
{c: '&#x2308;', h: 0.04, d: 2.96, n: 52, tclass: 'delim4a'},
{c: '&#x2309;', h: 0.04, d: 2.96, n: 53, tclass: 'delim4a'},
{c: '&#x230A;', h: 0.04, d: 2.96, n: 54, tclass: 'delim4a'},
{c: '&#x230B;', h: 0.04, d: 2.96, n: 55, tclass: 'delim4a'},
{c: '<span style="position:relative; left:-.1em; margin-right:-.1em">{</span>', h: 0.04, d: 2.96, n: 56, tclass: 'delim4'},
{c: '<span style="position:relative; left:-.1em; margin-right:-.1em">}</span>', h: 0.04, d: 2.96, n: 57, tclass: 'delim4'},
{c: '&#x2329;', h: 0.04, d: 2.96, tclass: 'delim4b'},
{c: '&#x232A;', h: 0.04, d: 2.96, tclass: 'delim4b'},
{c: '/', h: 0.04, d: 2.96, tclass: 'delim4a'},
{c: '&#x2216;', h: 0.04, d: 2.96, tclass: 'delim4a'},
{c: '/', h: 0.04, d: 1.76, n: 30, tclass: 'delim2a'},
{c: '&#x2216;', h: 0.04, d: 1.76, n: 31, tclass: 'delim2a'},
// 30 - 3F
{c: '&#xE6;', h: .8, d: .2, delim: {top: 48, bot: 64, rep: 66}, tclass: 'delimx'},
{c: '&#xF6;', h: .8, d: .2, delim: {top: 49, bot: 65, rep: 67}, tclass: 'delimx'},
{c: '&#xE9;', h: .8, d: .2, delim: {top: 50, bot: 52, rep: 54}, tclass: 'delimx'},
{c: '&#xF9;', h: .8, d: .2, delim: {top: 51, bot: 53, rep: 55}, tclass: 'delimx'},
{c: '&#xEB;', h: .8, d: .2, delim: {bot: 52, rep: 54}, tclass: 'delimx'},
{c: '&#xFB;', h: .8, d: .2, delim: {bot: 53, rep: 55}, tclass: 'delimx'},
{c: '&#xEA;', h: .8, d: .2, delim: {top: 50, rep: 54}, tclass: 'delimx'},
{c: '&#xFA;', h: .8, d: .2, delim: {top: 51, rep: 55}, tclass: 'delimx'},
{c: '&#xEC;', h: .8, d: .2, delim: {top: 56, mid: 60, bot: 58, rep: 62}, tclass: 'delimx'},
{c: '&#xFC;', h: .8, d: .2, delim: {top: 57, mid: 61, bot: 59, rep: 62}, tclass: 'delimx'},
{c: '&#xEE;', h: .8, d: .2, delim: {top: 56, bot: 58, rep: 62}, tclass: 'delimx'},
{c: '&#xFE;', h: .8, d: .2, delim: {top: 57, bot: 59, rep: 62}, tclass: 'delimx'},
{c: '&#xED;', h: .8, d: .2, delim: {rep: 63}, tclass: 'delimx'},
{c: '&#xFD;', h: .8, d: .2, delim: {rep: 119}, tclass: 'delimx'},
{c: '&#xEF;', h: .8, d: .2, delim: {rep: 62}, tclass: 'delimx'},
{c: '<span style="margin:.125em">|</span>', h: .8, d: 0, delim: {top: 120, bot: 121, rep: 63}, tclass: 'normal'},
// 40 - 4F
{c: '&#xE8;', h: .8, d: .2, delim: {top: 56, bot: 59, rep: 62}, tclass: 'delimx'},
{c: '&#xF8;', h: .8, d: .2, delim: {top: 57, bot: 58, rep: 62}, tclass: 'delimx'},
{c: '&#xE7;', h: .8, d: .2, delim: {rep: 66}, tclass: 'delimx'},
{c: '&#xF7;', h: .8, d: .2, delim: {rep: 67}, tclass: 'delimx'},
{c: '&#x2329;', h: 0.04, d: 1.76, n: 28, tclass: 'delim2b'},
{c: '&#x232A;', h: 0.04, d: 1.76, n: 29, tclass: 'delim2b'},
{c: '&#x2294;', h: 0, d: 1, n: 71, tclass: 'bigop1'},
{c: '&#x2294;', h: 0.1, d: 1.5, tclass: 'bigop2'},
{c: '&#x222E;', h: 0, d: 1.11, ic: 0.095, n: 73, tclass: 'bigop1c'},
{c: '&#x222E;', h: 0, d: 2.22, ic: 0.222, tclass: 'bigop2c'},
{c: '&#x2299;', h: 0, d: 1, n: 75, tclass: 'bigop1'},
{c: '&#x2299;', h: 0.1, d: 1.5, tclass: 'bigop2'},
{c: '&#x2295;', h: 0, d: 1, n: 77, tclass: 'bigop1'},
{c: '&#x2295;', h: 0.1, d: 1.5, tclass: 'bigop2'},
{c: '&#x2297;', h: 0, d: 1, n: 79, tclass: 'bigop1'},
{c: '&#x2297;', h: 0.1, d: 1.5, tclass: 'bigop2'},
// 50 - 5F
{c: '&#x2211;', h: 0, d: 1, n: 88, tclass: 'bigop1a'},
{c: '&#x220F;', h: 0, d: 1, n: 89, tclass: 'bigop1a'},
{c: '&#x222B;', h: 0, d: 1.11, ic: 0.095, n: 90, tclass: 'bigop1c'},
{c: '&#x222A;', h: 0, d: 1, n: 91, tclass: 'bigop1b'},
{c: '&#x2229;', h: 0, d: 1, n: 92, tclass: 'bigop1b'},
{c: '&#x228E;', h: 0, d: 1, n: 93, tclass: 'bigop1b'},
{c: '&#x22C0;', h: 0, d: 1, n: 94, tclass: 'bigop1'},
{c: '&#x22C1;', h: 0, d: 1, n: 95, tclass: 'bigop1'},
{c: '&#x2211;', h: 0.1, d: 1.6, tclass: 'bigop2a'},
{c: '&#x220F;', h: 0.1, d: 1.5, tclass: 'bigop2a'},
{c: '&#x222B;', h: 0, d: 2.22, ic: 0.222, tclass: 'bigop2c'},
{c: '&#x222A;', h: 0.1, d: 1.5, tclass: 'bigop2b'},
{c: '&#x2229;', h: 0.1, d: 1.5, tclass: 'bigop2b'},
{c: '&#x228E;', h: 0.1, d: 1.5, tclass: 'bigop2b'},
{c: '&#x22C0;', h: 0.1, d: 1.5, tclass: 'bigop2'},
{c: '&#x22C1;', h: 0.1, d: 1.5, tclass: 'bigop2'},
// 60 - 6F
{c: '&#x2210;', h: 0, d: 1, n: 97, tclass: 'bigop1a'},
{c: '&#x2210;', h: 0.1, d: 1.5, tclass: 'bigop2a'},
{c: '&#xFE3F;', h: 0.722, w: .65, n: 99, tclass: 'wide1'},
{c: '&#xFE3F;', h: 0.85, w: 1.1, n: 100, tclass: 'wide2'},
{c: '&#xFE3F;', h: 0.99, w: 1.65, tclass: 'wide3'},
{c: '~', h: 0.722, w: .5, n: 102, tclass: 'wide1a'},
{c: '~', h: 0.8, w: .8, n: 103, tclass: 'wide2a'},
{c: '~', h: 0.99, w: 1.3, tclass: 'wide3a'},
{c: '[', h: 0.04, d: 1.76, n: 20, tclass: 'delim2'},
{c: ']', h: 0.04, d: 1.76, n: 21, tclass: 'delim2'},
{c: '&#x2308;', h: 0.04, d: 1.76, n: 22, tclass: 'delim2a'},
{c: '&#x2309;', h: 0.04, d: 1.76, n: 23, tclass: 'delim2a'},
{c: '&#x230A;', h: 0.04, d: 1.76, n: 24, tclass: 'delim2a'},
{c: '&#x230B;', h: 0.04, d: 1.76, n: 25, tclass: 'delim2a'},
{c: '<span style="position:relative; left:-.1em; margin-right:-.1em">{</span>', h: 0.04, d: 1.76, n: 26, tclass: 'delim2'},
{c: '<span style="position:relative; margin-right:-.1em; left:-.05em">}</span>', h: 0.04, d: 1.76, n: 27, tclass: 'delim2'},
// 70 - 7F
{c: '<span style="font-size: 150%; position:relative; top:.8em">&#x221A;</span>', h: 0.04, d: 1.16, n: 113, tclass: 'root'},
{c: '<span style="font-size: 220%; position:relative; top:.8em">&#x221A;</span>', h: 0.04, d: 1.76, n: 114, tclass: 'root'},
{c: '<span style="font-size: 310%; position:relative; top:.8em; margin-right:-.01em">&#x221A;</span>', h: 0.06, d: 2.36, n: 115, tclass: 'root'},
{c: '<span style="font-size: 400%; position:relative; top:.8em; margin-right:-.025em">&#x221A;</span>', h: 0.08, d: 2.96, n: 116, tclass: 'root'},
{c: '<span style="font-size: 490%; position:relative; top:.8em; margin-right:-.03em">&#x221A;</span>', h: 0.1, d: 3.75, n: 117, tclass: 'root'},
{c: '<span style="font-size: 580%; position:relative; top:.775em; margin-right:-.04em">&#x221A;</span>', h: .12, d: 4.5, n: 118, tclass: 'root'},
{c: '<span style="font-size: 750%; position:relative; top:.775em;margin-right:-.04em">&#x221A;</span>', h: .14, d: 5.7, tclass: 'root'},
{c: '<span style="margin-left:.02em">|</span><span style="margin-left:.08em; margin-right:.125em">|</span>', h:.8, d:0, delim: {top: 126, bot: 127, rep: 119}, tclass: 'normal'},
{c: '&#x2191;', h:.7, d:0, delim: {top: 120, rep: 63}, tclass: 'arrow1a'},
{c: '&#x2193;', h:.65, d:0, delim: {bot: 121, rep: 63}, tclass: 'arrow1a'},
{c: '<span style="margin-left:-.1em"></span><span style="position:relative; top:.55em; margin-right:-.3em">&#x25DC;</span>', h: 0.05, tclass: 'symbol'},
{c: '<span style="margin-left:-.3em"></span><span style="position:relative; top:.55em; margin-right:-.1em">&#x25DD;</span>', h: 0.05, tclass: 'symbol'},
{c: '<span style="margin-left:-.1em"></span><span style="position:relative; top:.15em; margin-right:-.3em">&#x25DF;</span>', h: 0.05, tclass: 'symbol'},
{c: '<span style="margin-left:-.3em"></span><span style="position:relative; top:.15em; margin-right:-.1em">&#x25DE;</span>', h: 0.05, tclass: 'symbol'},
{c: '&#x21D1;', h: .7, d:0, delim: {top: 126, rep: 119}, tclass: 'arrow1a'},
{c: '&#x21D3;', h: .7, d:0, delim: {bot: 127, rep: 119}, tclass: 'arrow1a'}
],
cmti10: [
// 00 - 0F
{c: '&Gamma;', ic: 0.133, tclass: 'igreek'},
{c: '&Delta;', tclass: 'igreek'},
{c: '&Theta;', ic: 0.094, tclass: 'igreek'},
{c: '&Lambda;', tclass: 'igreek'},
{c: '&Xi;', ic: 0.153, tclass: 'igreek'},
{c: '&Pi;', ic: 0.164, tclass: 'igreek'},
{c: '&Sigma;', ic: 0.12, tclass: 'igreek'},
{c: '&Upsilon;', ic: 0.111, tclass: 'igreek'},
{c: '&Phi;', ic: 0.0599, tclass: 'igreek'},
{c: '&Psi;', ic: 0.111, tclass: 'igreek'},
{c: '&Omega;', ic: 0.103, tclass: 'igreek'},
{c: 'ff', ic: 0.212, krn: {'39': 0.104, '63': 0.104, '33': 0.104, '41': 0.104, '93': 0.104}, lig: {'105': 14, '108': 15}, tclass: 'italic'},
{c: 'fi', ic: 0.103, tclass: 'italic'},
{c: 'fl', ic: 0.103, tclass: 'italic'},
{c: 'ffi', ic: 0.103, tclass: 'italic'},
{c: 'ffl', ic: 0.103, tclass: 'italic'},
// 10 - 1F
{c: '&#x131;', a:0, ic: 0.0767, tclass: 'italic'},
{c: 'j', d:.2, ic: 0.0374, tclass: 'italic'},
{c: '&#x2CB;', tclass: 'iaccent'},
{c: '&#x2CA;', ic: 0.0969, tclass: 'iaccent'},
{c: '&#x2C7;', ic: 0.083, tclass: 'iaccent'},
{c: '&#x2D8;', ic: 0.108, tclass: 'iaccent'},
{c: '&#x2C9;', ic: 0.103, tclass: 'iaccent'},
{c: '&#x2DA;', tclass: 'iaccent'},
{c: '?', d: 0.17, w: 0.46, tclass: 'italic'},
{c: '&#xDF;', ic: 0.105, tclass: 'italic'},
{c: '&#xE6;', a:0, ic: 0.0751, tclass: 'italic'},
{c: '&#x153;', a:0, ic: 0.0751, tclass: 'italic'},
{c: '&#xF8;', ic: 0.0919, tclass: 'italic'},
{c: '&#xC6;', ic: 0.12, tclass: 'italic'},
{c: '&#x152;', ic: 0.12, tclass: 'italic'},
{c: '&#xD8;', ic: 0.094, tclass: 'italic'},
// 20 - 2F
{c: '?', krn: {'108': -0.256, '76': -0.321}, tclass: 'italic'},
{c: '!', ic: 0.124, lig: {'96': 60}, tclass: 'italic'},
{c: '&#x201D;', ic: 0.0696, tclass: 'italic'},
{c: '#', ic: 0.0662, tclass: 'italic'},
{c: '$', tclass: 'italic'},
{c: '%', ic: 0.136, tclass: 'italic'},
{c: '&amp;', ic: 0.0969, tclass: 'italic'},
{c: '&#x2019;', ic: 0.124, krn: {'63': 0.102, '33': 0.102}, lig: {'39': 34}, tclass: 'italic'},
{c: '(', d:.2, ic: 0.162, tclass: 'italic'},
{c: ')', d:.2, ic: 0.0369, tclass: 'italic'},
{c: '*', ic: 0.149, tclass: 'italic'},
{c: '+', a:.1, ic: 0.0369, tclass: 'italic'},
{c: ',', a:-.3, d:.2, w: 0.278, tclass: 'italic'},
{c: '-', a:0, ic: 0.0283, lig: {'45': 123}, tclass: 'italic'},
{c: '.', a:-.25, tclass: 'italic'},
{c: '/', ic: 0.162, tclass: 'italic'},
// 30 - 3F
{c: '0', ic: 0.136, tclass: 'italic'},
{c: '1', ic: 0.136, tclass: 'italic'},
{c: '2', ic: 0.136, tclass: 'italic'},
{c: '3', ic: 0.136, tclass: 'italic'},
{c: '4', ic: 0.136, tclass: 'italic'},
{c: '5', ic: 0.136, tclass: 'italic'},
{c: '6', ic: 0.136, tclass: 'italic'},
{c: '7', ic: 0.136, tclass: 'italic'},
{c: '8', ic: 0.136, tclass: 'italic'},
{c: '9', ic: 0.136, tclass: 'italic'},
{c: ':', ic: 0.0582, tclass: 'italic'},
{c: ';', ic: 0.0582, tclass: 'italic'},
{c: '&#xA1;', ic: 0.0756, tclass: 'italic'},
{c: '=', a:0, d:-.1, ic: 0.0662, tclass: 'italic'},
{c: '&#xBF;', tclass: 'italic'},
{c: '?', ic: 0.122, lig: {'96': 62}, tclass: 'italic'},
// 40 - 4F
{c: '@', ic: 0.096, tclass: 'italic'},
{c: 'A', krn: {'110': -0.0256, '108': -0.0256, '114': -0.0256, '117': -0.0256, '109': -0.0256, '116': -0.0256, '105': -0.0256, '67': -0.0256, '79': -0.0256, '71': -0.0256, '104': -0.0256, '98': -0.0256, '85': -0.0256, '107': -0.0256, '118': -0.0256, '119': -0.0256, '81': -0.0256, '84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'},
{c: 'B', ic: 0.103, tclass: 'italic'},
{c: 'C', ic: 0.145, tclass: 'italic'},
{c: 'D', ic: 0.094, krn: {'88': -0.0256, '87': -0.0256, '65': -0.0256, '86': -0.0256, '89': -0.0256}, tclass: 'italic'},
{c: 'E', ic: 0.12, tclass: 'italic'},
{c: 'F', ic: 0.133, krn: {'111': -0.0767, '101': -0.0767, '117': -0.0767, '114': -0.0767, '97': -0.0767, '65': -0.102, '79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}, tclass: 'italic'},
{c: 'G', ic: 0.0872, tclass: 'italic'},
{c: 'H', ic: 0.164, tclass: 'italic'},
{c: 'I', ic: 0.158, tclass: 'italic'},
{c: 'J', ic: 0.14, tclass: 'italic'},
{c: 'K', ic: 0.145, krn: {'79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}, tclass: 'italic'},
{c: 'L', krn: {'84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'},
{c: 'M', ic: 0.164, tclass: 'italic'},
{c: 'N', ic: 0.164, tclass: 'italic'},
{c: 'O', ic: 0.094, krn: {'88': -0.0256, '87': -0.0256, '65': -0.0256, '86': -0.0256, '89': -0.0256}, tclass: 'italic'},
// 50 - 5F
{c: 'P', ic: 0.103, krn: {'65': -0.0767}, tclass: 'italic'},
{c: 'Q', d:.2, ic: 0.094, tclass: 'italic'},
{c: 'R', ic: 0.0387, krn: {'110': -0.0256, '108': -0.0256, '114': -0.0256, '117': -0.0256, '109': -0.0256, '116': -0.0256, '105': -0.0256, '67': -0.0256, '79': -0.0256, '71': -0.0256, '104': -0.0256, '98': -0.0256, '85': -0.0256, '107': -0.0256, '118': -0.0256, '119': -0.0256, '81': -0.0256, '84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'},
{c: 'S', ic: 0.12, tclass: 'italic'},
{c: 'T', ic: 0.133, krn: {'121': -0.0767, '101': -0.0767, '111': -0.0767, '114': -0.0767, '97': -0.0767, '117': -0.0767, '65': -0.0767}, tclass: 'italic'},
{c: 'U', ic: 0.164, tclass: 'italic'},
{c: 'V', ic: 0.184, krn: {'111': -0.0767, '101': -0.0767, '117': -0.0767, '114': -0.0767, '97': -0.0767, '65': -0.102, '79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}, tclass: 'italic'},
{c: 'W', ic: 0.184, krn: {'65': -0.0767}, tclass: 'italic'},
{c: 'X', ic: 0.158, krn: {'79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}, tclass: 'italic'},
{c: 'Y', ic: 0.194, krn: {'101': -0.0767, '111': -0.0767, '114': -0.0767, '97': -0.0767, '117': -0.0767, '65': -0.0767}, tclass: 'italic'},
{c: 'Z', ic: 0.145, tclass: 'italic'},
{c: '[', d:.1, ic: 0.188, tclass: 'italic'},
{c: '&#x201C;', ic: 0.169, tclass: 'italic'},
{c: ']', d:.1, ic: 0.105, tclass: 'italic'},
{c: '&#x2C6;', ic: 0.0665, tclass: 'iaccent'},
{c: '&#x2D9;', ic: 0.118, tclass: 'iaccent'},
// 60 - 6F
{c: '&#x2018;', ic: 0.124, lig: {'96': 92}, tclass: 'italic'},
{c: 'a', a:0, ic: 0.0767, tclass: 'italic'},
{c: 'b', ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'},
{c: 'c', a:0, ic: 0.0565, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'},
{c: 'd', ic: 0.103, krn: {'108': 0.0511}, tclass: 'italic'},
{c: 'e', a:0, ic: 0.0751, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'},
{c: 'f', ic: 0.212, krn: {'39': 0.104, '63': 0.104, '33': 0.104, '41': 0.104, '93': 0.104}, lig: {'105': 12, '102': 11, '108': 13}, tclass: 'italic'},
{c: 'g', a:0, d:.2, ic: 0.0885, tclass: 'italic'},
{c: 'h', ic: 0.0767, tclass: 'italic'},
{c: 'i', ic: 0.102, tclass: 'italic'},
{c: 'j', d:.2, ic: 0.145, tclass: 'italic'},
{c: 'k', ic: 0.108, tclass: 'italic'},
{c: 'l', ic: 0.103, krn: {'108': 0.0511}, tclass: 'italic'},
{c: 'm', a:0, ic: 0.0767, tclass: 'italic'},
{c: 'n', a:0, ic: 0.0767, krn: {'39': -0.102}, tclass: 'italic'},
{c: 'o', a:0, ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'},
// 70 - 7F
{c: 'p', a:0, d:.2, ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'},
{c: 'q', a:0, d:.2, ic: 0.0885, tclass: 'italic'},
{c: 'r', a:0, ic: 0.108, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'},
{c: 's', a:0, ic: 0.0821, tclass: 'italic'},
{c: 't', ic: 0.0949, tclass: 'italic'},
{c: 'u', a:0, ic: 0.0767, tclass: 'italic'},
{c: 'v', a:0, ic: 0.108, tclass: 'italic'},
{c: 'w', a:0, ic: 0.108, krn: {'108': 0.0511}, tclass: 'italic'},
{c: 'x', a:0, ic: 0.12, tclass: 'italic'},
{c: 'y', a:0, d:.2, ic: 0.0885, tclass: 'italic'},
{c: 'z', a:0, ic: 0.123, tclass: 'italic'},
{c: '&#x2013;', a:.1, ic: 0.0921, lig: {'45': 124}, tclass: 'italic'},
{c: '&#x2014;', a:.1, ic: 0.0921, tclass: 'italic'},
{c: '&#x2DD;', ic: 0.122, tclass: 'iaccent'},
{c: '&#x2DC;', ic: 0.116, tclass: 'iaccent'},
{c: '&#xA8;', tclass: 'iaccent'}
],
cmbx10: [
// 00 - 0F
{c: '&Gamma;', tclass: 'bgreek'},
{c: '&Delta;', tclass: 'bgreek'},
{c: '&Theta;', tclass: 'bgreek'},
{c: '&Lambda;', tclass: 'bgreek'},
{c: '&Xi;', tclass: 'bgreek'},
{c: '&Pi;', tclass: 'bgreek'},
{c: '&Sigma;', tclass: 'bgreek'},
{c: '&Upsilon;', tclass: 'bgreek'},
{c: '&Phi;', tclass: 'bgreek'},
{c: '&Psi;', tclass: 'bgreek'},
{c: '&Omega;', tclass: 'bgreek'},
{c: 'ff', ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 14, '108': 15}, tclass: 'bold'},
{c: 'fi', tclass: 'bold'},
{c: 'fl', tclass: 'bold'},
{c: 'ffi', tclass: 'bold'},
{c: 'ffl', tclass: 'bold'},
// 10 - 1F
{c: '&#x131;', a:0, tclass: 'bold'},
{c: 'j', d:.2, tclass: 'bold'},
{c: '&#x2CB;', tclass: 'baccent'},
{c: '&#x2CA;', tclass: 'baccent'},
{c: '&#x2C7;', tclass: 'baccent'},
{c: '&#x2D8;', tclass: 'baccent'},
{c: '&#x2C9;', tclass: 'baccent'},
{c: '&#x2DA;', tclass: 'baccent'},
{c: '?', tclass: 'bold'},
{c: '&#xDF;', tclass: 'bold'},
{c: '&#xE6;', a:0, tclass: 'bold'},
{c: '&#x153;', a:0, tclass: 'bold'},
{c: '&#xF8;', tclass: 'bold'},
{c: '&#xC6;', tclass: 'bold'},
{c: '&#x152;', tclass: 'bold'},
{c: '&#xD8;', tclass: 'bold'},
// 20 - 2F
{c: '?', krn: {'108': -0.278, '76': -0.319}, tclass: 'bold'},
{c: '!', lig: {'96': 60}, tclass: 'bold'},
{c: '&#x201D;', tclass: 'bold'},
{c: '#', tclass: 'bold'},
{c: '$', tclass: 'bold'},
{c: '%', tclass: 'bold'},
{c: '&amp;', tclass: 'bold'},
{c: '&#x2019;', krn: {'63': 0.111, '33': 0.111}, lig: {'39': 34}, tclass: 'bold'},
{c: '(', d:.2, tclass: 'bold'},
{c: ')', d:.2, tclass: 'bold'},
{c: '*', tclass: 'bold'},
{c: '+', a:.1, tclass: 'bold'},
{c: ',', a:-.3, d:.2, w: 0.278, tclass: 'bold'},
{c: '-', a:0, lig: {'45': 123}, tclass: 'bold'},
{c: '.', a:-.25, tclass: 'bold'},
{c: '/', tclass: 'bold'},
// 30 - 3F
{c: '0', tclass: 'bold'},
{c: '1', tclass: 'bold'},
{c: '2', tclass: 'bold'},
{c: '3', tclass: 'bold'},
{c: '4', tclass: 'bold'},
{c: '5', tclass: 'bold'},
{c: '6', tclass: 'bold'},
{c: '7', tclass: 'bold'},
{c: '8', tclass: 'bold'},
{c: '9', tclass: 'bold'},
{c: ':', tclass: 'bold'},
{c: ';', tclass: 'bold'},
{c: '&#xA1;', tclass: 'bold'},
{c: '=', a:0, d:-.1, tclass: 'bold'},
{c: '&#xBF;', tclass: 'bold'},
{c: '?', lig: {'96': 62}, tclass: 'bold'},
// 40 - 4F
{c: '@', tclass: 'bold'},
{c: 'A', krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}, tclass: 'bold'},
{c: 'B', tclass: 'bold'},
{c: 'C', tclass: 'bold'},
{c: 'D', krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}, tclass: 'bold'},
{c: 'E', tclass: 'bold'},
{c: 'F', krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'bold'},
{c: 'G', tclass: 'bold'},
{c: 'H', tclass: 'bold'},
{c: 'I', krn: {'73': 0.0278}, tclass: 'bold'},
{c: 'J', tclass: 'bold'},
{c: 'K', krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'bold'},
{c: 'L', krn: {'84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}, tclass: 'bold'},
{c: 'M', tclass: 'bold'},
{c: 'N', tclass: 'bold'},
{c: 'O', krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}, tclass: 'bold'},
// 50 - 5F
{c: 'P', krn: {'65': -0.0833, '111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}, tclass: 'bold'},
{c: 'Q', d:.2, tclass: 'bold'},
{c: 'R', krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}, tclass: 'bold'},
{c: 'S', tclass: 'bold'},
{c: 'T', krn: {'121': -0.0278, '101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}, tclass: 'bold'},
{c: 'U', tclass: 'bold'},
{c: 'V', ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'bold'},
{c: 'W', ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'bold'},
{c: 'X', krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'bold'},
{c: 'Y', ic: 0.025, krn: {'101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}, tclass: 'bold'},
{c: 'Z', tclass: 'bold'},
{c: '[', d:.1, tclass: 'bold'},
{c: '&#x201C;', tclass: 'bold'},
{c: ']', d:.1, tclass: 'bold'},
{c: '&#x2C6;', tclass: 'baccent'},
{c: '&#x2D9;', tclass: 'baccent'},
// 60 - 6F
{c: '&#x2018;', lig: {'96': 92}, tclass: 'bold'},
{c: 'a', a:0, krn: {'118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'bold'},
{c: 'b', krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'bold'},
{c: 'c', a:0, krn: {'104': -0.0278, '107': -0.0278}, tclass: 'bold'},
{c: 'd', tclass: 'bold'},
{c: 'e', a:0, tclass: 'bold'},
{c: 'f', ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 12, '102': 11, '108': 13}, tclass: 'bold'},
{c: 'g', a:0, d:.2, ic: 0.0139, krn: {'106': 0.0278}, tclass: 'bold'},
{c: 'h', krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}, tclass: 'bold'},
{c: 'i', tclass: 'bold'},
{c: 'j', d:.2, tclass: 'bold'},
{c: 'k', krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}, tclass: 'bold'},
{c: 'l', tclass: 'bold'},
{c: 'm', a:0, krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}, tclass: 'bold'},
{c: 'n', a:0, krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}, tclass: 'bold'},
{c: 'o', a:0, krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'bold'},
// 70 - 7F
{c: 'p', a:0, d:.2, krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'bold'},
{c: 'q', a:0, d:.2, tclass: 'bold'},
{c: 'r', a:0, tclass: 'bold'},
{c: 's', a:0, tclass: 'bold'},
{c: 't', krn: {'121': -0.0278, '119': -0.0278}, tclass: 'bold'},
{c: 'u', a:0, krn: {'119': -0.0278}, tclass: 'bold'},
{c: 'v', a:0, ic: 0.0139, krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}, tclass: 'bold'},
{c: 'w', a:0, ic: 0.0139, krn: {'101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}, tclass: 'bold'},
{c: 'x', a:0, tclass: 'bold'},
{c: 'y', a:0, d:.2, ic: 0.0139, krn: {'111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}, tclass: 'bold'},
{c: 'z', a:0, tclass: 'bold'},
{c: '&#x2013;', a:.1, ic: 0.0278, lig: {'45': 124}, tclass: 'bold'},
{c: '&#x2014;', a:.1, ic: 0.0278, tclass: 'bold'},
{c: '&#x2DD;', tclass: 'baccent'},
{c: '&#x2DC;', tclass: 'baccent'},
{c: '&#xA8;', tclass: 'baccent'}
]
});
jsMath.Setup.Styles({
'.typeset .cmr10': "font-family: serif",
'.typeset .italic': "font-style: italic",
'.typeset .bold': "font-weight: bold",
'.typeset .lucida': "font-family: 'lucida sans unicode'",
'.typeset .arial': "font-family: 'Arial unicode MS'",
'.typeset .cal': "font-family: 'Script MT', 'Script MT Bold', cursive",
'.typeset .arrows': "font-family: 'Arial unicode MS'",
'.typeset .arrow1': "font-family: 'Arial unicode MS'",
'.typeset .arrow1a': "font-family: 'Arial unicode MS'; position:relative; top:.05em;left:-.15em; margin-right:-.15em",
'.typeset .arrow2': "font-family: 'Arial unicode MS'; position:relative; top:-.1em;",
'.typeset .arrow3': "font-family: 'Arial unicode MS'; margin:.1em",
'.typeset .symbol': "font-family: 'Arial unicode MS'",
'.typeset .symbol2': "font-family: 'Arial unicode MS'",
'.typeset .delim1': "font-family: 'Times New Roman'; font-size: 133%; position:relative; top:.7em",
'.typeset .delim1a': "font-family: 'Lucida sans unicode'; font-size: 133%; position:relative; top:.8em",
'.typeset .delim1b': "font-family: 'Arial unicode MS'; font-size: 133%; position:relative; top:.8em",
'.typeset .delim2': "font-family: 'Times New Roman'; font-size: 180%; position:relative; top:.75em",
'.typeset .delim2a': "font-family: 'Lucida sans unicode'; font-size: 180%; position:relative; top:.8em",
'.typeset .delim2b': "font-family: 'Arial unicode MS'; font-size: 180%; position:relative; top:.8em",
'.typeset .delim3': "font-family: 'Times New Roman'; font-size: 250%; position:relative; top:.725em",
'.typeset .delim3a': "font-family: 'Lucida sans unicode'; font-size: 250%; position:relative; top:.775em",
'.typeset .delim3b': "font-family: 'Arial unicode MS'; font-size: 250%; position:relative; top:.8em",
'.typeset .delim4': "font-family: 'Times New Roman'; font-size: 325%; position:relative; top:.7em",
'.typeset .delim4a': "font-family: 'Lucida sans unicode'; font-size: 325%; position:relative; top:.775em",
'.typeset .delim4b': "font-family: 'Arial unicode MS'; font-size: 325%; position:relative; top:.8em",
'.typeset .delimx': "font-family: Symbol; position:relative; top:.2em",
'.typeset .greek': "font-family: 'Times New Roman'",
'.typeset .igreek': "font-family: 'Times New Roman'; font-style:italic",
'.typeset .bgreek': "font-family: 'Times New Roman'; font-weight:bold",
'.typeset .bigop1': "font-family: 'Arial unicode MS'; font-size: 130%; position: relative; top: .7em; margin:-.05em",
'.typeset .bigop1a': "font-family: 'Arial unicode MS'; font-size: 110%; position: relative; top: .85em;",
'.typeset .bigop1b': "font-family: 'Arial unicode MS'; font-size: 180%; position: relative; top: .6em",
'.typeset .bigop1c': "font-family: 'Arial unicode MS'; font-size: 85%; position: relative; top: 1em",
'.typeset .bigop2': "font-family: 'Arial unicode MS'; font-size: 230%; position: relative; top: .6em; margin:-.05em",
'.typeset .bigop2a': "font-family: 'Arial unicode MS'; font-size: 185%; position: relative; top: .75em",
'.typeset .bigop2b': "font-family: 'Arial unicode MS'; font-size: 275%; position: relative; top: .55em",
'.typeset .bigop2c': "font-family: 'Arial unicode MS'; font-size: 185%; position: relative; top: 1em; margin-right:-.1em",
'.typeset .wide1': "font-size: 67%; position: relative; top:-.5em;",
'.typeset .wide2': "font-size: 110%; position: relative; top:-.2em;",
'.typeset .wide3': "font-size: 175%;",
'.typeset .wide1a': "font-family: 'Times New Roman'; font-size: 75%; position: relative; top:-.5em",
'.typeset .wide2a': "font-family: 'Times New Roman'; font-size: 133%; position: relative; top:-.2em",
'.typeset .wide3a': "font-family: 'Times New Roman'; font-size: 200%; position: relative; top:-.1em",
'.typeset .root': "font-family: 'Arial unicode MS'; margin-right:-.075em",
'.typeset .accent': "font-family: 'Arial unicode MS'; position:relative; top:.05em; left:.15em",
'.typeset .iaccent': "font-family: 'Arial unicode MS'; position:relative; top:.05em; left:.15em; font-style:italic",
'.typeset .baccent': "font-family: 'Arial unicode MS'; position:relative; top:.05em; left:.15em; font-weight:bold"
});
//
// adjust for Mozilla
//
if (jsMath.browser == 'Mozilla') {
jsMath.Update.TeXfonts({
cmex10: {
'48': {c: '&#xF8EB;'},
'49': {c: '&#xF8F6;'},
'50': {c: '&#xF8EE;'},
'51': {c: '&#xF8F9;'},
'52': {c: '&#xF8F0;'},
'53': {c: '&#xF8FB;'},
'54': {c: '&#xF8EF;'},
'55': {c: '&#xF8FA;'},
'56': {c: '&#xF8F1;'},
'57': {c: '&#xF8FC;'},
'58': {c: '&#xF8F3;'},
'59': {c: '&#xF8FE;'},
'60': {c: '&#xF8F2;'},
'61': {c: '&#xF8FD;'},
'62': {c: '&#xF8F4;'},
'64': {c: '&#xF8ED;'},
'65': {c: '&#xF8F8;'},
'66': {c: '&#xF8EC;'},
'67': {c: '&#xF8F7;'}
}
});
jsMath.Setup.Styles({
'.typeset .accent': 'font-family: Arial unicode MS; position:relative; top:.05em; left:.05em'
});
}
//
// adjust for MSIE
//
if (jsMath.browser == "MSIE") {
jsMath.Browser.msieFontBug = 1;
jsMath.Update.TeXfonts({
cmex10: {
'63': {c: '<span style="position:relative; left:.125em; margin-right:.125em">|</span>'},
'119': {c: '<span style="position:relative; left:.02em; margin-right=.08em">|</span><span style="margin-right:.125em">|</span>'}
}
});
}
/*
* No access to TeX "not" character, so fake this
* Also ajust the bowtie spacing
*/
jsMath.Macro('not','\\mathrel{\\rlap{\\kern 3mu/}}');
jsMath.Macro('bowtie','\\mathrel\\triangleright\\kern-6mu\\mathrel\\triangleleft');
jsMath.Box.defaultH = 0.8;

View File

@ -0,0 +1,415 @@
/*
* jsMath-fallback-symbols.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file makes changes needed to use image fonts for symbols
* but standard native fonts for letters and numbers.
*
* ---------------------------------------------------------------------
*
* Copyright 2004-2006 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
jsMath.Add(jsMath.Img,{
UpdateTeXFonts: function (change) {
for (var font in change) {
for (var code in change[font]) {
jsMath.TeX[font][code] = change[font][code];
jsMath.TeX[font][code].tclass = 'i' + font;
}
}
}
});
jsMath.Img.UpdateTeXFonts({
cmr10: {
'33': {c: '!', lig: {'96': 60}},
'35': {c: '#'},
'36': {c: '$'},
'37': {c: '%'},
'38': {c: '&amp;'},
'40': {c: '(', d:.2},
'41': {c: ')', d:.2},
'42': {c: '*', d:-.3},
'43': {c: '+', a:.1},
'44': {c: ',', a:-.3},
'45': {c: '-', a:0, lig: {'45': 123}},
'46': {c: '.', a:-.25},
'47': {c: '/'},
'48': {c: '0'},
'49': {c: '1'},
'50': {c: '2'},
'51': {c: '3'},
'52': {c: '4'},
'53': {c: '5'},
'54': {c: '6'},
'55': {c: '7'},
'56': {c: '8'},
'57': {c: '9'},
'58': {c: ':'},
'59': {c: ';'},
'61': {c: '=', a:0, d:-.1},
'63': {c: '?', lig: {'96': 62}},
'64': {c: '@'},
'65': {c: 'A', krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}},
'66': {c: 'B'},
'67': {c: 'C'},
'68': {c: 'D', krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}},
'69': {c: 'E'},
'70': {c: 'F', krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}},
'71': {c: 'G'},
'72': {c: 'H'},
'73': {c: 'I', krn: {'73': 0.0278}},
'74': {c: 'J'},
'75': {c: 'K', krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}},
'76': {c: 'L', krn: {'84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}},
'77': {c: 'M'},
'78': {c: 'N'},
'79': {c: 'O', krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}},
'80': {c: 'P', krn: {'65': -0.0833, '111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}},
'81': {c: 'Q', d: 1},
'82': {c: 'R', krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}},
'83': {c: 'S'},
'84': {c: 'T', krn: {'121': -0.0278, '101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}},
'85': {c: 'U'},
'86': {c: 'V', ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}},
'87': {c: 'W', ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}},
'88': {c: 'X', krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}},
'89': {c: 'Y', ic: 0.025, krn: {'101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}},
'90': {c: 'Z'},
'91': {c: '[', d:.1},
'93': {c: ']', d:.1},
'97': {c: 'a', a:0, krn: {'118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}},
'98': {c: 'b', krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}},
'99': {c: 'c', a:0, krn: {'104': -0.0278, '107': -0.0278}},
'100': {c: 'd'},
'101': {c: 'e', a:0},
'102': {c: 'f', ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 12, '102': 11, '108': 13}},
'103': {c: 'g', a:0, d:.2, ic: 0.0139, krn: {'106': 0.0278}},
'104': {c: 'h', krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}},
'105': {c: 'i'},
'106': {c: 'j', d:1},
'107': {c: 'k', krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}},
'108': {c: 'l'},
'109': {c: 'm', a:0, krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}},
'110': {c: 'n', a:0, krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}},
'111': {c: 'o', a:0, krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}},
'112': {c: 'p', a:0, d:.2, krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}},
'113': {c: 'q', a:0, d:1},
'114': {c: 'r', a:0},
'115': {c: 's', a:0},
'116': {c: 't', krn: {'121': -0.0278, '119': -0.0278}},
'117': {c: 'u', a:0, krn: {'119': -0.0278}},
'118': {c: 'v', a:0, ic: 0.0139, krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}},
'119': {c: 'w', a:0, ic: 0.0139, krn: {'101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}},
'120': {c: 'x', a:0},
'121': {c: 'y', a:0, d:.2, ic: 0.0139, krn: {'111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}},
'122': {c: 'z', a:0}
},
cmmi10: {
'65': {c: 'A', krn: {'127': 0.139}},
'66': {c: 'B', ic: 0.0502, krn: {'127': 0.0833}},
'67': {c: 'C', ic: 0.0715, krn: {'61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}},
'68': {c: 'D', ic: 0.0278, krn: {'127': 0.0556}},
'69': {c: 'E', ic: 0.0576, krn: {'127': 0.0833}},
'70': {c: 'F', ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0833}},
'71': {c: 'G', krn: {'127': 0.0833}},
'72': {c: 'H', ic: 0.0812, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}},
'73': {c: 'I', ic: 0.0785, krn: {'127': 0.111}},
'74': {c: 'J', ic: 0.0962, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.167}},
'75': {c: 'K', ic: 0.0715, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}},
'76': {c: 'L', krn: {'127': 0.0278}},
'77': {c: 'M', ic: 0.109, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}},
'78': {c: 'N', ic: 0.109, krn: {'61': -0.0833, '61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}},
'79': {c: 'O', ic: 0.0278, krn: {'127': 0.0833}},
'80': {c: 'P', ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0833}},
'81': {c: 'Q', d:.2, krn: {'127': 0.0833}},
'82': {c: 'R', ic: 0.00773, krn: {'127': 0.0833}},
'83': {c: 'S', ic: 0.0576, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}},
'84': {c: 'T', ic: 0.139, krn: {'61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}},
'85': {c: 'U', ic: 0.109, krn: {'59': -0.111, '58': -0.111, '61': -0.0556, '127': 0.0278}},
'86': {c: 'V', ic: 0.222, krn: {'59': -0.167, '58': -0.167, '61': -0.111}},
'87': {c: 'W', ic: 0.139, krn: {'59': -0.167, '58': -0.167, '61': -0.111}},
'88': {c: 'X', ic: 0.0785, krn: {'61': -0.0833, '61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}},
'89': {c: 'Y', ic: 0.222, krn: {'59': -0.167, '58': -0.167, '61': -0.111}},
'90': {c: 'Z', ic: 0.0715, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}},
'97': {c: 'a', a:0},
'98': {c: 'b'},
'99': {c: 'c', a:0, krn: {'127': 0.0556}},
'100': {c: 'd', krn: {'89': 0.0556, '90': -0.0556, '106': -0.111, '102': -0.167, '127': 0.167}},
'101': {c: 'e', a:0, krn: {'127': 0.0556}},
'102': {c: 'f', d:.2, ic: 0.108, krn: {'59': -0.0556, '58': -0.0556, '127': 0.167}},
'103': {c: 'g', a:0, d:.2, ic: 0.0359, krn: {'127': 0.0278}},
'104': {c: 'h', krn: {'127': -0.0278}},
'105': {c: 'i'},
'106': {c: 'j', d:.2, ic: 0.0572, krn: {'59': -0.0556, '58': -0.0556}},
'107': {c: 'k', ic: 0.0315},
'108': {c: 'l', ic: 0.0197, krn: {'127': 0.0833}},
'109': {c: 'm', a:0},
'110': {c: 'n', a:0},
'111': {c: 'o', a:0, krn: {'127': 0.0556}},
'112': {c: 'p', a:0, d:.2, krn: {'127': 0.0833}},
'113': {c: 'q', a:0, d:.2, ic: 0.0359, krn: {'127': 0.0833}},
'114': {c: 'r', a:0, ic: 0.0278, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0556}},
'115': {c: 's', a:0, krn: {'127': 0.0556}},
'116': {c: 't', krn: {'127': 0.0833}},
'117': {c: 'u', a:0, krn: {'127': 0.0278}},
'118': {c: 'v', a:0, ic: 0.0359, krn: {'127': 0.0278}},
'119': {c: 'w', a:0, ic: 0.0269, krn: {'127': 0.0833}},
'120': {c: 'x', a:0, krn: {'127': 0.0278}},
'121': {c: 'y', a:0, d:.2, ic: 0.0359, krn: {'127': 0.0556}},
'122': {c: 'z', a:0, ic: 0.044, krn: {'127': 0.0556}}
},
cmsy10: {
'0': {c:'&#x2212;', a:.1}
},
cmti10: {
'33': {c: '!', lig: {'96': 60}},
'35': {c: '#', ic: 0.0662},
'37': {c: '%', ic: 0.136},
'38': {c: '&amp;', ic: 0.0969},
'40': {c: '(', d:.2, ic: 0.162},
'41': {c: ')', d:.2, ic: 0.0369},
'42': {c: '*', ic: 0.149},
'43': {c: '+', a:.1, ic: 0.0369},
'44': {c: ',', a:-.3, d:.2, w: 0.278},
'45': {c: '-', a:0, ic: 0.0283, lig: {'45': 123}},
'46': {c: '.', a:-.25},
'47': {c: '/', ic: 0.162},
'48': {c: '0', ic: 0.136},
'49': {c: '1', ic: 0.136},
'50': {c: '2', ic: 0.136},
'51': {c: '3', ic: 0.136},
'52': {c: '4', ic: 0.136},
'53': {c: '5', ic: 0.136},
'54': {c: '6', ic: 0.136},
'55': {c: '7', ic: 0.136},
'56': {c: '8', ic: 0.136},
'57': {c: '9', ic: 0.136},
'58': {c: ':', ic: 0.0582},
'59': {c: ';', ic: 0.0582},
'61': {c: '=', a:0, d:-.1, ic: 0.0662},
'63': {c: '?', ic: 0.122, lig: {'96': 62}},
'64': {c: '@', ic: 0.096},
'65': {c: 'A', krn: {'110': -0.0256, '108': -0.0256, '114': -0.0256, '117': -0.0256, '109': -0.0256, '116': -0.0256, '105': -0.0256, '67': -0.0256, '79': -0.0256, '71': -0.0256, '104': -0.0256, '98': -0.0256, '85': -0.0256, '107': -0.0256, '118': -0.0256, '119': -0.0256, '81': -0.0256, '84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}},
'66': {c: 'B', ic: 0.103},
'67': {c: 'C', ic: 0.145},
'68': {c: 'D', ic: 0.094, krn: {'88': -0.0256, '87': -0.0256, '65': -0.0256, '86': -0.0256, '89': -0.0256}},
'69': {c: 'E', ic: 0.12},
'70': {c: 'F', ic: 0.133, krn: {'111': -0.0767, '101': -0.0767, '117': -0.0767, '114': -0.0767, '97': -0.0767, '65': -0.102, '79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}},
'71': {c: 'G', ic: 0.0872},
'72': {c: 'H', ic: 0.164},
'73': {c: 'I', ic: 0.158},
'74': {c: 'J', ic: 0.14},
'75': {c: 'K', ic: 0.145, krn: {'79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}},
'76': {c: 'L', krn: {'84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}},
'77': {c: 'M', ic: 0.164},
'78': {c: 'N', ic: 0.164},
'79': {c: 'O', ic: 0.094, krn: {'88': -0.0256, '87': -0.0256, '65': -0.0256, '86': -0.0256, '89': -0.0256}},
'80': {c: 'P', ic: 0.103, krn: {'65': -0.0767}},
'81': {c: 'Q', d:.2, ic: 0.094},
'82': {c: 'R', ic: 0.0387, krn: {'110': -0.0256, '108': -0.0256, '114': -0.0256, '117': -0.0256, '109': -0.0256, '116': -0.0256, '105': -0.0256, '67': -0.0256, '79': -0.0256, '71': -0.0256, '104': -0.0256, '98': -0.0256, '85': -0.0256, '107': -0.0256, '118': -0.0256, '119': -0.0256, '81': -0.0256, '84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}},
'83': {c: 'S', ic: 0.12},
'84': {c: 'T', ic: 0.133, krn: {'121': -0.0767, '101': -0.0767, '111': -0.0767, '114': -0.0767, '97': -0.0767, '117': -0.0767, '65': -0.0767}},
'85': {c: 'U', ic: 0.164},
'86': {c: 'V', ic: 0.184, krn: {'111': -0.0767, '101': -0.0767, '117': -0.0767, '114': -0.0767, '97': -0.0767, '65': -0.102, '79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}},
'87': {c: 'W', ic: 0.184, krn: {'65': -0.0767}},
'88': {c: 'X', ic: 0.158, krn: {'79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}},
'89': {c: 'Y', ic: 0.194, krn: {'101': -0.0767, '111': -0.0767, '114': -0.0767, '97': -0.0767, '117': -0.0767, '65': -0.0767}},
'90': {c: 'Z', ic: 0.145},
'91': {c: '[', d:.1, ic: 0.188},
'93': {c: ']', d:.1, ic: 0.105},
'97': {c: 'a', a:0, ic: 0.0767},
'98': {c: 'b', ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}},
'99': {c: 'c', a:0, ic: 0.0565, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}},
'100': {c: 'd', ic: 0.103, krn: {'108': 0.0511}},
'101': {c: 'e', a:0, ic: 0.0751, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}},
'102': {c: 'f', ic: 0.212, krn: {'39': 0.104, '63': 0.104, '33': 0.104, '41': 0.104, '93': 0.104}, lig: {'105': 12, '102': 11, '108': 13}},
'103': {c: 'g', a:0, d:.2, ic: 0.0885},
'104': {c: 'h', ic: 0.0767},
'105': {c: 'i', ic: 0.102},
'106': {c: 'j', d:.2, ic: 0.145},
'107': {c: 'k', ic: 0.108},
'108': {c: 'l', ic: 0.103, krn: {'108': 0.0511}},
'109': {c: 'm', a:0, ic: 0.0767},
'110': {c: 'n', a:0, ic: 0.0767, krn: {'39': -0.102}},
'111': {c: 'o', a:0, ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}},
'112': {c: 'p', a:0, d:.2, ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}},
'113': {c: 'q', a:0, d:.2, ic: 0.0885},
'114': {c: 'r', a:0, ic: 0.108, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}},
'115': {c: 's', a:0, ic: 0.0821},
'116': {c: 't', ic: 0.0949},
'117': {c: 'u', a:0, ic: 0.0767},
'118': {c: 'v', a:0, ic: 0.108},
'119': {c: 'w', a:0, ic: 0.108, krn: {'108': 0.0511}},
'120': {c: 'x', a:0, ic: 0.12},
'121': {c: 'y', a:0, d:.2, ic: 0.0885},
'122': {c: 'z', a:0, ic: 0.123}
},
cmbx10: {
'33': {c: '!', lig: {'96': 60}},
'35': {c: '#'},
'36': {c: '$'},
'37': {c: '%'},
'38': {c: '&amp;'},
'40': {c: '(', d:.2},
'41': {c: ')', d:.2},
'42': {c: '*'},
'43': {c: '+', a:.1},
'44': {c: ',', a:-.3, d:.2, w: 0.278},
'45': {c: '-', a:0, lig: {'45': 123}},
'46': {c: '.', a:-.25},
'47': {c: '/'},
'48': {c: '0'},
'49': {c: '1'},
'50': {c: '2'},
'51': {c: '3'},
'52': {c: '4'},
'53': {c: '5'},
'54': {c: '6'},
'55': {c: '7'},
'56': {c: '8'},
'57': {c: '9'},
'58': {c: ':'},
'59': {c: ';'},
'61': {c: '=', a:0, d:-.1},
'63': {c: '?', lig: {'96': 62}},
'64': {c: '@'},
'65': {c: 'A', krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}},
'66': {c: 'B'},
'67': {c: 'C'},
'68': {c: 'D', krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}},
'69': {c: 'E'},
'70': {c: 'F', krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}},
'71': {c: 'G'},
'72': {c: 'H'},
'73': {c: 'I', krn: {'73': 0.0278}},
'74': {c: 'J'},
'75': {c: 'K', krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}},
'76': {c: 'L', krn: {'84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}},
'77': {c: 'M'},
'78': {c: 'N'},
'79': {c: 'O', krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}},
'80': {c: 'P', krn: {'65': -0.0833, '111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}},
'81': {c: 'Q', d: 1},
'82': {c: 'R', krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}},
'83': {c: 'S'},
'84': {c: 'T', krn: {'121': -0.0278, '101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}},
'85': {c: 'U'},
'86': {c: 'V', ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}},
'87': {c: 'W', ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}},
'88': {c: 'X', krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}},
'89': {c: 'Y', ic: 0.025, krn: {'101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}},
'90': {c: 'Z'},
'91': {c: '[', d:.1},
'93': {c: ']', d:.1},
'97': {c: 'a', a:0, krn: {'118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}},
'98': {c: 'b', krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}},
'99': {c: 'c', a:0, krn: {'104': -0.0278, '107': -0.0278}},
'100': {c: 'd'},
'101': {c: 'e', a:0},
'102': {c: 'f', ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 12, '102': 11, '108': 13}},
'103': {c: 'g', a:0, d:.2, ic: 0.0139, krn: {'106': 0.0278}},
'104': {c: 'h', krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}},
'105': {c: 'i'},
'106': {c: 'j', d:1},
'107': {c: 'k', krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}},
'108': {c: 'l'},
'109': {c: 'm', a:0, krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}},
'110': {c: 'n', a:0, krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}},
'111': {c: 'o', a:0, krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}},
'112': {c: 'p', a:0, d:.2, krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}},
'113': {c: 'q', a:0, d:1},
'114': {c: 'r', a:0},
'115': {c: 's', a:0},
'116': {c: 't', krn: {'121': -0.0278, '119': -0.0278}},
'117': {c: 'u', a:0, krn: {'119': -0.0278}},
'118': {c: 'v', a:0, ic: 0.0139, krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}},
'119': {c: 'w', a:0, ic: 0.0139, krn: {'101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}},
'120': {c: 'x', a:0},
'121': {c: 'y', a:0, d:.2, ic: 0.0139, krn: {'111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}},
'122': {c: 'z', a:0}
}
});
if (jsMath.browser == 'MSIE' && jsMath.platform == 'mac') {
jsMath.Setup.Styles({
'.typeset .math': 'font-style: normal',
'.typeset .typeset': 'font-style: normal',
'.typeset .icmr10': 'font-family: Times',
'.typeset .icmmi10': 'font-family: Times; font-style: italic',
'.typeset .icmbx10': 'font-family: Times; font-weight: bold',
'.typeset .icmti10': 'font-family: Times; font-style: italic'
});
} else {
jsMath.Setup.Styles({
'.typeset .math': 'font-style: normal',
'.typeset .typeset': 'font-style: normal',
'.typeset .icmr10': 'font-family: serif',
'.typeset .icmmi10': 'font-family: serif; font-style: italic',
'.typeset .icmbx10': 'font-family: serif; font-weight: bold',
'.typeset .icmti10': 'font-family: serif; font-style: italic'
});
}
jsMath.Add(jsMath.Img,{
symbols: [
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 34, 39,
60, 62,
92, 94, 95,
96,
123,124,125,126,127
]
});
/*
* for now, use images for everything
*/
jsMath.Img.SetFont({
cmr10: jsMath.Img.symbols,
cmmi10: [
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
64,
91, 92, 93, 94, 95,
96,
123,124,125,126,127
],
cmsy10: [
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
96, 97, 98, 99,100,101,102,103, 104,105,106,107,108,109,110,111,
112,113,114,115,116,117,118,119, 120,121,122,123,124,125,126,127
],
cmex10: ['all'],
cmti10: jsMath.Img.symbols.concat(36),
cmbx10: jsMath.Img.symbols
});
jsMath.Img.LoadFont('cm-fonts');

View File

@ -0,0 +1,935 @@
/*
* jsMath-fallback-mac.js
*
* Part of the jsMath package for mathematics on the web.
*
* This file makes changes needed for when the TeX fonts are not available
* with a browser on the Mac.
*
* ---------------------------------------------------------------------
*
* Copyright 2004-2006 by Davide P. Cervone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/********************************************************************
*
* Here we replace the TeX character mappings by equivalent unicode
* points when possible, and adjust the character dimensions
* based on the fonts we hope we get them from (the styles are set
* to try to use the best characters available in the standard
* fonts).
*/
jsMath.Add(jsMath.TeX,{
cmr10: [
// 00 - 0F
{c: '&Gamma;', tclass: 'greek'},
{c: '&Delta;', tclass: 'greek'},
{c: '&Theta;', tclass: 'greek'},
{c: '&Lambda;', tclass: 'greek'},
{c: '&Xi;', tclass: 'greek'},
{c: '&Pi;', tclass: 'greek'},
{c: '&Sigma;', tclass: 'greek'},
{c: '&Upsilon;', tclass: 'greek'},
{c: '&Phi;', tclass: 'greek'},
{c: '&Psi;', tclass: 'greek'},
{c: '&Omega;', tclass: 'greek'},
{c: 'ff', ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 14, '108': 15}, tclass: 'normal'},
{c: 'fi', tclass: 'normal'},
{c: 'fl', tclass: 'normal'},
{c: 'ffi', tclass: 'normal'},
{c: 'ffl', tclass: 'normal'},
// 10 - 1F
{c: '&#x131;', a:0, tclass: 'normal'},
{c: 'j', d:.2, tclass: 'normal'},
{c: '&#x60;', tclass: 'accent'},
{c: '&#xB4;', tclass: 'accent'},
{c: '&#x2C7;', tclass: 'accent'},
{c: '&#x2D8;', tclass: 'accent'},
{c: '<span style="position:relative; top:.1em">&#x2C9;</span>', tclass: 'accent'},
{c: '&#x2DA;', tclass: 'accent'},
{c: '&#x0327;', tclass: 'normal'},
{c: '&#xDF;', tclass: 'normal'},
{c: '&#xE6;', a:0, tclass: 'normal'},
{c: '&#x153;', a:0, tclass: 'normal'},
{c: '&#xF8;', tclass: 'normal'},
{c: '&#xC6;', tclass: 'normal'},
{c: '&#x152;', tclass: 'normal'},
{c: '&#xD8;', tclass: 'normal'},
// 20 - 2F
{c: '?', krn: {'108': -0.278, '76': -0.319}, tclass: 'normal'},
{c: '!', lig: {'96': 60}, tclass: 'normal'},
{c: '&#x201D;', tclass: 'normal'},
{c: '#', tclass: 'normal'},
{c: '$', tclass: 'normal'},
{c: '%', tclass: 'normal'},
{c: '&amp;', tclass: 'normal'},
{c: '&#x2019;', krn: {'63': 0.111, '33': 0.111}, lig: {'39': 34}, tclass: 'normal'},
{c: '(', d:.2, tclass: 'normal'},
{c: ')', d:.2, tclass: 'normal'},
{c: '*', tclass: 'normal'},
{c: '+', a:.1, tclass: 'normal'},
{c: ',', a:-.3, d:.2, w: 0.278, tclass: 'normal'},
{c: '-', a:0, lig: {'45': 123}, tclass: 'normal'},
{c: '.', a:-.25, tclass: 'normal'},
{c: '/', tclass: 'normal'},
// 30 - 3F
{c: '0', tclass: 'normal'},
{c: '1', tclass: 'normal'},
{c: '2', tclass: 'normal'},
{c: '3', tclass: 'normal'},
{c: '4', tclass: 'normal'},
{c: '5', tclass: 'normal'},
{c: '6', tclass: 'normal'},
{c: '7', tclass: 'normal'},
{c: '8', tclass: 'normal'},
{c: '9', tclass: 'normal'},
{c: ':', tclass: 'normal'},
{c: ';', tclass: 'normal'},
{c: '&#xA1;', tclass: 'normal'},
{c: '=', a:0, d:-.1, tclass: 'normal'},
{c: '&#xBF;', tclass: 'normal'},
{c: '?', lig: {'96': 62}, tclass: 'normal'},
// 40 - 4F
{c: '@', tclass: 'normal'},
{c: 'A', krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}, tclass: 'normal'},
{c: 'B', tclass: 'normal'},
{c: 'C', tclass: 'normal'},
{c: 'D', krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}, tclass: 'normal'},
{c: 'E', tclass: 'normal'},
{c: 'F', krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'normal'},
{c: 'G', tclass: 'normal'},
{c: 'H', tclass: 'normal'},
{c: 'I', krn: {'73': 0.0278}, tclass: 'normal'},
{c: 'J', tclass: 'normal'},
{c: 'K', krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'normal'},
{c: 'L', krn: {'84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}, tclass: 'normal'},
{c: 'M', tclass: 'normal'},
{c: 'N', tclass: 'normal'},
{c: 'O', krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}, tclass: 'normal'},
// 50 - 5F
{c: 'P', krn: {'65': -0.0833, '111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}, tclass: 'normal'},
{c: 'Q', d: 1, tclass: 'normal'},
{c: 'R', krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}, tclass: 'normal'},
{c: 'S', tclass: 'normal'},
{c: 'T', krn: {'121': -0.0278, '101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}, tclass: 'normal'},
{c: 'U', tclass: 'normal'},
{c: 'V', ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'normal'},
{c: 'W', ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'normal'},
{c: 'X', krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'normal'},
{c: 'Y', ic: 0.025, krn: {'101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}, tclass: 'normal'},
{c: 'Z', tclass: 'normal'},
{c: '[', d:.1, tclass: 'normal'},
{c: '&#x201C;', tclass: 'normal'},
{c: ']', d:.1, tclass: 'normal'},
{c: '&#x2C6;', tclass: 'accent'},
{c: '&#x2D9;', tclass: 'accent'},
// 60 - 6F
{c: '&#x2018;', lig: {'96': 92}, tclass: 'normal'},
{c: 'a', a:0, krn: {'118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'normal'},
{c: 'b', krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'normal'},
{c: 'c', a:0, krn: {'104': -0.0278, '107': -0.0278}, tclass: 'normal'},
{c: 'd', tclass: 'normal'},
{c: 'e', a:0, tclass: 'normal'},
{c: 'f', ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 12, '102': 11, '108': 13}, tclass: 'normal'},
{c: 'g', a:0, d:.2, ic: 0.0139, krn: {'106': 0.0278}, tclass: 'normal'},
{c: 'h', krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}, tclass: 'normal'},
{c: 'i', tclass: 'normal'},
{c: 'j', d:.2, tclass: 'normal'},
{c: 'k', krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}, tclass: 'normal'},
{c: 'l', tclass: 'normal'},
{c: 'm', a:0, krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}, tclass: 'normal'},
{c: 'n', a:0, krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}, tclass: 'normal'},
{c: 'o', a:0, krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'normal'},
// 70 - 7F
{c: 'p', a:0, d:.2, krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'normal'},
{c: 'q', a:0, d:.2, tclass: 'normal'},
{c: 'r', a:0, tclass: 'normal'},
{c: 's', a:0, tclass: 'normal'},
{c: 't', krn: {'121': -0.0278, '119': -0.0278}, tclass: 'normal'},
{c: 'u', a:0, krn: {'119': -0.0278}, tclass: 'normal'},
{c: 'v', a:0, ic: 0.0139, krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}, tclass: 'normal'},
{c: 'w', a:0, ic: 0.0139, krn: {'101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}, tclass: 'normal'},
{c: 'x', a:0, tclass: 'normal'},
{c: 'y', a:0, d:.2, ic: 0.0139, krn: {'111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}, tclass: 'normal'},
{c: 'z', a:0, tclass: 'normal'},
{c: '&#x2013;', a:.1, ic: 0.0278, lig: {'45': 124}, tclass: 'normal'},
{c: '&#x2014;', a:.1, ic: 0.0278, tclass: 'normal'},
{c: '&#x2DD;', tclass: 'accent'},
{c: '&#x2DC;', tclass: 'accent'},
{c: '&#xA8;', tclass: 'accent'}
],
cmmi10: [
// 00 - 0F
{c: '&Gamma;', ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0833}, tclass: 'igreek'},
{c: '&Delta;', krn: {'127': 0.167}, tclass: 'igreek'},
{c: '&Theta;', ic: 0.0278, krn: {'127': 0.0833}, tclass: 'igreek'},
{c: '&Lambda;', krn: {'127': 0.167}, tclass: 'igreek'},
{c: '&Xi;', ic: 0.0757, krn: {'127': 0.0833}, tclass: 'igreek'},
{c: '&Pi;', ic: 0.0812, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}, tclass: 'igreek'},
{c: '&Sigma;', ic: 0.0576, krn: {'127': 0.0833}, tclass: 'igreek'},
{c: '&Upsilon;', ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0556}, tclass: 'igreek'},
{c: '&Phi;', krn: {'127': 0.0833}, tclass: 'igreek'},
{c: '&Psi;', ic: 0.11, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}, tclass: 'igreek'},
{c: '&Omega;', ic: 0.0502, krn: {'127': 0.0833}, tclass: 'igreek'},
{c: '&alpha;', a:0, ic: 0.0037, krn: {'127': 0.0278}, tclass: 'greek'},
{c: '&beta;', d:.2, ic: 0.0528, krn: {'127': 0.0833}, tclass: 'greek'},
{c: '&gamma;', a:0, d:.2, ic: 0.0556, tclass: 'greek'},
{c: '&delta;', ic: 0.0378, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0556}, tclass: 'greek'},
{c: '&epsilon;', a:0, krn: {'127': 0.0556}, tclass: 'symbol'},
// 10 - 1F
{c: '&zeta;', d:.2, ic: 0.0738, krn: {'127': 0.0833}, tclass: 'greek'},
{c: '&eta;', a:0, d:.2, ic: 0.0359, krn: {'127': 0.0556}, tclass: 'greek'},
{c: '&theta;', ic: 0.0278, krn: {'127': 0.0833}, tclass: 'greek'},
{c: '&iota;', a:0, krn: {'127': 0.0556}, tclass: 'greek'},
{c: '&kappa;', a:0, tclass: 'greek'},
{c: '&lambda;', tclass: 'greek'},
{c: '&mu;', a:0, d:.2, krn: {'127': 0.0278}, tclass: 'greek'},
{c: '&nu;', a:0, ic: 0.0637, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0278}, tclass: 'greek'},
{c: '&xi;', d:.2, ic: 0.046, krn: {'127': 0.111}, tclass: 'greek'},
{c: '&pi;', a:0, ic: 0.0359, tclass: 'greek'},
{c: '&rho;', a:0, d:.2, krn: {'127': 0.0833}, tclass: 'greek'},
{c: '&sigma;', a:0, ic: 0.0359, krn: {'59': -0.0556, '58': -0.0556}, tclass: 'greek'},
{c: '&tau;', a:0, ic: 0.113, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0278}, tclass: 'greek'},
{c: '&upsilon;', a:0, ic: 0.0359, krn: {'127': 0.0278}, tclass: 'greek'},
{c: '&phi;', a:.1, d:.2, krn: {'127': 0.0833}, tclass: 'greek'},
{c: '&chi;', a:0, d:.2, krn: {'127': 0.0556}, tclass: 'greek'},
// 20 - 2F
{c: '&psi;', a:.1, d:.2, ic: 0.0359, krn: {'127': 0.111}, tclass: 'greek'},
{c: '&omega;', a:0, ic: 0.0359, tclass: 'greek'},
{c: '&epsilon;', a:0, krn: {'127': 0.0833}, tclass: 'greek'},
{c: '&#x3D1;', krn: {'127': 0.0833}, tclass: 'normal'},
{c: '&#x3D6;', a:0, ic: 0.0278, tclass: 'normal'},
{c: '&#x3F1;', a:0, d:.2, krn: {'127': 0.0833}, tclass: 'normal'},
{c: '&#x3C2;', a:0, d:.2, ic: 0.0799, krn: {'127': 0.0833}, tclass: 'normal'},
{c: '&#x3D5;', a:.1, d:.2, krn: {'127': 0.0833}, tclass: 'normal'},
{c: '&#x21BC;', a:0, d:-.2, tclass: 'harpoon'},
{c: '&#x21BD;', a:0, d:-.1, tclass: 'harpoon'},
{c: '&#x21C0;', a:0, d:-.2, tclass: 'harpoon'},
{c: '&#x21C1;', a:0, d:-.1, tclass: 'harpoon'},
{c: '<span style="font-size: 133%; position:relative; top:-.1em; margin:-.2em; left:-.05em">&#x02D3;</span>', a:.1, tclass: 'symbol'},
{c: '<span style="font-size: 133%; position:relative; top:-.1em; margin:-.2em; left:-.05em">&#x02D2;</span>', a:.1, tclass: 'symbol'},
{c: '<span style="font-size:50%">&#x25B7;</span>', tclass: 'symbol'},
{c: '<span style="font-size:50%">&#x25C1;</span>', tclass: 'symbol'},
// 30 - 3F
{c: '0', tclass: 'normal'},
{c: '1', tclass: 'normal'},
{c: '2', tclass: 'normal'},
{c: '3', tclass: 'normal'},
{c: '4', tclass: 'normal'},
{c: '5', tclass: 'normal'},
{c: '6', tclass: 'normal'},
{c: '7', tclass: 'normal'},
{c: '8', tclass: 'normal'},
{c: '9', tclass: 'normal'},
{c: '.', a:-.3, tclass: 'normal'},
{c: ',', a:-.3, d:.2, tclass: 'normal'},
{c: '&lt;', a:.1, tclass: 'normal'},
{c: '/', krn: {'1': -0.0556, '65': -0.0556, '77': -0.0556, '78': -0.0556, '89': 0.0556, '90': -0.0556}, tclass: 'normal'},
{c: '&gt;', a:.1, tclass: 'normal'},
{c: '<span style="font-size:50%">&#x2605;</span>', a:0, tclass: 'symbol'},
// 40 - 4F
{c: '&#x2202;', ic: 0.0556, krn: {'127': 0.0833}, tclass: 'normal'},
{c: 'A', krn: {'127': 0.139}, tclass: 'italic'},
{c: 'B', ic: 0.0502, krn: {'127': 0.0833}, tclass: 'italic'},
{c: 'C', ic: 0.0715, krn: {'61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'},
{c: 'D', ic: 0.0278, krn: {'127': 0.0556}, tclass: 'italic'},
{c: 'E', ic: 0.0576, krn: {'127': 0.0833}, tclass: 'italic'},
{c: 'F', ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0833}, tclass: 'italic'},
{c: 'G', krn: {'127': 0.0833}, tclass: 'italic'},
{c: 'H', ic: 0.0812, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}, tclass: 'italic'},
{c: 'I', ic: 0.0785, krn: {'127': 0.111}, tclass: 'italic'},
{c: 'J', ic: 0.0962, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.167}, tclass: 'italic'},
{c: 'K', ic: 0.0715, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}, tclass: 'italic'},
{c: 'L', krn: {'127': 0.0278}, tclass: 'italic'},
{c: 'M', ic: 0.109, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'},
{c: 'N', ic: 0.109, krn: {'61': -0.0833, '61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'},
{c: 'O', ic: 0.0278, krn: {'127': 0.0833}, tclass: 'italic'},
// 50 - 5F
{c: 'P', ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0833}, tclass: 'italic'},
{c: 'Q', d:.2, krn: {'127': 0.0833}, tclass: 'italic'},
{c: 'R', ic: 0.00773, krn: {'127': 0.0833}, tclass: 'italic'},
{c: 'S', ic: 0.0576, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'},
{c: 'T', ic: 0.139, krn: {'61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'},
{c: 'U', ic: 0.109, krn: {'59': -0.111, '58': -0.111, '61': -0.0556, '127': 0.0278}, tclass: 'italic'},
{c: 'V', ic: 0.222, krn: {'59': -0.167, '58': -0.167, '61': -0.111}, tclass: 'italic'},
{c: 'W', ic: 0.139, krn: {'59': -0.167, '58': -0.167, '61': -0.111}, tclass: 'italic'},
{c: 'X', ic: 0.0785, krn: {'61': -0.0833, '61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'},
{c: 'Y', ic: 0.222, krn: {'59': -0.167, '58': -0.167, '61': -0.111}, tclass: 'italic'},
{c: 'Z', ic: 0.0715, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}, tclass: 'italic'},
{c: '&#x266D;', tclass: 'symbol2'},
{c: '&#x266E;', tclass: 'symbol2'},
{c: '&#x266F;', tclass: 'symbol2'},
{c: '&#x2323;', a:0, d:-.1, tclass: 'normal'},
{c: '&#x2322;', a:0, d:-.1, tclass: 'normal'},
// 60 - 6F
{c: '&#x2113;', krn: {'127': 0.111}, tclass: 'symbol'},
{c: 'a', a:0, tclass: 'italic'},
{c: 'b', tclass: 'italic'},
{c: 'c', a:0, krn: {'127': 0.0556}, tclass: 'italic'},
{c: 'd', krn: {'89': 0.0556, '90': -0.0556, '106': -0.111, '102': -0.167, '127': 0.167}, tclass: 'italic'},
{c: 'e', a:0, krn: {'127': 0.0556}, tclass: 'italic'},
{c: 'f', d:.2, ic: 0.108, krn: {'59': -0.0556, '58': -0.0556, '127': 0.167}, tclass: 'italic'},
{c: 'g', a:0, d:.2, ic: 0.0359, krn: {'127': 0.0278}, tclass: 'italic'},
{c: 'h', krn: {'127': -0.0278}, tclass: 'italic'},
{c: 'i', tclass: 'italic'},
{c: 'j', d:.2, ic: 0.0572, krn: {'59': -0.0556, '58': -0.0556}, tclass: 'italic'},
{c: 'k', ic: 0.0315, tclass: 'italic'},
{c: 'l', ic: 0.0197, krn: {'127': 0.0833}, tclass: 'italic'},
{c: 'm', a:0, tclass: 'italic'},
{c: 'n', a:0, tclass: 'italic'},
{c: 'o', a:0, krn: {'127': 0.0556}, tclass: 'italic'},
// 70 - 7F
{c: 'p', a:0, d:.2, krn: {'127': 0.0833}, tclass: 'italic'},
{c: 'q', a:0, d:.2, ic: 0.0359, krn: {'127': 0.0833}, tclass: 'italic'},
{c: 'r', a:0, ic: 0.0278, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0556}, tclass: 'italic'},
{c: 's', a:0, krn: {'127': 0.0556}, tclass: 'italic'},
{c: 't', krn: {'127': 0.0833}, tclass: 'italic'},
{c: 'u', a:0, krn: {'127': 0.0278}, tclass: 'italic'},
{c: 'v', a:0, ic: 0.0359, krn: {'127': 0.0278}, tclass: 'italic'},
{c: 'w', a:0, ic: 0.0269, krn: {'127': 0.0833}, tclass: 'italic'},
{c: 'x', a:0, krn: {'127': 0.0278}, tclass: 'italic'},
{c: 'y', a:0, d:.2, ic: 0.0359, krn: {'127': 0.0556}, tclass: 'italic'},
{c: 'z', a:0, ic: 0.044, krn: {'127': 0.0556}, tclass: 'italic'},
{c: '&#x131;', a:0, krn: {'127': 0.0278}, tclass: 'italic'},
{c: 'j', d:.2, krn: {'127': 0.0833}, tclass: 'italic'},
{c: '&#x2118;', a:0, d:.2, krn: {'127': 0.111}, tclass: 'normal'},
{c: '<span style="position:relative; left: .4em; top: -.8em; font-size: 50%">&#x2192;</span>', ic: 0.154, tclass: 'symbol'},
{c: '&#x0311;', ic: 0.399, tclass: 'normal'}
],
cmsy10: [
// 00 - 0F
{c: '&#x2212;', a:.1, tclass: 'symbol'},
{c: '&#xB7;', a:0, d:-.2, tclass: 'symbol'},
{c: '&#xD7;', a:0, tclass: 'symbol'},
{c: '<span style="position:relative; top:.2em">&#x2A;</span>', a:0, tclass: 'symbol'},
{c: '&#xF7;', a:0, tclass: 'symbol'},
{c: '&#x25CA;', tclass: 'symbol'},
{c: '&#xB1;', a:.1, tclass: 'symbol'},
{c: '&#x2213;', tclass: 'symbol'},
{c: '&#x2295;', tclass: 'symbol'},
{c: '&#x2296;', tclass: 'symbol'},
{c: '&#x2297;', tclass: 'symbol'},
{c: '&#x2298;', tclass: 'symbol'},
{c: '&#x2299;', tclass: 'symbol'},
{c: '&#x25EF;', tclass: 'symbol'},
{c: '<span style="position:relative; top:.25em;">&#xB0;</span>', a:0, d:-.1, tclass: 'symbol'},
{c: '&#x2022;', a:0, d:-.2, tclass: 'symbol'},
// 10 - 1F
{c: '&#x224D;', a:.1, tclass: 'symbol'},
{c: '&#x2261;', a:.1, tclass: 'symbol'},
{c: '&#x2286;', tclass: 'symbol'},
{c: '&#x2287;', tclass: 'symbol'},
{c: '&#x2264;', tclass: 'symbol'},
{c: '&#x2265;', tclass: 'symbol'},
{c: '&#x227C;', tclass: 'symbol'},
{c: '&#x227D;', tclass: 'symbol'},
{c: '~', a:0, d: -.2, tclass: 'normal'},
{c: '&#x2248;', a:.1, d:-.1, tclass: 'symbol'},
{c: '&#x2282;', tclass: 'symbol'},
{c: '&#x2283;', tclass: 'symbol'},
{c: '&#x226A;', tclass: 'symbol'},
{c: '&#x226B;', tclass: 'symbol'},
{c: '&#x227A;', tclass: 'symbol'},
{c: '&#x227B;', tclass: 'symbol'},
// 20 - 2F
{c: '&#x2190;', a:0, d:-.15, tclass: 'arrows'},
{c: '&#x2192;', a:0, d:-.15, tclass: 'arrows'},
{c: '&#x2191;', h:1, tclass: 'arrows'},
{c: '&#x2193;', h:1, tclass: 'arrows'},
{c: '&#x2194;', a:0, tclass: 'arrows'},
{c: '&#x2197;', h:1, tclass: 'arrows'},
{c: '&#x2198;', h:1, tclass: 'arrows'},
{c: '&#x2243;', a: .1, tclass: 'symbol'},
{c: '&#x21D0;', a:.1, tclass: 'arrows'},
{c: '&#x21D2;', a:.1, tclass: 'arrows'},
{c: '&#x21D1;', h:.9, d:.1, tclass: 'arrows'},
{c: '&#x21D3;', h:.9, d:.1, tclass: 'arrows'},
{c: '&#x21D4;', a:.1, tclass: 'arrows'},
{c: '&#x2196;', h:1, tclass: 'arrows'},
{c: '&#x2199;', h:1, tclass: 'arrows'},
{c: '&#x221D;', a:.1, tclass: 'symbol'},
// 30 - 3F
{c: '<span style="font-size: 133%; margin-right: -.1em; position: relative; top:.4em">&#x2032;</span>', a: 0, tclass: 'symbol'},
{c: '&#x221E;', a:.1, tclass: 'symbol'},
{c: '&#x2208;', tclass: 'symbol'},
{c: '&#x220B;', tclass: 'symbol'},
{c: '&#x25B3;', tclass: 'symbol'},
{c: '&#x25BD;', tclass: 'symbol'},
{c: '/', tclass: 'symbol'},
{c: '<span style="font-size:50%; position:relative; top:-.3em; margin-right:-.2em">|</span>', a:0, tclass: 'normal'},
{c: '&#x2200;', tclass: 'symbol'},
{c: '&#x2203;', tclass: 'symbol'},
{c: '&#xAC;', a:0, d:-.1, tclass: 'symbol1'},
{c: '&#x2205;', tclass: 'symbol'},
{c: '&#x211C;', tclass: 'symbol'},
{c: '&#x2111;', tclass: 'symbol'},
{c: '&#x22A4;', tclass: 'symbol'},
{c: '&#x22A5;', tclass: 'symbol'},
// 40 - 4F
{c: '&#x2135;', tclass: 'symbol'},
{c: 'A', krn: {'48': 0.194}, tclass: 'cal'},
{c: 'B', ic: 0.0304, krn: {'48': 0.139}, tclass: 'cal'},
{c: 'C', ic: 0.0583, krn: {'48': 0.139}, tclass: 'cal'},
{c: 'D', ic: 0.0278, krn: {'48': 0.0833}, tclass: 'cal'},
{c: 'E', ic: 0.0894, krn: {'48': 0.111}, tclass: 'cal'},
{c: 'F', ic: 0.0993, krn: {'48': 0.111}, tclass: 'cal'},
{c: 'G', d:.2, ic: 0.0593, krn: {'48': 0.111}, tclass: 'cal'},
{c: 'H', ic: 0.00965, krn: {'48': 0.111}, tclass: 'cal'},
{c: 'I', ic: 0.0738, krn: {'48': 0.0278}, tclass: 'cal'},
{c: 'J', d:.2, ic: 0.185, krn: {'48': 0.167}, tclass: 'cal'},
{c: 'K', ic: 0.0144, krn: {'48': 0.0556}, tclass: 'cal'},
{c: 'L', krn: {'48': 0.139}, tclass: 'cal'},
{c: 'M', krn: {'48': 0.139}, tclass: 'cal'},
{c: 'N', ic: 0.147, krn: {'48': 0.0833}, tclass: 'cal'},
{c: 'O', ic: 0.0278, krn: {'48': 0.111}, tclass: 'cal'},
// 50 - 5F
{c: 'P', ic: 0.0822, krn: {'48': 0.0833}, tclass: 'cal'},
{c: 'Q', d:.2, krn: {'48': 0.111}, tclass: 'cal'},
{c: 'R', krn: {'48': 0.0833}, tclass: 'cal'},
{c: 'S', ic: 0.075, krn: {'48': 0.139}, tclass: 'cal'},
{c: 'T', ic: 0.254, krn: {'48': 0.0278}, tclass: 'cal'},
{c: 'U', ic: 0.0993, krn: {'48': 0.0833}, tclass: 'cal'},
{c: 'V', ic: 0.0822, krn: {'48': 0.0278}, tclass: 'cal'},
{c: 'W', ic: 0.0822, krn: {'48': 0.0833}, tclass: 'cal'},
{c: 'X', ic: 0.146, krn: {'48': 0.139}, tclass: 'cal'},
{c: 'Y', ic: 0.0822, krn: {'48': 0.0833}, tclass: 'cal'},
{c: 'Z', ic: 0.0794, krn: {'48': 0.139}, tclass: 'cal'},
{c: '&#x22C3;', tclass: 'symbol'},
{c: '&#x22C2;', tclass: 'symbol'},
{c: '&#x228E;', tclass: 'symbol'},
{c: '&#x22C0;', tclass: 'symbol'},
{c: '&#x22C1;', tclass: 'symbol'},
// 60 - 6F
{c: '&#x22A2;', tclass: 'symbol'},
{c: '&#x22A3;', tclass: 'symbol2'},
{c: '&#xF8F0;', a:.3, d:.2, tclass: 'normal'},
{c: '&#xF8FB;', a:.3, d:.2, tclass: 'normal'},
{c: '&#xF8EE;', a:.3, d:.2, tclass: 'normal'},
{c: '&#xF8F9;', a:.3, d:.2, tclass: 'normal'},
{c: '{', d:.2, tclass: 'normal'},
{c: '}', d:.2, tclass: 'normal'},
{c: '&#x3008;', a:.3, d:.2, tclass: 'normal'},
{c: '&#x3009;', a:.3, d:.2, tclass: 'normal'},
{c: '|', d:.1, tclass: 'vertical'},
{c: '||', d:0, tclass: 'vertical'},
{c: '&#x2195;', h:1, d:.15, tclass: 'arrows'},
{c: '&#x21D5;', a:.2, d:.1, tclass: 'arrows'},
{c: '&#x2216;', a:.3, d:.1, tclass: 'normal'},
{c: '&#x2240;', tclass: 'symbol'},
// 70 - 7F
{c: '<span style="position:relative; top: .8em">&#x221A;</span>', h:.04, d:.9, tclass: 'normal'},
{c: '&#x2210;', a:.4, tclass: 'symbol'},
{c: '&#x2207;', tclass: 'symbol'},
{c: '&#x222B;', h:1, d:.1, ic: 0.111, tclass: 'root'},
{c: '&#x2294;', tclass: 'symbol'},
{c: '&#x2293;', tclass: 'symbol'},
{c: '&#x2291;', tclass: 'symbol'},
{c: '&#x2292;', tclass: 'symbol'},
{c: '&#xA7;', d:.1, tclass: 'normal'},
{c: '&#x2020;', d:.1, tclass: 'normal'},
{c: '&#x2021;', d:.1, tclass: 'normal'},
{c: '&#xB6;', a:.3, d:.1, tclass: 'normal'},
{c: '&#x2663;', tclass: 'symbol'},
{c: '&#x2666;', tclass: 'symbol'},
{c: '&#x2665;', tclass: 'symbol'},
{c: '&#x2660;', tclass: 'symbol'}
],
cmex10: [
// 00 - 0F
{c: '(', h: 0.04, d: 1.16, n: 16, tclass: 'delim1'},
{c: ')', h: 0.04, d: 1.16, n: 17, tclass: 'delim1'},
{c: '[', h: 0.04, d: 1.16, n: 104, tclass: 'delim1'},
{c: ']', h: 0.04, d: 1.16, n: 105, tclass: 'delim1'},
{c: '&#xF8F0', h: 0.04, d: 1.16, n: 106, tclass: 'delim1'},
{c: '&#xF8FB;', h: 0.04, d: 1.16, n: 107, tclass: 'delim1'},
{c: '&#xF8EE;', h: 0.04, d: 1.16, n: 108, tclass: 'delim1'},
{c: '&#xF8F9;', h: 0.04, d: 1.16, n: 109, tclass: 'delim1'},
{c: '{', h: 0.04, d: 1.16, n: 110, tclass: 'delim1'},
{c: '}', h: 0.04, d: 1.16, n: 111, tclass: 'delim1'},
{c: '&#x3008;', h: 0.04, d: 1.16, n: 68, tclass: 'delim1c'},
{c: '&#x3009;', h: 0.04, d: 1.16, n: 69, tclass: 'delim1c'},
{c: '|', h:.7, d:0, delim: {rep: 12}, tclass: 'vertical'},
{c: '||', h:.7, d:0, delim: {rep: 13}, tclass: 'vertical'},
{c: '/', h: 0.04, d: 1.16, n: 46, tclass: 'delim1b'},
{c: '&#x2216;', h: 0.04, d: 1.16, n: 47, tclass: 'delim1b'},
// 10 - 1F
{c: '(', h: 0.04, d: 1.76, n: 18, tclass: 'delim2'},
{c: ')', h: 0.04, d: 1.76, n: 19, tclass: 'delim2'},
{c: '(', h: 0.04, d: 2.36, n: 32, tclass: 'delim3'},
{c: ')', h: 0.04, d: 2.36, n: 33, tclass: 'delim3'},
{c: '[', h: 0.04, d: 2.36, n: 34, tclass: 'delim3'},
{c: ']', h: 0.04, d: 2.36, n: 35, tclass: 'delim3'},
{c: '&#xF8F0;', h: 0.04, d: 2.36, n: 36, tclass: 'delim3'},
{c: '&#xF8FB;', h: 0.04, d: 2.36, n: 37, tclass: 'delim3'},
{c: '&#xF8EE;', h: 0.04, d: 2.36, n: 38, tclass: 'delim3'},
{c: '&#xF8F9;', h: 0.04, d: 2.36, n: 39, tclass: 'delim3'},
{c: '{', h: 0.04, d: 2.36, n: 40, tclass: 'delim3'},
{c: '}', h: 0.04, d: 2.36, n: 41, tclass: 'delim3'},
{c: '&#x3008;', h: 0.04, d: 2.36, n: 42, tclass: 'delim3c'},
{c: '&#x3009;', h: 0.04, d: 2.36, n: 43, tclass: 'delim3c'},
{c: '/', h: 0.04, d: 2.36, n: 44, tclass: 'delim3b'},
{c: '&#x2216;', h: 0.04, d: 2.36, n: 45, tclass: 'delim3b'},
// 20 - 2F
{c: '(', h: 0.04, d: 2.96, n: 48, tclass: 'delim4'},
{c: ')', h: 0.04, d: 2.96, n: 49, tclass: 'delim4'},
{c: '[', h: 0.04, d: 2.96, n: 50, tclass: 'delim4'},
{c: ']', h: 0.04, d: 2.96, n: 51, tclass: 'delim4'},
{c: '&#xF8F0;', h: 0.04, d: 2.96, n: 52, tclass: 'delim4'},
{c: '&#xF8FB;', h: 0.04, d: 2.96, n: 53, tclass: 'delim4'},
{c: '&#xF8EE;', h: 0.04, d: 2.96, n: 54, tclass: 'delim4'},
{c: '&#xF8F9;', h: 0.04, d: 2.96, n: 55, tclass: 'delim4'},
{c: '{', h: 0.04, d: 2.96, n: 56, tclass: 'delim4'},
{c: '}', h: 0.04, d: 2.96, n: 57, tclass: 'delim4'},
{c: '&#x3008;', h: 0.04, d: 2.96, tclass: 'delim4c'},
{c: '&#x3009;', h: 0.04, d: 2.96, tclass: 'delim4c'},
{c: '/', h: 0.04, d: 2.96, tclass: 'delim4b'},
{c: '&#x2216;', h: 0.04, d: 2.96, tclass: 'delim4b'},
{c: '/', h: 0.04, d: 1.76, n: 30, tclass: 'delim2b'},
{c: '&#x2216;', h: 0.04, d: 1.76, n: 31, tclass: 'delim2b'},
// 30 - 3F
{c: '&#xF8EB;', h: .8, d: .15, delim: {top: 48, bot: 64, rep: 66}, tclass: 'delim'},
{c: '&#xF8F6;', h: .8, d: .15, delim: {top: 49, bot: 65, rep: 67}, tclass: 'delim'},
{c: '&#xF8EE;', h: .8, d: .15, delim: {top: 50, bot: 52, rep: 54}, tclass: 'delim'},
{c: '&#xF8F9;', h: .8, d: .15, delim: {top: 51, bot: 53, rep: 55}, tclass: 'delim'},
{c: '&#xF8F0;', h: .8, d: .15, delim: {bot: 52, rep: 54}, tclass: 'delim'},
{c: '&#xF8FB;', h: .8, d: .15, delim: {bot: 53, rep: 55}, tclass: 'delim'},
{c: '&#xF8EF;', h: .8, d: .15, delim: {top: 50, rep: 54}, tclass: 'delim'},
{c: '&#xF8FA;', h: .8, d: .15, delim: {top: 51, rep: 55}, tclass: 'delim'},
{c: '&#xF8F1;', h: .8, d: .15, delim: {top: 56, mid: 60, bot: 58, rep: 62}, tclass: 'delim'},
{c: '&#xF8FC;', h: .8, d: .15, delim: {top: 57, mid: 61, bot: 59, rep: 62}, tclass: 'delim'},
{c: '&#xF8F3;', h: .8, d: .15, delim: {top: 56, bot: 58, rep: 62}, tclass: 'delim'},
{c: '&#xF8FE;', h: .8, d: .15, delim: {top: 57, bot: 59, rep: 62}, tclass: 'delim'},
{c: '&#xF8F2;', h: .8, d: .15, delim: {rep: 63}, tclass: 'delim'},
{c: '&#xF8FD;', h: .8, d: .15, delim: {rep: 119}, tclass: 'delim'},
{c: '&#xF8F4;', h: .8, d: .15, delim: {rep: 62}, tclass: 'delim'},
{c: '|', h: .65, d: 0, delim: {top: 120, bot: 121, rep: 63}, tclass: 'vertical'},
// 40 - 4F
{c: '&#xF8ED;', h: .8, d: .15, delim: {top: 56, bot: 59, rep: 62}, tclass: 'delim'},
{c: '&#xF8F8;', h: .8, d: .15, delim: {top: 57, bot: 58, rep: 62}, tclass: 'delim'},
{c: '&#xF8EC;', h: .8, d: .15, delim: {rep: 66}, tclass: 'delim'},
{c: '&#xF8F7;', h: .8, d: .15, delim: {rep: 67}, tclass: 'delim'},
{c: '&#x3008;', h: 0.04, d: 1.76, n: 28, tclass: 'delim2c'},
{c: '&#x3009;', h: 0.04, d: 1.76, n: 29, tclass: 'delim2c'},
{c: '&#x2294;', h: 0, d: 1, n: 71, tclass: 'bigop1'},
{c: '&#x2294;', h: 0.1, d: 1.5, tclass: 'bigop2'},
{c: '&#x222E;', h: 0, d: 1.11, ic: 0.095, n: 73, tclass: 'bigop1c'},
{c: '&#x222E;', h: 0, d: 2.22, ic: 0.222, tclass: 'bigop2c'},
{c: '&#x2299;', h: 0, d: 1, n: 75, tclass: 'bigop1'},
{c: '&#x2299;', h: 0.1, d: 1.5, tclass: 'bigop2'},
{c: '&#x2295;', h: 0, d: 1, n: 77, tclass: 'bigop1'},
{c: '&#x2295;', h: 0.1, d: 1.5, tclass: 'bigop2'},
{c: '&#x2297;', h: 0, d: 1, n: 79, tclass: 'bigop1'},
{c: '&#x2297;', h: 0.1, d: 1.5, tclass: 'bigop2'},
// 50 - 5F
{c: '&#x2211;', h: 0, d: 1, n: 88, tclass: 'bigop1a'},
{c: '&#x220F;', h: 0, d: 1, n: 89, tclass: 'bigop1a'},
{c: '&#x222B;', h: 0, d: 1.11, ic: 0.095, n: 90, tclass: 'bigop1c'},
{c: '&#x222A;', h: 0, d: 1, n: 91, tclass: 'bigop1b'},
{c: '&#x2229;', h: 0, d: 1, n: 92, tclass: 'bigop1b'},
{c: '&#x228E;', h: 0, d: 1, n: 93, tclass: 'bigop1b'},
{c: '&#x2227;', h: 0, d: 1, n: 94, tclass: 'bigop1'},
{c: '&#x2228;', h: 0, d: 1, n: 95, tclass: 'bigop1'},
{c: '&#x2211;', h: 0.1, d: 1.6, tclass: 'bigop2a'},
{c: '&#x220F;', h: 0.1, d: 1.5, tclass: 'bigop2a'},
{c: '&#x222B;', h: 0, d: 2.22, ic: 0.222, tclass: 'bigop2c'},
{c: '&#x222A;', h: 0.1, d: 1.5, tclass: 'bigop2b'},
{c: '&#x2229;', h: 0.1, d: 1.5, tclass: 'bigop2b'},
{c: '&#x228E;', h: 0.1, d: 1.5, tclass: 'bigop2b'},
{c: '&#x2227;', h: 0.1, d: 1.5, tclass: 'bigop2'},
{c: '&#x2228;', h: 0.1, d: 1.5, tclass: 'bigop2'},
// 60 - 6F
{c: '&#x2210;', h: 0, d: 1, n: 97, tclass: 'bigop1a'},
{c: '&#x2210;', h: 0.1, d: 1.5, tclass: 'bigop2a'},
{c: '&#xFE3F;', h: 0.722, w: .65, n: 99, tclass: 'wide1'},
{c: '&#xFE3F;', h: 0.85, w: 1.1, n: 100, tclass: 'wide2'},
{c: '&#xFE3F;', h: 0.99, w: 1.65, tclass: 'wide3'},
{c: '&#x2053;', h: 0.722, w: .75, n: 102, tclass: 'wide1a'},
{c: '&#x2053;', h: 0.8, w: 1.35, n: 103, tclass: 'wide2a'},
{c: '&#x2053;', h: 0.99, w: 2, tclass: 'wide3a'},
{c: '[', h: 0.04, d: 1.76, n: 20, tclass: 'delim2'},
{c: ']', h: 0.04, d: 1.76, n: 21, tclass: 'delim2'},
{c: '&#xF8F0;', h: 0.04, d: 1.76, n: 22, tclass: 'delim2'},
{c: '&#xF8FB;', h: 0.04, d: 1.76, n: 23, tclass: 'delim2'},
{c: '&#xF8EE;', h: 0.04, d: 1.76, n: 24, tclass: 'delim2'},
{c: '&#xF8F9', h: 0.04, d: 1.76, n: 25, tclass: 'delim2'},
{c: '{', h: 0.04, d: 1.76, n: 26, tclass: 'delim2'},
{c: '}', h: 0.04, d: 1.76, n: 27, tclass: 'delim2'},
// 70 - 7F
{c: '<span style="font-size: 125%; position:relative; top:.95em">&#x221A;</span>', h: 0.04, d: 1.16, n: 113, tclass: 'root'},
{c: '<span style="font-size: 190%; position:relative; top:.925em">&#x221A;</span>', h: 0.04, d: 1.76, n: 114, tclass: 'root'},
{c: '<span style="font-size: 250%; position:relative; top:.925em">&#x221A;</span>', h: 0.06, d: 2.36, n: 115, tclass: 'root'},
{c: '<span style="font-size: 320%; position:relative; top:.92em">&#x221A;</span>', h: 0.08, d: 2.96, n: 116, tclass: 'root'},
{c: '<span style="font-size: 400%; position:relative; top:.92em">&#x221A;</span>', h: 0.1, d: 3.75, n: 117, tclass: 'root'},
{c: '<span style="font-size: 500%; position:relative; top:.9em">&#x221A;</span>', h: .12, d: 4.5, n: 118, tclass: 'root'},
{c: '<span style="font-size: 625%; position:relative; top:.9em">&#x221A;</span>', h: .14, d: 5.7, tclass: 'root'},
{c: '<span style="margin:.001em">||</span>', h:.65, d:0, delim: {top: 126, bot: 127, rep: 119}, tclass: 'vertical'},
{c: '&#x25B5;', h:.45, delim: {top: 120, rep: 63}, tclass: 'arrow1'},
{c: '&#x25BF;', h:.45, delim: {bot: 121, rep: 63}, tclass: 'arrow1'},
{c: '<span style="font-size: 67%; position:relative; top:.35em; margin-left:-.5em">&#x256D;</span>', h:.1, tclass: 'symbol'},
{c: '<span style="font-size: 67%; position:relative; top:.35em; margin-right:-.5em">&#x256E;</span>', h:.1, tclass: 'symbol'},
{c: '<span style="font-size: 67%; position:relative; top:.35em; margin-left:-.5em">&#x2570;</span>', h:.1, tclass: 'symbol'},
{c: '<span style="font-size: 67%; position:relative; top:.35em; margin-right:-.5em">&#x256F;</span>', h:.1, tclass: 'symbol'},
{c: '&#x25B5;', h:.5, delim: {top: 126, rep: 119}, tclass: 'arrow2'},
{c: '&#x25BF;', h:.5, delim: {bot: 127, rep: 119}, tclass: 'arrow2'}
],
cmti10: [
// 00 - 0F
{c: '&Gamma;', ic: 0.133, tclass: 'igreek'},
{c: '&Delta;', tclass: 'igreek'},
{c: '&Theta;', ic: 0.094, tclass: 'igreek'},
{c: '&Lambda;', tclass: 'igreek'},
{c: '&Xi;', ic: 0.153, tclass: 'igreek'},
{c: '&Pi;', ic: 0.164, tclass: 'igreek'},
{c: '&Sigma;', ic: 0.12, tclass: 'igreek'},
{c: '&Upsilon;', ic: 0.111, tclass: 'igreek'},
{c: '&Phi;', ic: 0.0599, tclass: 'igreek'},
{c: '&Psi;', ic: 0.111, tclass: 'igreek'},
{c: '&Omega;', ic: 0.103, tclass: 'igreek'},
{c: 'ff', ic: 0.212, krn: {'39': 0.104, '63': 0.104, '33': 0.104, '41': 0.104, '93': 0.104}, lig: {'105': 14, '108': 15}, tclass: 'italic'},
{c: 'fi', ic: 0.103, tclass: 'italic'},
{c: 'fl', ic: 0.103, tclass: 'italic'},
{c: 'ffi', ic: 0.103, tclass: 'italic'},
{c: 'ffl', ic: 0.103, tclass: 'italic'},
// 10 - 1F
{c: '&#x131;', a:0, ic: 0.0767, tclass: 'italic'},
{c: 'j', d:.2, ic: 0.0374, tclass: 'italic'},
{c: '&#x60;', tclass: 'iaccent'},
{c: '&#xB4;', ic: 0.0969, tclass: 'iaccent'},
{c: '&#x2C7;', ic: 0.083, tclass: 'iaccent'},
{c: '&#x2D8;', ic: 0.108, tclass: 'iaccent'},
{c: '&#x2C9;', ic: 0.103, tclass: 'iaccent'},
{c: '&#x2DA;', tclass: 'iaccent'},
{c: '?', d: 0.17, w: 0.46, tclass: 'italic'},
{c: '&#xDF;', ic: 0.105, tclass: 'italic'},
{c: '&#xE6;', a:0, ic: 0.0751, tclass: 'italic'},
{c: '&#x153;', a:0, ic: 0.0751, tclass: 'italic'},
{c: '&#xF8;', ic: 0.0919, tclass: 'italic'},
{c: '&#xC6;', ic: 0.12, tclass: 'italic'},
{c: '&#x152;', ic: 0.12, tclass: 'italic'},
{c: '&#xD8;', ic: 0.094, tclass: 'italic'},
// 20 - 2F
{c: '?', krn: {'108': -0.256, '76': -0.321}, tclass: 'italic'},
{c: '!', ic: 0.124, lig: {'96': 60}, tclass: 'italic'},
{c: '&#x201D;', ic: 0.0696, tclass: 'italic'},
{c: '#', ic: 0.0662, tclass: 'italic'},
{c: '$', tclass: 'italic'},
{c: '%', ic: 0.136, tclass: 'italic'},
{c: '&amp;', ic: 0.0969, tclass: 'italic'},
{c: '&#x2019;', ic: 0.124, krn: {'63': 0.102, '33': 0.102}, lig: {'39': 34}, tclass: 'italic'},
{c: '(', d:.2, ic: 0.162, tclass: 'italic'},
{c: ')', d:.2, ic: 0.0369, tclass: 'italic'},
{c: '*', ic: 0.149, tclass: 'italic'},
{c: '+', a:.1, ic: 0.0369, tclass: 'italic'},
{c: ',', a:-.3, d:.2, w: 0.278, tclass: 'italic'},
{c: '-', a:0, ic: 0.0283, lig: {'45': 123}, tclass: 'italic'},
{c: '.', a:-.25, tclass: 'italic'},
{c: '/', ic: 0.162, tclass: 'italic'},
// 30 - 3F
{c: '0', ic: 0.136, tclass: 'italic'},
{c: '1', ic: 0.136, tclass: 'italic'},
{c: '2', ic: 0.136, tclass: 'italic'},
{c: '3', ic: 0.136, tclass: 'italic'},
{c: '4', ic: 0.136, tclass: 'italic'},
{c: '5', ic: 0.136, tclass: 'italic'},
{c: '6', ic: 0.136, tclass: 'italic'},
{c: '7', ic: 0.136, tclass: 'italic'},
{c: '8', ic: 0.136, tclass: 'italic'},
{c: '9', ic: 0.136, tclass: 'italic'},
{c: ':', ic: 0.0582, tclass: 'italic'},
{c: ';', ic: 0.0582, tclass: 'italic'},
{c: '&#xA1;', ic: 0.0756, tclass: 'italic'},
{c: '=', a:0, d:-.1, ic: 0.0662, tclass: 'italic'},
{c: '&#xBF;', tclass: 'italic'},
{c: '?', ic: 0.122, lig: {'96': 62}, tclass: 'italic'},
// 40 - 4F
{c: '@', ic: 0.096, tclass: 'italic'},
{c: 'A', krn: {'110': -0.0256, '108': -0.0256, '114': -0.0256, '117': -0.0256, '109': -0.0256, '116': -0.0256, '105': -0.0256, '67': -0.0256, '79': -0.0256, '71': -0.0256, '104': -0.0256, '98': -0.0256, '85': -0.0256, '107': -0.0256, '118': -0.0256, '119': -0.0256, '81': -0.0256, '84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'},
{c: 'B', ic: 0.103, tclass: 'italic'},
{c: 'C', ic: 0.145, tclass: 'italic'},
{c: 'D', ic: 0.094, krn: {'88': -0.0256, '87': -0.0256, '65': -0.0256, '86': -0.0256, '89': -0.0256}, tclass: 'italic'},
{c: 'E', ic: 0.12, tclass: 'italic'},
{c: 'F', ic: 0.133, krn: {'111': -0.0767, '101': -0.0767, '117': -0.0767, '114': -0.0767, '97': -0.0767, '65': -0.102, '79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}, tclass: 'italic'},
{c: 'G', ic: 0.0872, tclass: 'italic'},
{c: 'H', ic: 0.164, tclass: 'italic'},
{c: 'I', ic: 0.158, tclass: 'italic'},
{c: 'J', ic: 0.14, tclass: 'italic'},
{c: 'K', ic: 0.145, krn: {'79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}, tclass: 'italic'},
{c: 'L', krn: {'84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'},
{c: 'M', ic: 0.164, tclass: 'italic'},
{c: 'N', ic: 0.164, tclass: 'italic'},
{c: 'O', ic: 0.094, krn: {'88': -0.0256, '87': -0.0256, '65': -0.0256, '86': -0.0256, '89': -0.0256}, tclass: 'italic'},
// 50 - 5F
{c: 'P', ic: 0.103, krn: {'65': -0.0767}, tclass: 'italic'},
{c: 'Q', d: 1, ic: 0.094, tclass: 'italic'},
{c: 'R', ic: 0.0387, krn: {'110': -0.0256, '108': -0.0256, '114': -0.0256, '117': -0.0256, '109': -0.0256, '116': -0.0256, '105': -0.0256, '67': -0.0256, '79': -0.0256, '71': -0.0256, '104': -0.0256, '98': -0.0256, '85': -0.0256, '107': -0.0256, '118': -0.0256, '119': -0.0256, '81': -0.0256, '84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'},
{c: 'S', ic: 0.12, tclass: 'italic'},
{c: 'T', ic: 0.133, krn: {'121': -0.0767, '101': -0.0767, '111': -0.0767, '114': -0.0767, '97': -0.0767, '117': -0.0767, '65': -0.0767}, tclass: 'italic'},
{c: 'U', ic: 0.164, tclass: 'italic'},
{c: 'V', ic: 0.184, krn: {'111': -0.0767, '101': -0.0767, '117': -0.0767, '114': -0.0767, '97': -0.0767, '65': -0.102, '79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}, tclass: 'italic'},
{c: 'W', ic: 0.184, krn: {'65': -0.0767}, tclass: 'italic'},
{c: 'X', ic: 0.158, krn: {'79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}, tclass: 'italic'},
{c: 'Y', ic: 0.194, krn: {'101': -0.0767, '111': -0.0767, '114': -0.0767, '97': -0.0767, '117': -0.0767, '65': -0.0767}, tclass: 'italic'},
{c: 'Z', ic: 0.145, tclass: 'italic'},
{c: '[', d:.1, ic: 0.188, tclass: 'italic'},
{c: '&#x201C;', ic: 0.169, tclass: 'italic'},
{c: ']', d:.1, ic: 0.105, tclass: 'italic'},
{c: '&#x2C6;', ic: 0.0665, tclass: 'iaccent'},
{c: '&#x2D9;', ic: 0.118, tclass: 'iaccent'},
// 60 - 6F
{c: '&#x2018;', ic: 0.124, lig: {'96': 92}, tclass: 'italic'},
{c: 'a', a:0, ic: 0.0767, tclass: 'italic'},
{c: 'b', ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'},
{c: 'c', a:0, ic: 0.0565, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'},
{c: 'd', ic: 0.103, krn: {'108': 0.0511}, tclass: 'italic'},
{c: 'e', a:0, ic: 0.0751, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'},
{c: 'f', ic: 0.212, krn: {'39': 0.104, '63': 0.104, '33': 0.104, '41': 0.104, '93': 0.104}, lig: {'105': 12, '102': 11, '108': 13}, tclass: 'italic'},
{c: 'g', a:0, d:.2, ic: 0.0885, tclass: 'italic'},
{c: 'h', ic: 0.0767, tclass: 'italic'},
{c: 'i', ic: 0.102, tclass: 'italic'},
{c: 'j', d:.2, ic: 0.145, tclass: 'italic'},
{c: 'k', ic: 0.108, tclass: 'italic'},
{c: 'l', ic: 0.103, krn: {'108': 0.0511}, tclass: 'italic'},
{c: 'm', a:0, ic: 0.0767, tclass: 'italic'},
{c: 'n', a:0, ic: 0.0767, krn: {'39': -0.102}, tclass: 'italic'},
{c: 'o', a:0, ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'},
// 70 - 7F
{c: 'p', a:0, d:.2, ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'},
{c: 'q', a:0, d:.2, ic: 0.0885, tclass: 'italic'},
{c: 'r', a:0, ic: 0.108, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}, tclass: 'italic'},
{c: 's', a:0, ic: 0.0821, tclass: 'italic'},
{c: 't', ic: 0.0949, tclass: 'italic'},
{c: 'u', a:0, ic: 0.0767, tclass: 'italic'},
{c: 'v', a:0, ic: 0.108, tclass: 'italic'},
{c: 'w', a:0, ic: 0.108, krn: {'108': 0.0511}, tclass: 'italic'},
{c: 'x', a:0, ic: 0.12, tclass: 'italic'},
{c: 'y', a:0, d:.2, ic: 0.0885, tclass: 'italic'},
{c: 'z', a:0, ic: 0.123, tclass: 'italic'},
{c: '&#x2013;', a:.1, ic: 0.0921, lig: {'45': 124}, tclass: 'italic'},
{c: '&#x2014;', a:.1, ic: 0.0921, tclass: 'italic'},
{c: '&#x2DD;', ic: 0.122, tclass: 'iaccent'},
{c: '&#x2DC;', ic: 0.116, tclass: 'iaccent'},
{c: '&#xA8;', tclass: 'iaccent'}
],
cmbx10: [
// 00 - 0F
{c: '&Gamma;', tclass: 'bgreek'},
{c: '&Delta;', tclass: 'bgreek'},
{c: '&Theta;', tclass: 'bgreek'},
{c: '&Lambda;', tclass: 'bgreek'},
{c: '&Xi;', tclass: 'bgreek'},
{c: '&Pi;', tclass: 'bgreek'},
{c: '&Sigma;', tclass: 'bgreek'},
{c: '&Upsilon;', tclass: 'bgreek'},
{c: '&Phi;', tclass: 'bgreek'},
{c: '&Psi;', tclass: 'bgreek'},
{c: '&Omega;', tclass: 'bgreek'},
{c: 'ff', ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 14, '108': 15}, tclass: 'bold'},
{c: 'fi', tclass: 'bold'},
{c: 'fl', tclass: 'bold'},
{c: 'ffi', tclass: 'bold'},
{c: 'ffl', tclass: 'bold'},
// 10 - 1F
{c: '&#x131;', a:0, tclass: 'bold'},
{c: 'j', d:.2, tclass: 'bold'},
{c: '&#x60;', tclass: 'baccent'},
{c: '&#xB4;', tclass: 'baccent'},
{c: '&#x2C7;', tclass: 'baccent'},
{c: '&#x2D8;', tclass: 'baccent'},
{c: '&#x2C9;', tclass: 'baccent'},
{c: '&#x2DA;', tclass: 'baccent'},
{c: '?', tclass: 'bold'},
{c: '&#xDF;', tclass: 'bold'},
{c: '&#xE6;', a:0, tclass: 'bold'},
{c: '&#x153;', a:0, tclass: 'bold'},
{c: '&#xF8;', tclass: 'bold'},
{c: '&#xC6;', tclass: 'bold'},
{c: '&#x152;', tclass: 'bold'},
{c: '&#xD8;', tclass: 'bold'},
// 20 - 2F
{c: '?', krn: {'108': -0.278, '76': -0.319}, tclass: 'bold'},
{c: '!', lig: {'96': 60}, tclass: 'bold'},
{c: '&#x201D;', tclass: 'bold'},
{c: '#', tclass: 'bold'},
{c: '$', tclass: 'bold'},
{c: '%', tclass: 'bold'},
{c: '&amp;', tclass: 'bold'},
{c: '&#x2019;', krn: {'63': 0.111, '33': 0.111}, lig: {'39': 34}, tclass: 'bold'},
{c: '(', d:.2, tclass: 'bold'},
{c: ')', d:.2, tclass: 'bold'},
{c: '*', tclass: 'bold'},
{c: '+', a:.1, tclass: 'bold'},
{c: ',', a:-.3, d:.2, w: 0.278, tclass: 'bold'},
{c: '-', a:0, lig: {'45': 123}, tclass: 'bold'},
{c: '.', a:-.25, tclass: 'bold'},
{c: '/', tclass: 'bold'},
// 30 - 3F
{c: '0', tclass: 'bold'},
{c: '1', tclass: 'bold'},
{c: '2', tclass: 'bold'},
{c: '3', tclass: 'bold'},
{c: '4', tclass: 'bold'},
{c: '5', tclass: 'bold'},
{c: '6', tclass: 'bold'},
{c: '7', tclass: 'bold'},
{c: '8', tclass: 'bold'},
{c: '9', tclass: 'bold'},
{c: ':', tclass: 'bold'},
{c: ';', tclass: 'bold'},
{c: '&#xA1;', tclass: 'bold'},
{c: '=', a:0, d:-.1, tclass: 'bold'},
{c: '&#xBF;', tclass: 'bold'},
{c: '?', lig: {'96': 62}, tclass: 'bold'},
// 40 - 4F
{c: '@', tclass: 'bold'},
{c: 'A', krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}, tclass: 'bold'},
{c: 'B', tclass: 'bold'},
{c: 'C', tclass: 'bold'},
{c: 'D', krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}, tclass: 'bold'},
{c: 'E', tclass: 'bold'},
{c: 'F', krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'bold'},
{c: 'G', tclass: 'bold'},
{c: 'H', tclass: 'bold'},
{c: 'I', krn: {'73': 0.0278}, tclass: 'bold'},
{c: 'J', tclass: 'bold'},
{c: 'K', krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'bold'},
{c: 'L', krn: {'84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}, tclass: 'bold'},
{c: 'M', tclass: 'bold'},
{c: 'N', tclass: 'bold'},
{c: 'O', krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}, tclass: 'bold'},
// 50 - 5F
{c: 'P', krn: {'65': -0.0833, '111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}, tclass: 'bold'},
{c: 'Q', d: 1, tclass: 'bold'},
{c: 'R', krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}, tclass: 'bold'},
{c: 'S', tclass: 'bold'},
{c: 'T', krn: {'121': -0.0278, '101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}, tclass: 'bold'},
{c: 'U', tclass: 'bold'},
{c: 'V', ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'bold'},
{c: 'W', ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'bold'},
{c: 'X', krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}, tclass: 'bold'},
{c: 'Y', ic: 0.025, krn: {'101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}, tclass: 'bold'},
{c: 'Z', tclass: 'bold'},
{c: '[', d:.1, tclass: 'bold'},
{c: '&#x201C;', tclass: 'bold'},
{c: ']', d:.1, tclass: 'bold'},
{c: '&#x2C6;', tclass: 'baccent'},
{c: '&#x2D9;', tclass: 'baccent'},
// 60 - 6F
{c: '&#x2018;', lig: {'96': 92}, tclass: 'bold'},
{c: 'a', a:0, krn: {'118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'bold'},
{c: 'b', krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'bold'},
{c: 'c', a:0, krn: {'104': -0.0278, '107': -0.0278}, tclass: 'bold'},
{c: 'd', tclass: 'bold'},
{c: 'e', a:0, tclass: 'bold'},
{c: 'f', ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 12, '102': 11, '108': 13}, tclass: 'bold'},
{c: 'g', a:0, d:.2, ic: 0.0139, krn: {'106': 0.0278}, tclass: 'bold'},
{c: 'h', krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}, tclass: 'bold'},
{c: 'i', tclass: 'bold'},
{c: 'j', d:.2, tclass: 'bold'},
{c: 'k', krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}, tclass: 'bold'},
{c: 'l', tclass: 'bold'},
{c: 'm', a:0, krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}, tclass: 'bold'},
{c: 'n', a:0, krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}, tclass: 'bold'},
{c: 'o', a:0, krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'bold'},
// 70 - 7F
{c: 'p', a:0, d:.2, krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}, tclass: 'bold'},
{c: 'q', a:0, d:.2, tclass: 'bold'},
{c: 'r', a:0, tclass: 'bold'},
{c: 's', a:0, tclass: 'bold'},
{c: 't', krn: {'121': -0.0278, '119': -0.0278}, tclass: 'bold'},
{c: 'u', a:0, krn: {'119': -0.0278}, tclass: 'bold'},
{c: 'v', a:0, ic: 0.0139, krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}, tclass: 'bold'},
{c: 'w', a:0, ic: 0.0139, krn: {'101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}, tclass: 'bold'},
{c: 'x', a:0, tclass: 'bold'},
{c: 'y', a:0, d:.2, ic: 0.0139, krn: {'111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}, tclass: 'bold'},
{c: 'z', a:0, tclass: 'bold'},
{c: '&#x2013;', a:.1, ic: 0.0278, lig: {'45': 124}, tclass: 'bold'},
{c: '&#x2014;', a:.1, ic: 0.0278, tclass: 'bold'},
{c: '&#x2DD;', tclass: 'baccent'},
{c: '&#x2DC;', tclass: 'baccent'},
{c: '&#xA8;', tclass: 'baccent'}
]
});
jsMath.Setup.Styles({
'.typeset .math': 'font-style: normal',
'.typeset .italic': 'font-style: italic',
'.typeset .bold': 'font-weight: bold',
'.typeset .cmr10': 'font-family: serif',
'.typeset .cal': 'font-family: cursive',
'.typeset .arrows': '',
'.typeset .arrow1': '',
'.typeset .arrow2': '',
'.typeset .harpoon': 'font-size: 125%',
'.typeset .symbol': '',
'.typeset .symbol2': '',
'.typeset .delim1': 'font-size: 133%; position:relative; top:.75em',
'.typeset .delim1b': 'font-size: 133%; position:relative; top:.8em; margin: -.1em',
'.typeset .delim1c': 'font-size: 120%; position:relative; top:.8em;',
'.typeset .delim2': 'font-size: 180%; position:relative; top:.75em',
'.typeset .delim2b': 'font-size: 190%; position:relative; top:.8em; margin: -.1em',
'.typeset .delim2c': 'font-size: 167%; position:relative; top:.8em;',
'.typeset .delim3': 'font-size: 250%; position:relative; top:.725em',
'.typeset .delim3b': 'font-size: 250%; position:relative; top:.8em; margin: -.1em',
'.typeset .delim3c': 'font-size: 240%; position:relative; top:.775em;',
'.typeset .delim4': 'font-size: 325%; position:relative; top:.7em',
'.typeset .delim4b': 'font-size: 325%; position:relative; top:.8em; margin: -.1em',
'.typeset .delim4c': 'font-size: 300%; position:relative; top:.8em;',
'.typeset .delim': '',
'.typeset .vertical': '',
'.typeset .greek': '',
'.typeset .igreek': 'font-style: italic',
'.typeset .bgreek': 'font-weight: bold',
'.typeset .bigop1': 'font-size: 133%; position: relative; top: .85em; margin:-.05em',
'.typeset .bigop1a': 'font-size: 100%; position: relative; top: .775em;',
'.typeset .bigop1b': 'font-size: 160%; position: relative; top: .7em; margin:-.1em',
'.typeset .bigop1c': 'font-size: 125%; position: relative; top: .75em; margin:-.1em;',
'.typeset .bigop2': 'font-size: 200%; position: relative; top: .8em; margin:-.07em',
'.typeset .bigop2a': 'font-size: 175%; position: relative; top: .7em;',
'.typeset .bigop2b': 'font-size: 270%; position: relative; top: .62em; margin:-.1em',
'.typeset .bigop2c': 'font-size: 250%; position: relative; top: .7em; margin:-.17em;',
'.typeset .wide1': 'font-size: 67%; position: relative; top:-.8em',
'.typeset .wide2': 'font-size: 110%; position: relative; top:-.5em',
'.typeset .wide3': 'font-size: 175%; position: relative; top:-.32em',
'.typeset .wide1a': 'font-size: 75%; position: relative; top:-.5em',
'.typeset .wide2a': 'font-size: 133%; position: relative; top: -.15em',
'.typeset .wide3a': 'font-size: 200%; position: relative; top: -.05em',
'.typeset .root': '',
'.typeset .accent': 'position: relative; top: .02em',
'.typeset .iaccent': 'position: relative; top: .02em; font-style: italic',
'.typeset .baccent': 'position: relative; top: .02em; font-weight: bold'
});
jsMath.Setup.Styles();
/*
* No access to TeX "not" character, so fake this
*/
jsMath.Macro('not','\\mathrel{\\rlap{\\kern 4mu/}}');
jsMath.Macro('joinrel','\\mathrel{\\kern-2mu}');
jsMath.Box.DelimExtend = jsMath.Box.DelimExtendRelative;
jsMath.Box.defaultH = 0.8;

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

View File

@ -0,0 +1,54 @@
About
**********
madIS is a extensible relational database system build upon the SQLite database and with extensions written in Python.
It was designed and created by a small team of developers at the MaDgIK lab of the National and Kapodistrian University of Athens, under the surpevising of professor Yannis Ioannidis.
The extensibility permits quick experimentation concerning data analysis tasks, rapid development of data processing workflows and serves in general as a simple and easy environment to test database related ideas without much effort.
madIS' query language is SQL with some syntactic "extensions" aiming to simplify query composition.
madIS main design goals are:
- To be easy, and versatile
- To be extremely productive for data analysis and data processing tasks
- Maximum reusability of extensions
In practice madIS has proved to be extremely easy when adding new functionalities to it, very fast in developing new workflows and most of all the majority of the external functions written for madIS, have proven to be reusable in new tasks for which they were not designed for.
madIS is suitable for
=======================
Complex data analysis tasks
----------------------------
In madIS it is very easy to create additional relational functions, or join against external files without first importing them into the database.
Additionally madIS offers a very fast multidimensional index, greatly speeding up multi-constraint joins, even when joining against external sources.
Data transformations
---------------------
madIS can already use the file system or network sources as tables. In addition, with a little Python knowledge, complex data transformation functions can be created and be used inside the database. All these can be done even without importing anything inside the database.
In addition madIS offers a very easy, to work with, workflow engine to automate the data transformation steps.
Database research
-------------------
If you wish to develop and test a new indexing structure, it can easily be developed in madIS. madIS uses Python for its extensions and already has plenty of code to start from.
.. note::
Due to madIS' SQLite core, the database format of madIS is exactly the same as SQLite's one.
This means that all SQLite databases are directly usable with madIS.
.. seealso::
* `SQLite <http://www.sqlite.org>`_
* `Python <http://www.python.org>`_
* `APSW <http://code.google.com/p/apsw/>`_

View File

@ -0,0 +1,215 @@
# -*- coding: utf-8 -*-
#
# madIS documentation build configuration file, created by
# sphinx-quickstart on Thu Nov 26 16:25:19 2009.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys, os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.append(os.path.abspath('.'))
sys.path.append(os.path.abspath(os.path.dirname(__file__)+'../../../'))
import functions
#sys.path.append(os.path.abspath(os.path.dirname(__file__)+'\\..\\..\\'))
# -- General configuration -----------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.jsmath', 'sphinx.ext.ifconfig']
# JSMath extension option
jsmath_path='jsMath/easy/load.js'
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.txt'
# The encoding of source files.
#source_encoding = 'utf-8'
def process_signature(app, what, name, obj, opts, sig, ann):
if what == 'function':
return ""
def setup(app):
app.connect('autodoc-process-signature', process_signature)
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'madIS'
copyright = u'2009-2010, L. Stamatogiannakis, M. Triantafyllidi, M. Vayanou, M. Kyriakidi'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = functions.VERSION
# The full version, including alpha/beta/rc tags.
release = version
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of documents that shouldn't be included in the build.
#unused_docs = []
# List of directories, relative to source directory, that shouldn't be searched
# for source files.
exclude_trees = []
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
add_module_names = False
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. Major themes that come with
# Sphinx are currently 'default' and 'sphinxdoc'.
html_theme = 'default'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
html_theme_options = {} #{'stickysidebar': True}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
html_logo = 'madislog.png'
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_use_modindex = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
html_split_index = True
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = ''
# Output file base name for HTML help builder.
htmlhelp_basename = 'madisdoc'
# -- Options for LaTeX output --------------------------------------------------
# The paper size ('letter' or 'a4').
#latex_paper_size = 'letter'
# The font size ('10pt', '11pt' or '12pt').
#latex_font_size = '10pt'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'madis.tex', u'madIS Documentation',
u'mlmlml', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# Additional stuff for the LaTeX preamble.
#latex_preamble = ''
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_use_modindex = True
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {'http://docs.python.org/': None}

View File

@ -0,0 +1,192 @@
Examples
********
.. _pivoting:
.. highlight:: mysql
Pivot
=====
First import data from a tsv file (Tab Separated Values) with :func:`~functions.vtable.file.file` virtual table function.
:download:`sales.tsv <../../functions/row/testing/sales.tsv>`
.. code-block:: python
>>> sql("""create table sales as
... select Product,Region,Month,cast(Sales as int) as Sales
... from
... (file 'testing/sales.tsv' 'dialect:tsv' header:t)""")
>>> sql("select * from sales")
Product | Region | Month | Sales
----------------------------------
Cars | Athens | 2010-01 | 200
Cars | Athens | 2010-02 | 130
Bikes | NY | 2010-01 | 10
Bikes | NY | 2010-02 | 30
Cars | NY | 2010-01 | 100
Cars | NY | 2010-02 | 160
Cars | Paris | 2010-01 | 70
Cars | Paris | 2010-02 | 20
Bikes | Paris | 2010-01 | 100
Bikes | Paris | 2010-02 | 20
Boats | Paris | 2010-01 | 200
Let's say we want the result to be a table with columns:
- Product
- NY: the total sales in NY for this product
- Paris: the total sales in Paris for this product
- Athens: the total sales in Athens for this product
We will perform the aggregate function *sum* over *Sales* column, grouping by *Product* and *Region* columns.
Then :func:`~functions.aggregate.packing.vecpack` must be performed over *Region* and *Sales* sums, grouping on *Product*.
To use :func:`~functions.aggregate.packing.vecpack` the first argument must be a pack of the dimensions. This is the
result of packing the distinct *Region* values, grouping over all the table.
.. code-block:: python
>>> sql("""select Product,unpackcol(vpck)
... from
... (select Product,vecpack(rpk,Region,salessum) as vpck
... from
... (select pack(distinct Region) as rpk from sales),
... (select Product,Region,sum(sales) as salessum
... from sales group by Product,Region)
... group by Product)""")
Product | Paris | NY | Athens
------------------------------
Bikes | 120 | 40 | 0
Boats | 200 | 0 | 0
Cars | 90 | 260 | 330
.. _applexample:
Application scenario
====================
In this example we implement a simple application for query recommendation based on user's country of origin. The input data come from a web portal's logs.
The query mining workflow includes the following five main steps:
1. Import the portal log files into a relational table
2. Use time-heuristics so as to identify coherent query sessions.
Assign and store a new, reconstructed session id for each record in the logs
3. Preprocess and clean logged queries text
4. Retrieve IP-to-country information from the web and combine this with the IP information from portal log files
so as to assign a country code to each one of the logged sessions
5. Apply an `Apriori-based <http://en.wikipedia.org/wiki/Apriori_algorithm>`_ technique for extracting frequent term sets per country.
A sample from the log file used is presented below:
.. code-block:: none
36506 guest X.X.X.134 p93t9q5eqaa0u0p8isd9skp1n6 en ("paradis riedinger") search_sim 2010-01-01 00:28:23
36507 guest X.X.X.134 p93t9q5eqaa0u0p8isd9skp1n6 en ("paradis riedinger") view_brief 2010-01-01 00:28:34
36508 guest X.X.X.134 p93t9q5eqaa0u0p8isd9skp1n6 en ("paradis riedinger") view_brief 2010-01-01 00:28:34
36509 guest X.X.X.134 p93t9q5eqaa0u0p8isd9skp1n6 en ("paradis riedinger") view_full 2010-01-01 00:28:42
36510 guest X.X.X.55 a9qo379qnl5hbbria6tj6nlp95 de (creator all "frank leonhard") search_adv 2010-01-01 00:28:44
36511 guest X.X.X.55 a9qo379qnl5hbbria6tj6nlp95 de (creator all "frank leonhard") view_brief 2010-01-01 00:29:10
36512 guest X.X.X.55 a9qo379qnl5hbbria6tj6nlp95 de (creator all "frank leonhard") search_res 2010-01-01 00:29:18
**Step 1**
Initially, log files which are available in the Tab Separated Value format, are imported into a relational table.
The import process is easily implemented in madIS using the :func:`~functions.vtable.file.file` function,
by selecting the appropriate columns from the ".tsv" file.
::
create table logs as
select C1 as id, C2 as userid, C3 as userip, C4 as sesid, C6 as query, c7 as action, C8 as date
from file('raw_logs.tsv','delimiter:\t','quoting:QUOTE_NONE');
**Step 2**
Thereafter, session reconstruction, a common task in web usage mining, is performed.
In this example it uses a predefined inactivity thresholds to break in-coming sessions.
Such functionality is performed in madIS through the :func:`~functions.aggregate.subgroup.datediffbreak` function,
which takes as an argument the inactivity threshold (as well as some additional parameters) and returns the new session ids.
In the following madSQL segment, where the efficient employment of the described function is presented,
the inactivity threshold has been set to 30 minutes (provided in milliseconds).
::
alter table logs add sesidnew text;
update logs
set sesidnew=
(select bgroupid
from
( cache select datediffbreak(sesid,id,date,30*60*1000,'order',date,id)
from logs
where sesid not null group by sesid)
where C1=id )
where sesid is not null;
**Step 3**
Then, focusing on issued queries, the distinct queries per session are retrieved from the logs
and a variety of query text processing steps take place.
However, a great amount of malformed queries has been observed, so it is only queries of valid text in utf8 encoding that are selected.
This filtering step is performed using the :func:`~functions.row.text.isvalidutf8` function in the where clause of the corresponding madSQL fragment. 
Thereafter, stop word removal is performed over the selected queries through the corresponding function.
Moreover, since queries are issued and logged using the Common Query Language (CQL) syntax, an additional filtering step is executed for removing *CQL* constructs,
through the madIS function :func:`~functions.row.text.cqlkeywords`. The processed queries are then stored in table *QueriesPerSession*.
One of the advantages offered by madIS framework, is that all the powerful Python capabilities and
open source libraries for text processing can be exploited for the rapid implementation of customized functions,
hence significantly easing the “flow-level programming”, in madSQL.
::
create table QueriesPerSession as
select filterstopwords(cqlkeywords(query)) as cleanquery , sesidnew, userid
from logs
where action like 'search%' and cleanquery!='' and isvalidutf8(query)
group by query, sesidnew;
**Step 4**
Aiming towards the extraction of term associations per country, an external data source is fetched from the web,
containing the mapping between IP ranges and countries.
Again, the :func:`~functions.vtable.file.file` function is employed for fetching the URL resource and importing the corresponding data in a main memory
indexed table using the :func:`~functions.vtable.cache.cache` function of madIS. The fetched data source specifies the IP ranges in IP long number format,
so the logged IPs have to be converted to the same format by using :func:`~functions.row.iptools.ip2long` function, and then to be subsequently matched
to the imported ranges. However, since each session may contain requests from multiple IPs (due to dynamic IPs, etc.),
it is only the first encountered IP that is considered for each session.
The first IP for each session is obtained using the :func:`~functions.aggregate.selection.minrow` function, comparing the corresponding records ids.
The generated mapping from each session to a country code is stored in table Session2Country.
::
create temporary table Session2Country as
select sesidnew, CountryCode
from
(select ip2long(minrow(id,userip)) as iplong, sesidnew
from logs
group by sesidnew),
(cache select cast(C3 as integer) as ipfrom, cast(C4 as integer) as ipto, C5 as CountryCode
from file('http://.../GeoIPCountryCSV.zip','dialect:csv','compression:t'))
where iplong>=ipfrom and iplong <= ipto;
**Step 5**
Then information regarding text of queries, and session to country mappings is jointly used so as to extract term associations,
with an `apriori-like <http://en.wikipedia.org/wiki/Apriori_algorithm>`_ technique, using the aggregate function :func:`~functions.aggregate.mining.freqitemsets`.
Frequent query term sets are computed over each one of the country codes that occur in Session2Country table.
::
create table FrequentItemsets as
select 'nat', CountryCode,
freqitemsets(cleanquery,'threshold:2','maxlen:5')
from QueriesPerSession as qs, Session2Country as sc
where qs.sesidnew = sc.sesidnew
group by CountryCode;

View File

@ -0,0 +1,20 @@
Where to create functions
-------------------------
Row functions HOWTO
-------------------
Aggregate functions HOWTO
-------------------------
Virtual table functions HOWTO
-----------------------------
Debugging
---------
Global settings
---------------

View File

@ -0,0 +1,49 @@
.. madIS documentation master file, created by
sphinx-quickstart on Thu Nov 26 16:25:19 2009.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
madIS documentation
===================
+--------------------------------------------------------------+
| |
|" Making the simple complicated is commonplace; |
| making the complicated simple, awesomely simple... |
| that's creativity. " |
| |
+--------------------------------------------------------------+
.. centered:: madIS |version|
madIS is a extensible relational database system build upon the SQLite database and with extensions written in Python.
The extensibility permits quick experimentation concerning data analysis tasks, rapid development of data processing workflows and serves in general as a simple and easy environment to test database related ideas without much effort.
madIS' query language is SQL with some syntactic "extensions" aiming to simplify query composition.
madIS is hosted at http://code.google.com/p/madis/
Contents:
.. toctree::
:maxdepth: 3
install
about
manual
usefulnotes
examples
row
aggregate
vtable
people
license
thanks
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

View File

@ -0,0 +1,60 @@
Installing madIS
================
The requirements for using madIS are:
1. **Python 2.6.x** or **2.7.x**: You can download a windows distribution of Python from
http://www.python.org/download/releases/ .You need to download the latest
Python in the 2.6 or 2.7 series. madIS doesn't currently work with Python 3.0.
.. note::
Most Linux distributions come with Python 2.6 or Python 2.7 preinstalled.
2. **APSW**:
Windows:
Download the windows distribution of `APSW` from http://code.google.com/p/apsw/downloads/list .
Linux:
Most Linux distributions contain in their repositories a sufficiently recent version of `APSW`.
If you use Ubuntu 10.04 and later, install the `python-apsw` package::
sudo apt-get install python-apsw
In case `APSW` is not provided with your Linux distribution of choise, `APSW` should be build from source.
The detailed instructions for building `APSW` can be found at:
http://apidoc.apsw.googlecode.com/hg/build.html#recommended
A quick command line to build and install `APSW` is::
sudo python setup.py fetch --all --missing-checksum-ok build install
If you are using Ubuntu and wish to build `APSW` from source, you also need the packages::
build-essential libreadline5-dev zlib1g-dev python-dev
MacOS:
On *MacOS 10.6* install `APSW` and `readline` via `easy_install`::
easy_install apsw
easy_install readline
On *MacOS 10.7* you have to build `APSW` from source (as showed above), for which you'll
also need *Xcode*.
After building `APSW`, install `readline` via `easy_install`::
sudo easy_install readline
3. Download the madIS archive (.zip) from:
http://code.google.com/p/madis/downloads/list
4. Uncompress above zip file
5. Use madis by entering into the new "madis/" path and executing "python mterm.py"

View File

@ -0,0 +1,32 @@
Copyright and License
=====================
Copyright (C) 2009-2013 Lefteris Stamatogiannakis, Mei Li Triantafyllidi,
Ioannis Foufoulas, Maria Vayanou, Marialena Kyriakidi.
The external libraries used throughout the madIS project are copyright
of their respective authors.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
* The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
* Altered source versions must be plainly marked as such, and must not
be misrepresented as being the original software.
* This notice may not be removed or altered from any source
distribution.
Alternatively you may strike the license above and use it under any
OSI approved open source license such as those listed at
http://opensource.org/licenses/alphabetical

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -0,0 +1,564 @@
.. highlight:: sql
Manual
#########
Functions
*********
Functions are the main mechanism with which extensions are implemented.
The are three kinds of functions:
- Row functions
- Aggregate functions
- Virtual tables
madIS also provides syntactic extensions, in its supported SQL, that simplify the use of above functions.
.. seealso::
* :ref:`row-functions-list`
* :ref:`aggregate-functions-list`
* :ref:`vtable-functions-list`
Row functions
Programmable row functions work in a similar way as standard SQL row functions such as *abs()*, *lower()* and *upper()*.
Their implementation is done in Python, and they are able to use all Python facilities and libraries.
An example of an SQL statement using an external row function is::
mterm> select detectlang('Il en est des livres comme du feu de nos foyers');
french
Above statement executes the *detectlang* function, which tries to detect the language of a snippet of text by analysing its statistical properties.
On the above example the snippet is a Voltaire quote, and the correct answer from *detectlang* is that it is in french.
If we wished to do the same for multiple quotes then we could use the following SQL statement (assuming the existence of a *quotes_table* which contains the column *quote*)::
mterm> select detectlang(quote) from quotes_table;
french
english
...
In general external row functions can be used in exactly the same way as SQLite's internal row functions.
.. seealso::
* :ref:`row-functions-list`
* :func:`~functions.row.langtools.detectlang`
Creating and using a simple row function
----------------------------------------
Python files that implement row functions live in "/src/functions/row". A single python file can contain many row functions.
Now lets create a simple "hello world" row function.
Go to the "src/functions/row/" path of madIS, and create "hello.py". Then write the following code in it:
.. sourcecode:: python
def hello(*args):
return "hello "+args[0]
hello.registered=True
The code above, looks like and indeed is, a simple python function that takes multiple arguments.
The only peculiarity is the "hello.registered=True" line.
What this line does, is to instruct madIS to register this function with the SQLite core.
This way, Python functions that we don't wish to become SQLite row functions, can simply be used without any change to them.
To execute the above row function we start madIS and execute an SQL query which uses the new *hello* row function::
% python mterm.py
mterm> select hello("world");
hello world
The SQL query above, shows the results of calling *hello* function with "world" as a parameter.
As happens very often in SQL queries, parameter values are retrieved from tables.
Below we show such an example::
mterm> select "world" as a UNION select "all" as a;
all
world
Query executed in 0 min. 0 sec 3 msec
mterm> select hello(a) from (select "world" as a UNION select "all" as a);
hello all
hello world
Query executed in 0 min. 0 sec 7 msec
When developing custom row functions it is very useful to browse through the already developed row functions, in the "functions/row" path of madIS.
Most of the time a custom function can be based on an already existing one.
.. note::
If a developer wishes to add a row function that in essence is a part of a pre-existing Python library.
The madIS convention is to put the library files in the "src/lib/" path of madIS and then create a row function in the "row" path of madIS which imports and calls the necessary methods of the actual library in "lib" path.
For an example of this see *detectlang.*
.. seealso::
* :ref:`row-functions-list`
Aggregate functions
Programmable aggregate functions work in a similar way as standard SQL aggregate functions such as *sum()*, *min()* and *max()*.
Their implementation is done in Python, and as is also the case for row functions, all Python facilities and libraries are available.
An example of an SQL statement using an external aggregate function is::
mterm> select "term1+term2" as a UNION select "term2 term3" as a;
term1+term2
term2 term3
mterm> select concatterms(a)
from (select "term1+term2" as a UNION select "term2 term3" as a);
term1+term2 term2 term3
The statement above, executes the :func:`~functions.aggregate.text.concatterms` function, which concatenates strings of terms together, while keeping the terms disjoint.
Using the aggregate function above, together with a row function is also possible.
To concatenate together only the input string keywords we could execute the following SQL::
mterm> select concatterms(keywords(a))
from (select "term1+term2" as a UNION select "term2 term3" as a);
term1 term2 term2 term3
.. seealso::
* :ref:`aggregate-functions-list`
* :func:`~functions.aggregate.text.concatterms`
* :func:`~functions.row.keywords.keywords`
Creating and using a simple aggregate function
----------------------------------------------
Python files that implement aggregate functions live in
"/src/functions/aggregate". A single python file can contain many aggregate functions.
Now, lets create a simple aggregate function.
Go to the "src/functions/aggregate/" path of madIS, and create "myconcat.py". Then write the following code in it:
.. sourcecode:: python
class quotedconcatterms:
registered=True
def __init__(self):
self.result=[]
def step(self, *args):
if len(args[0])!=0:
self.result.append("'"+args[0]+"'")
def final(self):
return ' '.join(self.result)
What the aggregate function above does, is to concatenate strings of terms together while inserting single quotes around each string.
In the "__init__" method of class *quotedconcatterms* we initialize all needed variables (self.result).
The "step" method, is called by SQLite's engine for every tuple of the group which is fed into the aggregate function.
At the end of the group, the "final" method is called to return the final result.
The "registered=True" line above, as in row functions, instructs madIS to load the class into the SQLite engine as an aggregate function.
To execute the above aggregate function we start madIS and execute an SQL query which uses the new *quotedconcatterms*
aggregate function (notice the single quotes around each input string in the results)::
% python mterm.py
mterm> select quotedconcatterms(keywords(a)) from (select "term1+term2" as a UNION select "term2 term3" as a);
'term1 term2' 'term2 term3'
As is the case with aggregate functions it is very useful to browse through the
already developed aggregate functions, in the "functions/aggregate" path of
madIS, to find snippets of code implementing wished for, functionality.
.. seealso::
* :ref:`aggregate-functions-list`
Virtual tables
Virtual tables are actually functions that take parameters and output table like data. They can be used in the SQL syntax wherever
a regular table would be placed.
Virtual tables are one of the most powerful function classes in madIS. They can function in a regular table fashion,
where the output data is finite in number, or in a streaming fashion, where the output stream can be infinite.
This, together with the SQL syntax extensions of madIS, creates a very powerful environment with which a variety
of standard madIS features have been developed, such as the *multisets*, *workflow engine*,
*direct data load from filesystem or network*, etc.
Typical examples of virtual tables sources are files, SQL query resulsets, or even external programs output.
In addition to the above, virtual tables can also function as programmable indexes on the input data,
negotiating with the database engine about which constraints or ordering they'll be able to answer/produce quickly.
The only madIS virtual table that implements and works as an index is :ref:`cache <tutcache>`, which offers, a created on the fly,
multidimensional index.
Using virtual tables can be done in a variety of ways.
The first is **parametric table**::
% python mterm.py
mterm> select * from file('./demo/continents.tsv') limit 2;
Asia|AF
Europe|AL
What the example above does, is to read the tab separated "continents.tsv" filesystem file as a table.
Using the standard *limit* SQL directive, the output is limited to only 2 rows.
An example showing the streaming nature of virtual tables is::
mterm> select output from pipe('query:date');
Fri Feb 1 12:34:55 EET 2000
""
mterm> select strsplit(output,'delimiter: ') from pipe('query:date');
Mon|Feb||1|12:34:56|EET|2000
The first of the above examples executes system's "date" command through the use of the :mod:`~functions.vtable.pipe` virtual table.
Notice that the :mod:`~functions.vtable.pipe` virtual table has a default returned schema, having one column named *output.*
The second of the above examples does the same as the previous one, however it also splits :mod:`~functions.vtable.pipe`'s output,
using space as a delimiter, into multiple columns through :func:`~functions.row.formating.strsplit` row function.
At this point, we should skip a little ahead, and mention two peculiarities on the queries above.
The first one is the "query:date" parameter of :mod:`~functions.vtable.pipe`.
This in madIS is called a *named parameter*, where the part before the ":" is a parameter's name and the second part is a parameter's value.
The second peculiarity is the that the row function :func:`~functions.row.formating.strsplit` returns multiple columns.
This is a :ref:`multiset <tutmultiset>` function, able to return as many columns and rows as it wishes.
To see the column names and column types of second query above, we can execute::
mterm> coltypes select strsplit(output,'delimiter: ') from pipe('query:date');
C1|text
C2|text
C3|text
C4|text
C5|text
C6|text
C7|text
The "coltypes" in the above query may look like a special function of the terminal but in essence it is also
a virtual table that takes as input a query and returns a table having as first column the column names
of the inside query and as second column the column types of the inside query.
.. note::
- :mod:`~functions.vtable.coltypes` is able to be used in front of a query because it is in its :ref:`inverted form <inversion>`.
We'll discuss madIS SQL extensions in the following section.
- We won't present a simple virtual table implementation as they are too complex to be presented here.
For more see the already existing tables in the "/src/functions/vtable" path of madIS, and the
`APSW documentation <http://apidoc.apsw.googlecode.com/hg/vtable.html>`_ concerning virtual tables.
.. seealso::
* :ref:`vtable-functions-list`
* :mod:`~functions.vtable.file`
* :mod:`~functions.vtable.pipe`
* :func:`~functions.row.formating.strsplit`
* :mod:`~functions.vtable.coltypes`
.. _inversion:
madIS SQL extensions
********************
While developing madIS, we realized that some simple ideas like virtual table chaining, were too difficult to be written in plain SQL.
In addition using a virtual table was more difficult than it needed to be, due to having to "create" a virtual table before using it.
To solve the problems above, we've extended SQL with the following features:
- Parametric virtual tables are automatically created and deleted
- Syntax inversion
The first of above features, is quite apparent. The user doesn't have to manage virtual tables,
madIS does everything it is needed automatically in the background, creating a virtual table just before a query using it, is executed, and
deleting it after the query's execution completes. This is why we could directly
read from the file system, with the *file* virtual table, in the previous section.
Inversions are slightly more complex.
So lets start with a simple virtual table chaining example and invert it::
mterm> select * from output('d.txt', "query:select * from pipe('query:date')");
1
What the query above does, is to call system's "date" command, through the *pipe* virtual table, and write the output back to the file system (in the file named "d.txt").
The *output* virtual table returns back if it succeeded or not (1 or 0).
Because chaining virtual tables on the manner shown above, proved to require a lot of effort and in addition was error prone, syntax inversion was added to madIS' accepted SQL syntax.
The inversion syntax is::
VTname 'param1' 'param2'... namedparam1:valueofnamedparam1 ... SQL_query
Whenever madIS' SQL preprocessor "sees" above syntax it turns it into::
select * from Vtname('param1', 'param2' ..., 'namedparam1:valueofnamedparam1' ... , 'query:SQL_query')
So lets use the inverted syntax, to reissue the query above::
mterm> output 'd.txt' pipe date;
1
In practice a wide range of functionalities has been possible with inversions.
The *coltypes* example shown in the previous section "feels" like special functionality that is implemented execution engine in other DB systems.
In madIS, most of the special commands are in essence virtual tables (or row functions) in their inverted form.
The same inverted syntax is also offered by madIS, for row functions.
So instead of::
mterm> select detectlang('Il en est des livres comme du feu de nos foyers');
french
We could have written it as such::
mterm> detectlang 'Il en est des livres comme du feu de nos foyers';
french
A problem arises with row inversions.
How to distinguish between the case of passing the actual query to a row function, and passing the **results** of the query to the row function.
madIS has the *var* row function, which sets and retrieves a madIS variable.
Some examples of its usage::
mterm> var 'demo' 'time'; -- This puts value 'time' to the variable named 'demo'
time
mterm> var 'demo'; -- This retrieves the value of variable 'demo'
time
mterm> select var('demo','time');--The same queries in their not inverted forms
time
mterm> select var('demo');
time
What would happen if instead of the value "time" we had a plain query?::
mterm> var 'demo2' select var('demo');
select var('demo')
mterm> var 'demo2';
select var('demo')
We see above, that instead of putting the result of the query "select var('demo')" into "demo2", it put the query's text in it.
This makes it complex to pass values between variables, forcing us to do::
mterm> select var('demo2', (select var('demo'))); --Non inverted syntax
time
mterm> var 'demo2';
time
Due to this, a directive which forces the use of the results of the embedded query has been created, to ease use cases such as above::
mterm> var 'demo2' 'essence of';
essence of
mterm> var 'demo' 'time';
time
mterm> var 'demo2' FROM var 'demo';
time
mterm> var 'demo2';
time
Notice the "FROM" keyword after the "var 'demo2'" part of the query.
What "FROM" does is to transform the query in its non inverted syntax shown above.
.. note::
Both "FROM" and "OF" are accepted as synonyms, when specifying the use of embedded query results.
.. seealso::
* :mod:`~functions.vtable.output`
* :mod:`~functions.vtable.pipe`
* :func:`~functions.row.langtools.detectlang`
* :func:`~functions.row.variables.var`
.. _tutmultiset:
Multisets
*********
Early in the development of madIS, the need to return multiple rows and columns from row and aggregate functions, arose.
This need was satisfied through the use of *expand* virtual table and an accompanying Python API (*CompBuffer*) to create multisets.
Virtual table *expand* works by looking into the results of a SQL query, and if
it finds a specially formatted tuple (in *CompBuffer's* format), it decompresses it,
looks for schema information, and then starts returning one by one the compressed data to the outside query.
If more than one *CompBuffers* are found, then their schemata are consolidated into one.
CompBuffer tries to avoid writing on the hard disk, by compressing in memory, the data fed
into it and only after a threshold of 10 Mb of compressed data is reached, spilling over into the hard disk.
To make multiset usage transparent to the user, madIS' SQL preprocessor, inserts automatically
the *expand* virtual table whenever a multiset producing function is met.
To flag a row or aggregate function as a multiset one, the programmer has to set the function's attribute
"multiset" to "True". This is done in the same way as for the "registered" function's attribute.
An example of a multiset row function which produces multiple columns is::
mterm> select strsplit("one,two,three");
one|two|three
And one which produces multiple rows is::
mterm> select strsplitv("one,two,three");
one
two
three
Both of the functions above, break their input on "comma" by default.
.. seealso::
* :func:`~functions.row.formating.strsplit`
* :func:`~functions.row.formating.strsplitv`
.. _tutcache:
On the fly multidimensional indexing (the *cache* virtual table)
****************************************************************
Working with external sources directly, has the major problem of not being able to put acceleration structures on them (indexing), unless materializing them in the form of a database table.
Joins with external sources, in particular, are very slow, forcing the SQLite core to do multiple sequential passes on the virtual tables tied to the external sources.
To solve the problems above, the *cache* virtual table was created.
The way it works is this:
- At the beginning it does one pass over the results of the input query, and keeps them in memory
- Then it negotiates with SQLite's core about what constraints and order bys, the core would like to have answered as fast as possible
- It builds a very fast multidimensional index based on the negotiations above
- It waits until the core starts sending queries on the above constraints, and returns the results using the just build multidimensional index
- At the end of the query it throws away the cached query's data and the multidimensional index
The multidimensional index is based on kd-trees and is implemented in Python, using the virtual table indexing API.
It is a very fast to be build index, and extremely fast on answering queries involving many constraints.
The multidimensional index is also designed to be memory efficient, needing O(number_of_dataset_rows) memory no matter the number of indexed dimensions.
In practice, it has been up to 10 times faster on interval joins compared to SQLite's native indexing, and as the dimensions grow in number its speed advantage becomes bigger.
An example of *cache* use is::
% cd demo
% python mterm.py
mterm> select country.c2, continent.c1
from file('countries.tsv') as country,
file('continents.tsv') as continent
where country.c1=continent.c2;
Aruba|Americas
Antigua and Barbuda|Americas
United Arab Emirates|Asia
Afghanistan|Asia
. . . . . . . . .
Query executed in 0 min 2 sec 40 msec
mterm> select country.c2, continent.c1
from file('countries.tsv') as country,
(CACHE file 'continents.tsv') as continent
where country.c1=continent.c2;
Aruba|Americas
Antigua and Barbuda|Americas
United Arab Emirates|Asia
Afghanistan|Asia
. . . . . . . . .
Query executed in 0 min 0 sec 71 msec
The queries above, do a direct join on the filesystem's files "countries.tsv" and "continents.tsv" (in the "demo" path of madIS).
The first query doesn't do any caching at all, so it is forced to do multiple sequential reads of the "continents" file, to execute the join.
The second query, using the inverted syntax, caches the "continents" file and creates the required indexes to execute the join quickly.
The speed difference between the two queries is quite significant (cached version of query is 28x faster).
For bigger datasets and more constraints the speed advantage could be even greater.
.. seealso::
* :mod:`~functions.vtable.cache`
* :mod:`~functions.vtable.file`
Workflows
*********
From the beginning madIS was designed for building complete data processing systems with it.
In madIS, workflows are viewed as a series of queries to be executed sequentially.
The main function that implements madIS' workflow engine is :mod:`~functions.vtable.exec` virtual table::
mterm> select 'select 5';
select 5
mterm> exec select 'select 5';
1
Virtual table :mod:`~functions.vtable.exec`, takes as input an SQL query, executes it and then operates on the **results** of the input query, executing them sequentially and returning "1" if all the queries executed successfully, or throwing an error if any queries failed to execute correctly.
This peculiar design (its a meta-meta function), enables :mod:`~functions.vtable.exec` to work in tandem with other virtual tables that feed to it the workflows to be executed.
The most frequent combination is::
mterm> exec flow file 'workflow.sql';
What the query above does, is to open and read the "workflow.sql" filesystem file via
the *file* virtual table, then feed its results into the *flow* virtual table
which collects in one line the "broken into multiple lines" queries, and finally
to feed the resulting queries to :mod:`~functions.vtable.exec` virtual table which will execute them.
The above combination of virtual tables presents, one the most powerful aspects of madIS.
Namely the ability to create complex functionality (in this instance a workflow engine), by quickly combining simple entities.
.. note::
Another benefit of using (or abusing) a relational database to implement a workflow engine, is that all ACID properties
of the database are still present during the workflow processing. Unfortunately due to limitations of the SQLite core,
transactional execution of madIS workflows isn't fully working yet (see :ref:`tutlimitations`).
.. seealso::
* :mod:`~functions.vtable.exec`
* :mod:`~functions.vtable.flow`
* :mod:`~functions.vtable.file`
Designing and building a data processing system with madIS
**********************************************************
Concerning the design of a data processing system.
The required steps that have to be made when **designing** a data processing system with madIS are:
1. Define the problem you are trying to solve
2. Break the problem into workflows
3. Break the workflows into queries
4. Find the functions that the queries will need
5. Find the Python libraries that the functions will need
The steps above, are mostly self evident, and should be made in the order that they are presented.
To **build** the data processing system, the above steps have to be followed, finding/building the required entities (functions, queries), for each step, **going from bottom to top** (Step 5 to Step 2),
In practice we have found that there is always some overlap between the designing and building stages and between steps.
Great care should be given, when designing, on the most difficult and time consuming step, which is step 1. When step 1 is successfully executed, the speed with which the rest of the steps are designed and following that, building them from bottom to top, is extremely fast in our experience.
.. note::
An example of a madIS workflow can be found in the :ref:`examples section <applexample>`.
.. _tutlimitations:
Limitations of madIS
********************
The limitations of madIS are:
- Due to SQLite's inability to simultaneously use multiple CPUs to execute a query, madIS' query execution is done by only one CPU.
This will be partially solved in the future through the use of the *map* virtual table, which will be able to execute a row function on multiple data rows in parallel.
For more heavy processing concurrency, functions and virtual tables enabling madIS to be used on clusters are in the planning stage
- Due to SQLite's locking semantics, workflows inside a parent workflow, aren't in their own transactions.
So when a child workflow fails, the whole parent transaction rolls back.
This will be solved whenever SQLite fixes the problem where the database's system schema table is locked whenever a table is deleted

View File

@ -0,0 +1,14 @@
Project Documentation
=====================
This page contains the Project Modules documentation.
Modules
-------
.. toctree::
:maxdepth: 4
row
aggregate
vtable

View File

@ -0,0 +1,12 @@
People
======
Core developers
---------------
- Lefteris Stamatogiannakis
- Mei Li Triantafyllidi
Extensions developers
---------------------
- Maria Vayanou
- Marialena Kyriakidi

View File

@ -0,0 +1,18 @@
Thanks
======
madIS project wouldn't exist without the amazing work of several other people, and the
Open Source spirit.
Specifically we would like to thank:
- APSW's Roger Binns
- SQLite's authors
In both of above projects, the work ethic and quality of their code are of an
extremely high level. Nearly every line of their code is extensively tested.
In madIS we stressed the code of both of above projects as much as we could, and
they handled it beautifully.

View File

@ -0,0 +1,190 @@
Useful notes
*************
This section contains useful tips to help with understanding function usage, ease
shell interaction and introduce some basic characteristics of the dynamic virtual tables.
.. _unotesexamples:
Understanding function examples
===============================
While reading each function's description, you will notice examples like this:
>>> sql("select ifthenelse(1>0,'yes','no') as answer")
answer
------
yes
Because examples also serve as tests for madIS's functions, they are coded and displayed as actual Python code. The string inside Python function "sql()" is
an SQL query, having its results displayed in the lines following it. Query results in examples also include the column names for clarity.
However in the interactive shell column names are not shown. In the interactive shell, the same as above example, would look like the following::
mterm> select ifthenelse(1>0,'yes','no') as answer;
yes
Query executed in 0 min. 0 sec 33 msec
.. _unotesparameters:
Understanding function parameters
=================================
**Named parameters**
All types of functions (row, aggregate and virtual table) can take simple or named parameters.
For simple parameters, ordering is important and should follow function's definition. Named
parameters can be placed anywhere in the parameters lists, with few exceptions that are clearly stated.
Named parameters are strings (so they must be placed inside quotes) using the format *paramname:paramvalue*.
For example :mod:`~functions.vtable.file` function is declared as::
file(location[, formatting options])
where *location* is a simple parameter containing the file name or network resource to read from,
and *formatting options* is a list of named parameters (eg. parameter *dialect* which accepts one of values *tsv* or *csv*).
So using this function to import a csv file would look like this::
select * from file('myfile','dialect:csv');
By using inverted syntax (see :ref:`SQL extensions <inversion>`), the query would look like this::
select * from (file 'myfile' dialect:csv);
Notice that non named parameters must be quoted. However named parameters quoting is optional. Also parameters are separated with spaces instead of commas.
If a space character appears in a named parameter's value field, quoting should be used.
So importing a file that uses spaces as value delimiters, would look like following (using inverted syntax)::
select * from (file 'myfile' 'delimiter: ');
An example of a function definition which contains named parameters is :mod:`~functions.vtable.output`::
output(query:None, file[, formatting options])
The definition above states, that the function output receives the named parameter *query* which has no default value (the value following the ":" character
of a named parameter in a functions' definition, represents the default value).
.. _unoteqparameter:
**The query parameter**
Named parameter *query* shown in the definition above, defines which SQL query the function *output* will execute
and then write the query's results in the given *file*.
When using, in inverted syntax, a function that takes a *query* parameter (see :ref:`SQL extensions <inversion>`) the *query* keyword should be omitted.
Instead the actual query should be placed at the end of the statement. For example to output, in inverted syntax, some query's result, the following could be used::
output 'outfile' dialect:tsv select * from table1;
In non inverted syntax, this is equivalent to::
select * from output('query:select * from table1','outfile','dialect:tsv');
Inverting queries that include the *query* parameter, permits "pipelining" of many virtual table functions, while using an easy to read syntax.
So to re-order a file and add line numbers you can do::
output 'outfile.csv' rowidvt select * from (file 'infile.csv') order by C2;
Let's look at the details of this query. :mod:`~functions.vtable.file` function reads *infile.csv* and returns the data as a table.
Returned data are then ordered by column C2.
The result of the query, *select \* from (file 'infile.csv') order by C2* is the *query* parameter for :mod:`~functions.vtable.rowidvt` function.
This function adds a *rowid* column to the query result that indicates the order of the row in the result (and not in the initial table).
The result of :mod:`~functions.vtable.rowidvt` function is forwarded into :mod:`~functions.vtable.output` which writes the result in the *outfile.csv* file.
.. _unotesreturntypes:
Understanding function return types
===================================
To understand how function return types works, make sure you understand how `SQLite types <http://www.sqlite.org/datatype3.html>`_ work.
The return type of the row and aggregate madIS functions refers to the storage class typically returned by the function.
Virtual table functions return a table having a static (or dynamic) schema with column names and `types affinity <http://www.sqlite.org/datatype3.html#affinity>`_.
To clarify the difference of the returned types of row/aggregate functions and virtual table functions consider the following example::
mterm> select * from (select kwnum('lol') as a) where a=='1';
Query executed in 0 min. 0 sec 17 msec
Here :func:`~functions.row.text.kwnum` function returns the number of keywords of the 'lol' string which is an integer.
Although the first returned column (named *a*) is of integer type, the literal text '1' in the *where* part is not converted to an integer,
so the condition fails. In the following example, by using the built in SQLite function *cast*, an integer type affinity
is suggested so the text literal '1' is automatically converted to an integer and the condition is evaluated to true.
::
mterm> select * from (select cast(kwnum('lol') as int) as a) where a=='1';
1
Query executed in 0 min. 0 sec 21 msec
In conclusion, the returned values from row and aggregate functions, even :ref:`multisets <tutmultiset>` do not also imply data affinity.
.. note::
The same result could be reached using the virtual table functions, eg. :mod:`~functions.vtable.typing` or :mod:`~functions.vtable.setschema`.
.. _unotesshell:
Shell interaction
=================
In madIS's interactive shell mode some helpful shell commands and functions helping with complex query composition are supported.
These can be listed in the terminal with the *.help* command.
**Names function**
Function :mod:`~functions.vtable.names` is a virtual table function that operates over a query (See :ref:`unotesparameters`)
and returns the column names of the query result.
::
mterm> names select * from file('test.csv','header:t') ;
City|Region|Country|Population
Query executed in 0 min. 0 sec 24 msec
Function :mod:`~functions.vtable.coltypes`, has similar functionality, additionally presenting the column's
`type affinity <http://www.sqlite.org/datatype3.html#affinity>`_ when this information is contained in its input.
::
mterm> coltypes select * from file('/home/meili/Desktop/test.csv','header:t') ;
City|text
Region|text
Country|text
Population|text
.. _unotesemptyschema:
Empty schema exception
======================
A price to pay for using virtual tables having dynamic schema creation, is that if no data are provided, for example an empty file
to the :mod:`~functions.vtable.file` function or
a query that returns no rows to virtual tables that accept input *queries* (eg. :mod:`~functions.vtable.cache` function), is an exception as a result::
mterm> select * from (cache select 5 as a where a!=5);
Madis SQLError: operator cache: Cannot initialise dynamic schema virtual table without data
To avoid this issue, especially in automatic flow execution where a flow crash is undesirable, the :mod:`~functions.vtable.setschema` function can be used.
*Setschema* is virtual table function that enforces a given schema. In the case of non empty resultsets, it can be used to project,
rename and typecast inner query columns, while in case of an empty resultset, it works as a static schema definition.
::
mterm> select * from (setschema 'a' cache select 5 as a where a!=5);
Query executed in 0 min. 0 sec 62 msec
In the example above, *cache* function has a possibility of producing an empty schema exception. Applying the *setschema* function with the desirable schema
(column a with NONE type) this problem is avoided.
Other possible causes of empty schema exceptions are also :ref:`multiset <tutmultiset>` functions which are actually implemented
through the :mod:`~functions.vtable.expand` virtual table function.
.. _unotesefficiencyvt:
Efficiency in streaming virtual tables
======================================
Virtual table functions that work as streams do not need to materialise the whole input/output data streams before returning them, they can produce them on demand.
So executing, for example a *join*, between streaming virtual tables for a huge volume of data is not a good idea, as the data will have to be re-produced
over and over again. Using :ref:`cache <tutcache>` virtual table function on one of the *streaming* queries will significantly increase performance.

View File

@ -0,0 +1,175 @@
Virtual table concept in madIS
==============================
Virtual table can be any piece of code that returns its results as list of lists. It will be used in madSQL in the FROM part of a query.
Example::
select * from file('data.tsv');
In this case data are produced from external sources. Many madis virtual tables take a query as an input, execute it and returns its results transformed.
(See :ref:`Query parameter <unoteqparameter>`). In that case the vtable "call" could be inverted in the query. (see :ref:`SQL extensions <inversion>`).
Example::
rowidvt select * from table1 limit 3;
Creating a virtual table function
----------------------------------------
Virtual table fuctions are the most advanced operator in madIS. Existing virtual table functions can be organized by increasing implementation complexity in three categories:
- Single boolean output vt functions with query input: Virtual table functions that take an input, do sth and return 1 or 0. Example table fuctions are :mod:`~functions.vtable.exec`
- Iterative output: Vts that take input and returns many data (iterator of list).
Its call of the iterator retuns a list with each row data. In this category falls :mod:`~functions.vtable.file` operator, as well as :mod:`~functions.vtable.expand`, :mod:`~functions.vtable.rowidvt`, etc.
- Advanced: Advanced vt's that need the index capability of virtual tables. In this category falls only :mod:`~functions.vtable.cache` functions. These functions must implement virtual tables from scratch as described in
`APSW documentation <http://apidoc.apsw.googlecode.com/hg/vtable.html>`_.
All virtual table functions are created in XXXX folder. Every virtual table function must be single module.
Detailed documentation of virtual table API could be found in `APSW documentation <http://apidoc.apsw.googlecode.com/hg/vtable.html>`_.
In madIS there are used mostly two specific types of Virtual table functions, that helper libraries have been implemented to simplify
their implementation.
So implementing a virtual table function, is feasible either by following the `APSW API <http://apidoc.apsw.googlecode.com/hg/vtable.html>`_
and adding the flags for madIS, either by using the helper libraries, as explained below.
To continue reading, have a look to the Virtual table function API in APSW and play with toggle function and a virtual table call.
Example::
mterm> toggle tracing;
tracing is now: True
Query executed in 0 min. 0 sec 4 msec
mterm> select * from (file 'data.csv');
executetrace(u"create virtual table temp.vt_144176563 using file('data.csv','automatic_vtable:1')")
executetrace(u'select * from (SELECT * FROM vt_144176563 );',None)
...
executetrace(u'drop table temp.vt_144176563;')
Query executed in 0 min. 0 sec 14 msec
mterm> toggle vtdebug;
executetrace(u"SELECT toggle('vtdebug');",None)
vtdebug is now: True
Query executed in 0 min. 0 sec 4 msec
mterm> select * from (file 'data.csv');
....
Toggle is a row function that toggles the value of :ref:`madIS global settings<>`
Important flags for madIS VT functions
--------------------------------------
registered=True # set this flag to register in madis the function, if set to false the module is not loaded.
external_stream=True # Set this flag if no query parameter can be used.
Impementing single boolean output virtual table function
--------------------------------------------------------
The
def function()
from madis.vtout import SourceNtoOne
class SourceNtoOne:
def __init__(self,func,boolargs=None,nonstringargs=None,needsescape=None,notsplit=None,connectionhandler=False,retalways=False):
To create iterative VT's the madIS vtiterable could be used that hide some of the implementation details, or it can be build from scratch as in APSW, documentation. (http://apsw.googlecode.com/svn/publish/vtable.html) If vtiterable is not used, no standard parameter parsing will be available.
MUST BE SET TO USE VT in madis:
One VT - one file in vtable folder
registered=True ( as in all operators)
external_stream=True (if the operator does not accept query parameter)
Source function must be implemented!!
::
#Cursor Iterator
class TableCursor: # INTERFACE
def __init__(self): # when called for first time, it must probably identify the schema, if it is not dynamic
pass
def __iter__(self):
pass
def next(self):
pass
def close(self):
pass
::
class TableVT: #INTERFACE
def __init__(self,envdict,largs,dictargs): #DO NOT DO ANYTHING HEAVY it, will be called before querying the table
pass
def getdescription(self):
"""
must return a list of tuples (column name, columntype), if type not available leave it empty or None eg.(col,)
example:
[('column1','int'),('column2',),('column3','text')]
"""
return schemalist
def open(self):
"""
After the first time it is called getdescription function must return table instance schema
Must returns VT cursor
"""
return TableCursor()
def destroy(self): # Called when Table instance is destroyed (on drop statement), OPTIONAL
pass
.. function:: TableVT.__init__(self,envdict,largs,dictargs)
Parameters:
:envdict:
Dictionary with enviromental variables (correspond to APSW parameters of VTModule.Create)
:tablename: name of the table that will be created.
:db: instance of the connection to the database
:dbname: database name
:modulename: The string name under which the module was registered???????
:largs: table function list arguments
:dictargs: dictionary table function named arguments eg. type:int -> dictargs['type']='int'
def Source():
return SourceVT(TableVT,boolargs,nonstringargs,needsescape,notsplit)
class SourceVT:
def __init__(self,table,boolargs=None,nonstringargs=None,needsescape=None,staticschema=False,notsplit=None):
.. params:
Parameters
:table: Class implementing TableVT interface
:boolargs: List of parameter names that will be chnged to True/False if they are accordingly t/f
:nonstringargs: Dictionary of parameter names that will be tranformed according to their value , eg. string input to dialect object {'dialect':{'line':line(),'tsv':tsv(),'csv':defaultcsv()}}
:needsescape: List of parameter names that that include escape sequences eg. \n, \t etc.
:staticschema: True if TableVT.open does not need to be executed before getdescription can be called
:notsplit: List of parameter names that should not be splitted in named parameters eg. ['http'] for do not splitting http://server.com

View File

@ -0,0 +1,12 @@
executing madSQL workflow
logging on workflows
flowname
variables in workflows
passing variable in new workflow execution
Transcactions in workflows

View File

@ -0,0 +1,22 @@
-- This is a simple example of bulk harvesting an OAI-PMH service. The data are then converted from XML to a single relational table.
-- Due to the extreme slowness and unreliability of OAI-PMH protocol, we first fetch all data into a plain text file. If the transmission breaks, you should continue the transfer on a different file (e.g. 'rawdata1.txt'), so as to no overwrite previously fetched data.
output 'rawdata.txt' select * from (oaiget metadataPrefix:oai_dc 'http://citeseerx.ist.psu.edu/oai2');
-- After fetching all of the above 'rawdataX' files, concatenate them into a single one ('rawdata.txt').
-- We then want to find out which XML keys the 'rawdata' file contains. We restrict our key search to keys under "record".
select jgroupunion(jdictkeys(c1)) from (xmlparse root:record fast:1 file 'rawdata.txt.gz');
-- ["record/header/identifier","record/header/datestamp","record/metadata/dc/@/schemalocation","record/metadata/dc/title","record/metadata/dc/creator","record/metadata/dc/subject","record/metadata/dc/description","record/metadata/dc/contributor","record/metadata/dc/publisher","record/metadata/dc/date","record/metadata/dc/format","record/metadata/dc/type","record/metadata/dc/identifier","record/metadata/dc/source","record/metadata/dc/language","record/metadata/dc/relation","record/metadata/dc/rights"]
-- Finally we create the "article" table using the keys from above that interest us
create table article as
select regexpr(':([^:]*)$', header_identifier) as header_identifier, header_datestamp, metadata_dc_schemalocation, metadata_dc_title, metadata_dc_creator, metadata_dc_subject, metadata_dc_description, metadata_dc_contributor, metadata_dc_publisher, metadata_dc_date, metadata_dc_format, metadata_dc_type, metadata_dc_identifier, metadata_dc_source, metadata_dc_language, metadata_dc_relation, metadata_dc_rights
from (
xmlparse strict:0 '["record/header/identifier","record/header/datestamp","record/metadata/dc/@/schemalocation","record/metadata/dc/title","record/metadata/dc/creator","record/metadata/dc/subject","record/metadata/dc/description","record/metadata/dc/contributor","record/metadata/dc/publisher","record/metadata/dc/date","record/metadata/dc/format","record/metadata/dc/type","record/metadata/dc/identifier","record/metadata/dc/source","record/metadata/dc/language","record/metadata/dc/relation","record/metadata/dc/rights"]'
file 'rawdata.txt' );

View File

@ -0,0 +1,85 @@
-- First of all download http://dblp.uni-trier.de/xml/dblp.xml.gz
-- To find the XML keys inside above XML and under the "article" tag, execute.
select jgroupunion(jdictkeys(c1)) from (xmlparse root:article fast:1 file 'dblp.xml.gz');
-- ["article/@/mdate","article/@/key","article/author","article/title/*","article/journal","article/volume","article/month","article/year","article/cdrom","article/ee","article/url","article/@/publtype","article/editor","article/publisher","article/pages","article/number","article/cite","article/cite/@/label","article/crossref","article/booktitle","article/note","article/@/rating","article/@/reviewid"]
-- We do the same for "www" and "inproceedings" tags.
select jgroupunion(jdictkeys(c1)) from (xmlparse root:www fast:1 file 'dblp.gz');
--["www/@/mdate","www/@/key","www/author","www/title","www/year","www/url","www/editor","www/booktitle","www/note","www/crossref","www/cite","www/ee","www/note/@/type","www/author/@/bibtex"]
select jgroupunion(jdictkeys(c1)) from (xmlparse root:inproceedings fast:1 file 'dblp.xml.gz');
--["inproceedings/@/mdate","inproceedings/@/key","inproceedings/author","inproceedings/title/*","inproceedings/pages","inproceedings/year","inproceedings/booktitle","inproceedings/month","inproceedings/url","inproceedings/note","inproceedings/cdrom","inproceedings/ee","inproceedings/crossref","inproceedings/cite","inproceedings/editor","inproceedings/cite/@/label","inproceedings/@/publtype","inproceedings/number"]
-- We create the article, www and inproceedings tables.
create table article as
select * from (
xmlparse '["article/@/mdate","article/@/key","article/author","article/title/*","article/journal","article/volume","article/month","article/year","article/cdrom","article/ee","article/url","article/@/publtype","article/editor","article/publisher","article/pages","article/number","article/cite","article/cite/@/label","article/crossref","article/booktitle","article/note","article/@/rating","article/@/reviewid"]' fast:1 file 'dblp.xml.gz' );
create table www as select * from (xmlparse '["www/@/mdate","www/@/key","www/author","www/title","www/year","www/url","www/editor","www/booktitle","www/note","www/crossref","www/cite","www/ee","www/note/@/type","www/author/@/bibtex"]' fast:1 file 'dblp.xml.gz');
create table inproceedings as select * from (xmlparse '["inproceedings/@/mdate","inproceedings/@/key","inproceedings/author","inproceedings/title/*","inproceedings/pages","inproceedings/year","inproceedings/booktitle","inproceedings/month","inproceedings/url","inproceedings/note","inproceedings/cdrom","inproceedings/ee","inproceedings/crossref","inproceedings/cite","inproceedings/editor","inproceedings/cite/@/label","inproceedings/@/publtype","inproceedings/number"]' fast:1 file 'dblp.xml.gz');
-- Lets say that we want to find the author tenure dates from the data. We'll do it by using a heuristic method, where the "oldest" author among a paper's author list is considered to be the "professor". Please NOTE that the used heuristic is very unreliable.
-- We start by creating a table that will contain author and his publication years.
create table authorpubyear as select jsplitv(t2j(author)) as author, year from article;
-- From author's publications we find the oldest one.
create table authorminyear as select author,min(year) as year from authorpubyear group by author;
create index idxauthorminyear on authorminyear(author);
-- For articles that have multiple authors (XMLPARSE uses TAB for multiple values on the same key, this is why we use "like '%TAB%'" below), find their minyear and select the author having the minimum minyear among them.
create table professors as
select minrow(myear,author) as pauthor,pyear from (
select
key,
author,
(select authorminyear.year from authorminyear where authorminyear.author=a.author) as myear,
pyear
from
(select key,jsplitv(t2j(author)) as author,year as pyear from article where author like '% %') as a
) group by key;
-- We assume that the first time that an author appeared as a professor in a paper, is his tenure year.
create table tenures as select pauthor,min(pyear) as tyear from professors group by pauthor;
-- Now, lets calculate some other statistics.
-- Number of per author publications before tenure
select pauthor,count(year) from authorpubyear, tenures where authorpubyear.author=tenures.pauthor and authorpubyear.year<tenures.tyear group by pauthor;
-- Distribution of number of publications before tenure
select btyear,count(btyear) from (select pauthor,count(year) as btyear from authorpubyear, tenures where authorpubyear.author=tenures.pauthor and authorpubyear.year<tenures.tyear group by pauthor) group by btyear;
-- Top 100 number of coauthors per author
select author1, coauths from (select author1, count(distinct author2) as coauths from (select jpermutations(t2j(author),2) as author from article where author like '% %') group by author1) order by coauths desc limit 100;
-- And run 5 steps of the PageRank algorithm on the graph created from author paper collaborations.
--Authorank
create table authorlinks as select distinct * from (select jpermutations(t2j(author),2) as author from article where author like '% %');
create index idxauthor1 on authorlinks(author1);
create table authorank as select author, 1.0 as rank,(select count(author1) from authorlinks where author1=author) as linkcount from (select distinct(author1) as author from authorlinks);
create index idxauthorank on authorank(author);
update authorank set rank=1.0;
update authorank set rank=0.15+0.85*(select sum(rank/linkcount) from authorlinks al,authorank ar where al.author2=ar.author and al.author1=authorank.author);
update authorank set rank=0.15+0.85*(select sum(rank/linkcount) from authorlinks al,authorank ar where al.author2=ar.author and al.author1=authorank.author);
update authorank set rank=0.15+0.85*(select sum(rank/linkcount) from authorlinks al,authorank ar where al.author2=ar.author and al.author1=authorank.author);
update authorank set rank=0.15+0.85*(select sum(rank/linkcount) from authorlinks al,authorank ar where al.author2=ar.author and al.author1=authorank.author);
update authorank set rank=0.15+0.85*(select sum(rank/linkcount) from authorlinks al,authorank ar where al.author2=ar.author and al.author1=authorank.author);

View File

@ -0,0 +1,41 @@
-- This is a simple example of harvesting Greek government decisions data from http://opendata.diavgeia.gov.gr/
-- First of all put file diavgeiaget.py in functionslocal/vtable/
-- Following query fetches the data
output 'rawdata.txt' select * from (diavgeiaget);
-- If the transmission breaks (it happens very often) then continue by using
-- output 'rawdataY.txt' select * from (diavgeiaget datefrom:DD-MM-YYYY);
-- where Y is an increasing number (so as to not overwrite previously fetched data), and you can get DD-MM-YYYY from the last <ns3:submissionTimestamp>YYYY-MM-DD....</ns3:submissionTimestamp> field in the data you've recieved
-- After fetching all of the above 'rawdataY' files, concatenate them into a single one ('rawdata.txt').
-- We then want to find out which XML keys the 'rawdata' file contains. We restrict our key search to keys under "decisionexpanded".
select jgroupunion(jdictkeys(c1)) from (xmlparse root:decisionexpanded select utf8clean(c1) from (file 'rawdata.txt'));
-- ["decisions/decisionexpanded/ada","decisions/decisionexpanded/submissiontimestamp","decisions/decisionexpanded/metadata/protocolnumber","decisions/decisionexpanded/metadata/date","decisions/decisionexpanded/metadata/subject","decisions/decisionexpanded/metadata/organization/@/uid","decisions/decisionexpanded/metadata/organization/label","decisions/decisionexpanded/metadata/organization/latinname","decisions/decisionexpanded/metadata/organizationunit/@/uid","decisions/decisionexpanded/metadata/organizationunit/label","decisions/decisionexpanded/metadata/decisiontype/@/uid","decisions/decisionexpanded/metadata/decisiontype/label","decisions/decisionexpanded/metadata/tags/tag/@/uid","decisions/decisionexpanded/metadata/tags/tag/label","decisions/decisionexpanded/metadata/relativefek/issue","decisions/decisionexpanded/metadata/relativefek/year","decisions/decisionexpanded/url","decisions/decisionexpanded/documenturl","decisions/decisionexpanded/metadata/relativefek/feknumber","decisions/decisionexpanded/metadata/extrafields/extrafield/@/name","decisions/decisionexpanded/metadata/extrafields/extrafield/label","decisions/decisionexpanded/metadata/extrafields/extrafield/value","decisions/decisionexpanded/metadata/tags/tag/@/nil","decisions/decisionexpanded/metadata/iscorrectedbyada","decisions/decisionexpanded/metadata/relativeada","decisions/decisionexpanded/metadata/organization/units/unit/@/uid","decisions/decisionexpanded/metadata/organization/units/unit/label","decisions/decisionexpanded/metadata/iscorrectionofada"]
-- We then create the "decisions" table using the keys from above that interest us
create table decisions as
select * from (
xmlparse '["decisionexpanded/ada","decisionexpanded/submissiontimestamp","decisionexpanded/metadata/protocolnumber","decisionexpanded/metadata/date","decisionexpanded/metadata/subject","decisionexpanded/metadata/organization/@/uid","decisionexpanded/metadata/organization/label","decisionexpanded/metadata/organization/latinname","decisionexpanded/metadata/organizationunit/@/uid","decisionexpanded/metadata/organizationunit/label","decisionexpanded/metadata/decisiontype/@/uid","decisionexpanded/metadata/decisiontype/label","decisionexpanded/metadata/tags/tag/@/uid","decisionexpanded/metadata/tags/tag/label","decisionexpanded/metadata/relativefek/issue","decisionexpanded/metadata/relativefek/year","decisionexpanded/url","decisionexpanded/documenturl","decisionexpanded/metadata/relativefek/feknumber","decisionexpanded/metadata/extrafields/extrafield/@/name","decisionexpanded/metadata/extrafields/extrafield/label","decisionexpanded/metadata/extrafields/extrafield/value","decisionexpanded/metadata/tags/tag/@/nil","decisionexpanded/metadata/iscorrectedbyada","decisionexpanded/metadata/relativeada","decisionexpanded/metadata/organization/units/unit/@/uid","decisionexpanded/metadata/organization/units/unit/label","decisionexpanded/metadata/iscorrectionofada"]'
select utf8clean(c1) from
(file 'rawdata.txt')
);
-- Finally we delete the duplicate ada (decision ids)
delete from decisions where rowid not in (
select rowid from decisions group by ada
);

View File

@ -0,0 +1,137 @@
"""
.. function:: diavgeiaget(url, verb, metadataPrefix,...)
Fetches data from an OAIPMH service, using resumption tokens to fetch large datasets.
- If no *verb* is provided then *verb* is assumed to be 'ListRecords'.
- If no *metadataPrefix* is provided then *verb* is assumed to be 'ListMetadataFormats', which will list
all metadata formats.
:Returned table schema:
Column C1 as text
Examples:
>>> sql("select * from diavgeiaget('verb:ListRecords', 'metadataPrefix:ctxo')") # doctest:+ELLIPSIS +NORMALIZE_WHITESPACE
Traceback (most recent call last):
...
OperatorError: Madis SQLError:
Operator OAIGET: An OAIPMH URL should be provided
>>> sql("select * from (diavgeiaget verb:ListRecords metadataPrefix:ctxo 'http://oaiurl' )") # doctest:+ELLIPSIS +NORMALIZE_WHITESPACE
Traceback (most recent call last):
...
OperatorError: Madis SQLError:
Operator OAIGET: <urlopen error [Errno -2] Name or service not known>
"""
from functions.vtable import vtbase
import functions
import time
registered=True
external_stream=True
class diavgeiaget(vtbase.VT):
def VTiter(self, *parsedArgs, **envars):
def buildURL(baseurl, opts):
return '?'.join([ baseurl, '&'.join([x+'='+unicode(y) for x,y in opts if y!=None]) ])
import urllib2
import re
opts= self.full_parse(parsedArgs)[1]
yield ('c1', 'text')
if 'datefrom' not in opts:
opts['datefrom']='01-01-1000'
if 'output' not in opts:
opts['output']='full'
if 'order' not in opts:
opts['order']='asc'
if 'http' not in opts:
opts['http']='//opendata.diavgeia.gov.gr/api/decisions'
baseurl='http:'+opts['http']
findcount=re.compile(r"""<count>[^\d]*?(\d+)[^\d]*?</count>""", re.DOTALL| re.UNICODE)
findtotal=re.compile(r"""<total>[^\d]*?(\d+)[^\d]*?</total>""", re.DOTALL| re.UNICODE)
findfrom=re.compile(r"""<from>[^\d]*?(\d+)[^\d]*?</from>""", re.DOTALL| re.UNICODE)
count=total=fromv=lastfromv=None
firsttime=True
del(opts['http'])
opts=list(opts.iteritems())
url=buildURL(baseurl, opts)
def buildopener():
o = urllib2.build_opener()
o.addheaders = [
('Accept', '*/*'),
('Connection', 'Keep-Alive'),
('Content-type', 'text/xml')
]
return o
opener=buildopener()
errorcount=0
while True:
try:
for i in opener.open( url, timeout=1200 ):
if count==None:
t=findcount.search(i)
if t:
count=int(t.groups()[0])
if total==None:
t=findtotal.search(i)
if t:
errorcount=0
total=int(t.groups()[0])
if fromv==None:
t=findfrom.search(i)
if t:
errorcount=0
fromv=int(t.groups()[0])
yield (unicode(i.rstrip("\n"), 'utf-8'),)
if count==None or total==None or fromv==None:
break
fromv=fromv+count
if fromv>total:
break
url=buildURL(baseurl, opts+[('from', fromv)])
lastfromv=fromv
count=total=fromv=None
firsttime=False
except Exception,e:
if errorcount<10 and not firsttime:
time.sleep(2**errorcount)
errorcount+=1
else:
if lastfromv==None:
raise functions.OperatorError(__name__.rsplit('.')[-1], e)
else:
raise functions.OperatorError(__name__.rsplit('.')[-1], str(e)+'\n'+'To continue, use the following "from" parameter:\n'+str(lastfromv))
def Source():
return vtbase.VTGenerator(diavgeiaget)
if not ('.' in __name__):
"""
This is needed to be able to test the function, put it at the end of every
new function you create
"""
import sys
import setpath
from functions import *
testfunction()
if __name__ == "__main__":
reload(sys)
sys.setdefaultencoding('utf-8')
import doctest
doctest.testmod()

View File

@ -0,0 +1,29 @@
Inside the subdirectories you'll find madIS' usage examples.
To execute the examples you'll need to enter inside a subdirectory and start
mterm with a database name argument:
> cd dblp
> mterm dblp.db
You can execute the entirety of a particular SQL flow by using:
exec flow file 'dblp.sql';
Or by opening "dblp.sql" in a text editor and copy pasting one by one the
SQL commands, from text editor's window into mterm's window.
To optimize the resulting database, it is best to execute (inside mterm) the
following SQLite pragmas as soon as you open mterm, and before executing any
other SQL query:
pragma page_size = 16384;
pragma default_cache_size = 10000;
pragma journal_mode = PERSIST;
pragma journal_size_limit = 10000000;
pragma legacy_file_format = false;
pragma synchronous = 1;
pragma auto_vacuum = 2;
Above pragmas optimize SQLite's default options for analytic (bulk/OLAP) SQL queries.

View File

@ -0,0 +1,612 @@
"""functions
"""
VERSION = "1.9"
import setpath
import os.path
import os
import apsw
import sqltransform
import traceback
import logging
import re
import sys
import copy
try:
from collections import OrderedDict
except ImportError:
# Python 2.6
from lib.collections26 import OrderedDict
try:
from inspect import isgeneratorfunction
except ImportError:
# Python < 2.6
def isgeneratorfunction(obj):
return bool((inspect.isfunction(object) or inspect.ismethod(object)) and
obj.func_code.co_flags & CO_GENERATOR)
sys.setcheckinterval(1000)
sqlite_version = apsw.sqlitelibversion()
apsw_version = apsw.apswversion()
VTCREATE = 'create virtual table temp.'
SQLITEAFTER3711 = False
SQLITEAFTER380 = False
sqlite_version_split = [int(x) for x in sqlite_version.split('.')]
if sqlite_version_split[0:3] >= [3,8,0]:
SQLITEAFTER380 = True
try:
if sqlite_version_split[0:3] >= [3,7,11]:
VTCREATE = 'create virtual table if not exists temp.'
SQLITEAFTER3711 = True
except Exception, e:
VTCREATE = 'create virtual table if not exists temp.'
SQLITEAFTER3711 = True
firstimport=True
test_connection = None
settings={
'tracing':False,
'vtdebug':False,
'logging':False,
'syspath':str(os.path.abspath(os.path.expandvars(os.path.expanduser(os.path.normcase(sys.path[0])))))
}
functions = {'row': {}, 'aggregate': {}, 'vtable': {}}
multiset_functions = {}
iterheader = 'ITER'+chr(30)
variables = lambda _: _
variables.flowname = ''
variables.execdb = None
variables.filename = ''
privatevars=lambda _: _
rowfuncs=lambda _: _
oldexecdb=-1
ExecutionCompleteError = apsw.ExecutionCompleteError
def getvar(name):
return variables.__dict__[name]
def setvar(name, value):
variables.__dict__[name] = value
def mstr(s):
if s==None:
return None
try:
return unicode(s, 'utf-8', errors='replace')
except KeyboardInterrupt:
raise
except:
# Parse exceptions that cannot be converted by unicode above
try:
return str(s)
except KeyboardInterrupt:
raise
except:
pass
o=repr(s)
if (o[0:2]=="u'" and o[-1]=="'") or (o[0:2]=='u"' and o[-1]=='"'):
o=o[2:-1]
elif (o[0]=="'" and o[-1]=="'") or (o[0]=='"' and o[-1]=='"'):
o=o[1:-1]
o=o.replace('''\\n''','\n')
o=o.replace('''\\t''','\t')
return o
class MadisError(Exception):
def __init__(self,msg):
self.msg=mstr(msg)
def __str__(self):
merrormsg="Madis SQLError: \n"
if self.msg.startswith(merrormsg):
return self.msg
else:
return merrormsg+self.msg
class OperatorError(MadisError):
def __init__(self,opname,msg):
self.msg="Operator %s: %s" %(mstr(opname.upper()),mstr(msg))
class DynamicSchemaWithEmptyResultError(MadisError):
def __init__(self,opname):
self.msg="Operator %s: Cannot initialize dynamic schema virtual table without data" %(mstr(opname.upper()))
def echofunctionmember(func):
def wrapper(*args, **kw):
if settings['tracing']:
if settings['logging']:
try:
lg = logging.LoggerAdapter(logging.getLogger(__name__),{ "flowname" : variables.flowname })
if hasattr(lg.logger.parent.handlers[0],'baseFilename'):
lg.info("%s(%s)" %(func.__name__,','.join(list([repr(el) for el in args[1:]])+["%s=%s" %(k,repr(v)) for k,v in kw.items()])))
except Exception:
pass
print "%s(%s)" %(func.__name__,','.join(list([repr(el)[:200]+('' if len(repr(el))<=200 else '...') for el in args[1:]])+["%s=%s" %(k,repr(v)) for k,v in kw.items()]))
return func(*args, **kw)
return wrapper
def iterwrapper(con, func, *args):
global iterheader
i=func(*args)
si=iterheader+str(i)
con.openiters[si]=i
return buffer(si)
def iterwrapperaggr(con, func, self):
global iterheader
i=func(self)
si=iterheader+str(i)
con.openiters[si]=i
return buffer(si)
class Cursor(object):
def __init__(self,w):
self.__wrapped=w
self.__vtables=[]
self.__permanentvtables=OrderedDict()
self.__query = ''
self.__initialised=True #this should be last in init
def __getattr__(self, attr):
if self.__dict__.has_key(attr):
return self.__dict__[attr]
return getattr(self.__wrapped, attr)
def __setattr__(self, attr, value):
if self.__dict__.has_key(attr):
return object.__setattr__(self, attr, value)
if not self.__dict__.has_key('_Cursor__initialised'): # this test allows attributes to be set in the __init__ method
return object.__setattr__(self, attr, value)
return setattr(self.__wrapped, attr, value)
@echofunctionmember
def executetrace(self,statements,bindings=None):
try:
return self.__wrapped.execute(statements,bindings)
except Exception, e:
try: # avoid masking exception in recover statements
raise e, None, sys.exc_info()[2]
finally:
try:
self.cleanupvts()
except:
pass
def execute(self,statements,bindings=None,parse=True, localbindings=None): # overload execute statement
if localbindings!=None:
bindings=localbindings
else:
if bindings==None:
bindings=variables.__dict__
else:
if type(bindings) is dict:
bindings.update(variables.__dict__)
if not parse:
self.__query = statements
return self.executetrace(statements,bindings)
svts=sqltransform.transform(statements, multiset_functions.keys(), functions['vtable'], functions['row'].keys(), substitute=functions['row']['subst'])
s=svts[0]
try:
if self.__vtables != []:
self.executetrace(''.join(['drop table ' + 'temp.'+x +';' for x in reversed(self.__vtables)]))
self.__vtables = []
for i in svts[1]:
createvirtualsql=None
if re.match(r'\s*$', i[2]) is None:
sep=','
else:
sep=''
createvirtualsql = VTCREATE+i[0]+ ' using ' + i[1] + "(" + i[2] + sep + "'automatic_vtable:1'" +")"
try:
self.executetrace(createvirtualsql)
except Exception, e:
strex = mstr(e)
if SQLITEAFTER3711 or type(e) != apsw.SQLError or strex.find('already exists')==-1 or strex.find(i[0])==-1:
raise e, None, sys.exc_info()[2]
else:
self.__permanentvtables[i[0]]=createvirtualsql
if len(i)==4:
self.__permanentvtables[i[0]]=createvirtualsql
else:
self.__vtables.append(i[0])
self.__query = s
return self.executetrace(s, bindings)
except Exception, e:
if settings['tracing']:
traceback.print_exc(limit=sys.getrecursionlimit())
try: # avoid masking exception in recover statements
raise e, None, sys.exc_info()[2]
finally:
try:
self.cleanupvts()
except:
pass
def getdescriptionsafe(self):
try:
# Try to get the schema the normal way
schema = self.__wrapped.getdescription()
except apsw.ExecutionCompleteError:
# Else create a tempview and query the view
if not self.__query.strip().lower().startswith('select'):
raise apsw.ExecutionCompleteError
try:
list(self.executetrace('create temp view temp.___schemaview as '+ self.__query + ';'))
schema = [(x[1], x[2]) for x in list(self.executetrace('pragma table_info(___schemaview);'))]
list(self.executetrace('drop view temp.___schemaview;'))
except Exception, e:
raise apsw.ExecutionCompleteError
return schema
def close(self, force=False):
self.cleanupvts()
return self.__wrapped.close(force)
def cleanupvts(self):
if self.__vtables!=[]:
for t in reversed(self.__vtables):
self.executetrace('drop table if exists ' + 'temp.'+t)
self.__vtables=[]
class Connection(apsw.Connection):
def cursor(self):
if 'registered' not in self.__dict__:
self.registered=True
register(self)
self.openiters = {}
return Cursor(apsw.Connection.cursor(self))
def queryplan(self, statements, bindings=None, parse=True, localbindings=None):
def authorizer(operation, paramone, paramtwo, databasename, triggerorview):
"""Called when each operation is prepared. We can return SQLITE_OK, SQLITE_DENY or SQLITE_IGNORE"""
# find the operation name
plan.append([apsw.mapping_authorizer_function[operation], paramone, paramtwo, databasename, triggerorview])
return apsw.SQLITE_OK
def buststatementcache():
c = self.cursor()
for i in xrange(110):
a = list(c.execute("select "+str(i)))
plan = []
buststatementcache()
cursor = self.cursor()
cursor.setexectrace(lambda v1, v2, v3: apsw.SQLITE_DENY)
self.setauthorizer(authorizer)
cursor.execute(statements)
self.setauthorizer(None)
cursor.close()
yield (('operation', 'text'), ('paramone', 'text'), ('paramtwo', 'text'), ('databasename', 'text'), ('triggerorview', 'text'))
for r in plan:
if r[1] not in ('sqlite_temp_master', 'sqlite_master'):
yield r
@echofunctionmember
def close(self):
apsw.Connection.close(self)
def register(connection=None):
global firstimport, oldexecdb
if connection == None:
if 'SQLITE_OPEN_URI' in apsw.__dict__:
connection = Connection(':memory:', flags=apsw.SQLITE_OPEN_READWRITE | apsw.SQLITE_OPEN_CREATE | apsw.SQLITE_OPEN_URI)
else:
connection = Connection(':memory:')
connection.openiters = {}
connection.registered = True
connection.cursor().execute("attach database ':memory:' as mem;", parse=False)
variables.filename = connection.filename
# To avoid db corruption set connection to fullfsync mode when MacOS is detected
if sys.platform == 'darwin':
c = connection.cursor().execute('pragma fullfsync=1;', parse=False)
functionspath=os.path.abspath(__path__[0])
def findmodules(abspath, relativepath):
return [ os.path.splitext(file)[0] for file
in os.listdir(os.path.join(abspath , relativepath))
if file.endswith(".py") and not file.startswith("_") ]
## Register main functions of madis (functions)
rowfiles = findmodules(functionspath, 'row')
aggrfiles = findmodules(functionspath, 'aggregate')
vtabfiles = findmodules(functionspath, 'vtable')
[__import__("functions.row" + "." + module) for module in rowfiles]
[__import__("functions.aggregate" + "." + module) for module in aggrfiles]
[__import__("functions.vtable" + "." + module) for module in vtabfiles]
# Register aggregate functions
for module in aggrfiles:
moddict = aggregate.__dict__[module]
register_ops(moddict,connection)
# Register row functions
for module in rowfiles:
moddict = row.__dict__[module]
register_ops(moddict,connection)
register_ops(vtable,connection)
## Register madis local functions (functionslocal)
functionslocalpath=os.path.abspath(os.path.join(functionspath,'..','functionslocal'))
flrowfiles = findmodules(functionslocalpath, 'row')
flaggrfiles = findmodules(functionslocalpath, 'aggregate')
flvtabfiles = findmodules(functionslocalpath, 'vtable')
for module in flrowfiles:
tmp=__import__("functionslocal.row." + module)
register_ops(tmp.row.__dict__[module], connection)
for module in flaggrfiles:
tmp=__import__("functionslocal.aggregate." + module)
register_ops(tmp.aggregate.__dict__[module], connection)
localvtable=lambda x:x
for module in flvtabfiles:
localvtable.__dict__[module]=__import__("functionslocal.vtable." + module, fromlist=['functionslocal.vtable'])
if len(flvtabfiles)!=0:
register_ops(localvtable,connection)
## Register db local functions (functions in db path)
if variables.execdb!=oldexecdb:
oldexecdb=variables.execdb
dbpath=None
if variables.execdb!=None:
dbpath=os.path.join(os.path.abspath(os.path.dirname(variables.execdb)),'functions')
if dbpath==None or not os.path.exists(dbpath):
currentpath=os.path.abspath(os.path.join(os.path.abspath('.'), 'functions'))
if os.path.exists(currentpath):
dbpath=currentpath
if dbpath!=None and os.path.exists(dbpath):
if os.path.abspath(dbpath)!=os.path.abspath(functionspath):
sys.path.append(dbpath)
if os.path.exists(os.path.join(dbpath, 'row')):
lrowfiles = findmodules(dbpath, 'row')
sys.path.append((os.path.abspath(os.path.join(os.path.join(dbpath),'row'))))
for module in lrowfiles:
tmp=__import__(module)
register_ops(tmp, connection)
if os.path.exists(os.path.join(dbpath, 'aggregate')):
sys.path.append((os.path.abspath(os.path.join(os.path.join(dbpath),'aggregate'))))
laggrfiles = findmodules(dbpath, 'aggregate')
for module in laggrfiles:
tmp=__import__(module)
register_ops(tmp, connection)
if os.path.exists(os.path.join(dbpath, 'vtable')):
sys.path.append((os.path.abspath(os.path.join(os.path.join(dbpath),'vtable'))))
lvtabfiles = findmodules(dbpath, 'vtable')
tmp=lambda x:x
for module in lvtabfiles:
tmp.__dict__[module]=__import__(module)
if localvtable!=None:
register_ops(tmp,connection)
firstimport=False
def register_ops(module, connection):
global rowfuncs, firstimport
def opexists(op):
if firstimport:
return op in functions['vtable'] or op in functions['row'] or op in functions['aggregate']
else:
return False
def wrapfunction(con, opfun):
return lambda *args: iterwrapper(con, opfun, *args)
def wrapaggr(con, opfun):
return lambda self: iterwrapperaggr(con, opfun, self)
def wrapaggregatefactory(wlambda):
return lambda cls: (cls(), cls.step, wlambda)
for f in module.__dict__:
fobject = module.__dict__[f]
if hasattr(fobject, 'registered') and type(fobject.registered).__name__ == 'bool' and fobject.registered == True:
opname=f.lower()
if firstimport:
if opname!=f:
raise MadisError("Extended SQLERROR: Function '"+module.__name__+'.'+f+"' uses uppercase characters. Functions should be lowercase")
if opname.upper() in sqltransform.sqlparse.keywords.KEYWORDS:
raise MadisError("Extended SQLERROR: Function '"+module.__name__+'.'+opname+"' is a reserved SQL function")
if type(fobject).__name__ == 'module':
if opexists(opname):
raise MadisError("Extended SQLERROR: Vtable '"+opname+"' name collision with other operator")
functions['vtable'][opname] = fobject
modinstance = fobject.Source()
modinstance._madisVT = True
connection.createmodule(opname, modinstance)
if type(fobject).__name__ == 'function':
if opexists(opname):
raise MadisError("Extended SQLERROR: Row operator '"+module.__name__+'.'+opname+"' name collision with other operator")
functions['row'][opname] = fobject
if isgeneratorfunction(fobject):
fobject=wrapfunction(connection, fobject)
fobject.multiset=True
setattr(rowfuncs, opname, fobject)
connection.createscalarfunction(opname, fobject)
if type(fobject).__name__ == 'classobj':
if opexists(opname):
raise MadisError("Extended SQLERROR: Aggregate operator '"+module.__name__+'.'+opname+"' name collision with other operator")
functions['aggregate'][opname] = fobject
if isgeneratorfunction(fobject.final):
wlambda = wrapaggr(connection, fobject.final)
fobject.multiset = True
setattr(fobject, 'factory', classmethod(wrapaggregatefactory(wlambda)))
connection.createaggregatefunction(opname, fobject.factory)
else:
setattr(fobject, 'factory', classmethod(lambda cls:(cls(), cls.step, cls.final)))
connection.createaggregatefunction(opname, fobject.factory)
try:
if fobject.multiset:
multiset_functions[opname] = True
except:
pass
def testfunction():
global test_connection, settings
test_connection = Connection(':memory:')
register(test_connection)
variables.execdb=':memory:'
def settestdb(testdb):
global test_connection, settings
abstestdb=str(os.path.abspath(os.path.expandvars(os.path.expanduser(os.path.normcase(testdb)))))
test_connection = Connection(abstestdb)
register(test_connection)
variables.execdb=abstestdb
def sql(sqlquery):
import locale
from lib import pptable
global test_connection
language, output_encoding = locale.getdefaultlocale()
if output_encoding==None:
output_encoding="UTF8"
test_cursor=test_connection.cursor()
e=test_cursor.execute(sqlquery.decode(output_encoding))
try:
desc=test_cursor.getdescription()
print pptable.indent([[x[0] for x in desc]]+[x for x in e], hasHeader=True),
except apsw.ExecutionCompleteError:
print '',
test_cursor.close()
def table(tab, num=''):
import shlex
"""
Creates a test table named "table". It's columns are fitted to the data
given to it and are automatically named a, b, c, ...
'num' parameter:
If a 'num' parameter is given then the table will be named for example
table1 when num=1, table2 when num=2 ...
Example:
table('''
1 2 3
4 5 6
''')
will create a table named 'table' having the following data:
a b c
---------
1 2 3
4 5 6
"""
colnames="abcdefghijklmnop"
import re
tab=tab.splitlines()
tab=[re.sub(r'[\s\t]+',' ',x.strip()) for x in tab]
tab=[x for x in tab if x!='']
# Convert NULL to None
tab=[[(y if y!='NULL' else None) for y in shlex.split(x)] for x in tab]
numberofcols=len(tab[0])
if num=='':
num='0'
createsql='create table table'+str(num)+'('
insertsql="insert into table"+str(num)+" values("
for i in range(0,numberofcols):
createsql=createsql+colnames[i]+' str'+','
insertsql=insertsql+'?,'
createsql=createsql[0:-1]+')'
insertsql=insertsql[0:-1]+')'
test_cursor=test_connection.cursor()
try:
test_cursor.execute(createsql)
except:
test_cursor.execute("drop table table"+str(num))
test_cursor.execute(createsql)
test_cursor.executemany(insertsql, tab)
def table1(tab):
table(tab, num=1)
def table2(tab):
table(tab, num=2)
def table3(tab):
table(tab, num=3)
def table4(tab):
table(tab, num=4)
def table5(tab):
table(tab, num=5)
def table6(tab):
table(tab, num=6)
def setlogfile(file):
pass

View File

@ -0,0 +1,271 @@
import Queue
import setpath
import functions
import datetime
from lib import iso8601
__docformat__ = 'reStructuredText en'
def timedelta2millisec(tdelta):
return tdelta.days*24*60*60*1000+tdelta.seconds*1000+tdelta.microseconds/1000
class mindtdiff:
"""
.. function:: mindtdiff(date)
Returns the minimum difference *date* values of the group in milliseconds. Input dates should be in :ref:`ISO 8601 format <iso8601>`.
Examples:
>>> table1('''
... '2007-01-01 00:03:13'
... '2007-01-01 00:03:27'
... '2007-01-01 00:03:36'
... '2007-01-01 00:04:39'
... '2007-01-01 00:04:40'
... '2007-01-01 00:04:49'
... ''')
>>> sql("select mindtdiff(a) from table1")
mindtdiff(a)
------------
1000
.. doctest::
:hide:
>>> sql("select mindtdiff(a) from (select '2005-01-01' as a) ")
mindtdiff(a)
------------
None
>>> sql("select mindtdiff(a) from (select 5 as a where a!=5) ")
mindtdiff(a)
------------
None
"""
registered=True
def __init__(self):
self.dates=Queue.PriorityQueue()
def step(self, *args):
if not args:
raise functions.OperatorError("mindtdiff","No arguments")
dt=iso8601.parse_date(args[0])
self.dates.put_nowait(dt)
def final(self):
mindiff=None
dtp=None
if not self.dates:
return
while not self.dates.empty():
if not mindiff:
if not dtp:
dtp=self.dates.get_nowait()
continue
dt=self.dates.get_nowait()
diff=timedelta2millisec(dt-dtp)
if mindiff==None:
mindiff=diff
elif mindiff>diff:
mindiff=diff
dtp=dt
import types
return mindiff
class avgdtdiff:
"""
.. function:: avgdtdiff(date)
Returns the average difference *date* values of the group in milliseconds. Input dates should be in :ref:`ISO 8601 format <iso8601>`.
Examples:
>>> table1('''
... '2007-01-01 00:04:37'
... '2007-01-01 00:04:39'
... '2007-01-01 00:04:40'
... '2007-01-01 00:04:49'
... ''')
>>> sql("select avgdtdiff(a) from table1")
avgdtdiff(a)
------------
3000.0
.. doctest::
:hide:
>>> sql("select avgdtdiff(a) from (select '2005-01-01' as a) ")
avgdtdiff(a)
------------
None
>>> sql("select avgdtdiff(a) from (select 5 as a where a!=5) ")
avgdtdiff(a)
------------
None
"""
registered=True
def __init__(self):
self.dates=Queue.PriorityQueue()
def step(self, *args):
if not args:
raise functions.OperatorError("avgdtdiff","No arguments")
dt=iso8601.parse_date(args[0])
self.dates.put_nowait(dt)
def final(self):
avgdiff=0
cntdiff=0
dtp=None
while not self.dates.empty():
if avgdiff==0:
if not dtp:
cntdiff+=1
dtp=self.dates.get_nowait()
continue
dt=self.dates.get_nowait()
diff=timedelta2millisec(dt-dtp)
cntdiff+=1
avgdiff+=diff
dtp=dt
if cntdiff<2:
return None
return float(avgdiff)/cntdiff
class dategroupduration:
"""
.. function:: dategroupduration(date)
Returns the duration of the group of dates in seconds. Input dates should be in :ref:`ISO 8601 format <iso8601>`.
Examples:
>>> table1('''
... '2007-01-01 00:04:37'
... '2007-01-01 00:04:39'
... '2007-01-01 00:04:40'
... '2007-01-01 00:04:49'
... ''')
>>> sql("select dategroupduration(a) from table1")
dategroupduration(a)
--------------------
12
>>> sql("select dategroupduration(a) from (select '2005-01-01' as a) ")
dategroupduration(a)
--------------------
0
"""
registered=True
def __init__(self):
self.datemin = None
self.datemax = None
def step(self, *args):
pdate = iso8601.parse_date(args[0])
if self.datemin == None:
self.datemin = pdate
if self.datemax == None:
self.datemax = pdate
if pdate < self.datemin:
self.datemin = pdate
if pdate > self.datemax:
self.datemax = pdate
def final(self):
if self.datemin == None or self.datemax == None:
return 0
diff=self.datemax - self.datemin
return diff.days*86400+diff.seconds
class frecencyindex:
"""
.. function:: frecencyindex(date)
Returns the frecency Index which is computed based on a set of *date* values, using predifend time-windows.
Input dates should be in :ref:`ISO 8601 format <iso8601>`.
Examples:
>>> table1('''
... '2011-04-01 00:04:37'
... '2011-01-01 00:04:39'
... '2011-02-12 00:04:40'
... '2011-02-14 00:04:49'
... ''')
>>> sql("select frecencyindex(a) from table1")
frecencyindex(a)
----------------
2.9
"""
registered=True
def __init__(self):
self.monthCounter=0
self.trimesterCounter=0
self.semesterCounter=0
self.yearCounter=0
self.twoyearsCounter=0
def step(self, *args):
if not args:
raise functions.OperatorError("frecencyindex","No arguments")
now = datetime.datetime.now()
now = iso8601.parse_date(now.strftime("%Y-%m-%d %H:%M:%S"))
d = args[0].replace('T',' ')
dt = iso8601.parse_date(args[0].replace('Z',''))
diff=now-dt
if (diff.days)<30:
self.monthCounter+=1
elif (diff.days)<3*30:
self.trimesterCounter+=1
elif (diff.days)<6*30:
self.semesterCounter+=1
elif (diff.days)<12*30:
self.yearCounter+=1
elif (diff.days)<24*30:
self.twoyearsCounter+=1
def final(self):
return self.monthCounter*1 + self.trimesterCounter*0.7 + self.semesterCounter*0.5 + self.yearCounter*0.3+ self.twoyearsCounter*0.2
if not ('.' in __name__):
"""
This is needed to be able to test the function, put it at the end of every
new function you create
"""
import sys
import setpath
from functions import *
testfunction()
if __name__ == "__main__":
reload(sys)
sys.setdefaultencoding('utf-8')
import doctest
doctest.testmod()

View File

@ -0,0 +1,635 @@
__docformat__ = 'reStructuredText en'
import setpath
import json
from hashlib import md5
from binascii import b2a_base64
import math
import collections
import functions
class graphpowerhash:
"""
.. function:: graphpowerhash(steps, [undirected_edge], node1, node2, [node1_details, edge_details, node2_details]) -> jpack of graph node hashes
Graph power hashing is based on a `power iteration algorithm <http://en.wikipedia.org/wiki/Power_iteration>`_
that calculates hashes on every processing step. The produced output, contains for every node in the input graph
a hash that "describes" its "surroundings".
Parameters:
:steps:
The *steps* option controls the number of steps that the power hashing will be executed for. Another
way to conceptualize the *steps* parameter is to think of it as the radius of the graph around
a particular node that the node's hash covers.
Steps parameter's possible value are:
- null (default). When steps=null, then steps is automatically set to number_of_nodes/2
- Positive integer value.
- -1 . Steps is set to number_of_nodes
- Negative integers, steps is set to number_of_nodes / absolute_value(steps)
:undirected_edge':
This option can only have the *null* value.
- Parameter absent. The graph is assumed to be directed.
- Parameter present and having a *null* value. The graph is assumed to be undirected
:node1,node2:
Node1 connects to Node2. If node1 doesn't connect to any node, then *node2*'s value should be null.
:node and edge details:
Optional details, that are processed with the graph's structure. In essence these
parameters define "tags" on the nodes and edges of the graph.
.. note::
The graph power hash algorithm is an experimental algorithm created by me, Lefteris Stamatogiannakis. I haven't
proved its correctness, so please use it with care. Due to its hash usage, there is a (very low probability)
that two different graphs could hash to the same power hash.
I would be very very thankfull to anyone knowledgable in graph theory, who could prove it to be wrong (or correct).
If the reader knows of a paper that describes another algorithm similar to this algorithm, i would be glad to be pointed towards it.
.. note::
The computational complexity of the powerhash algorithm is O(n * steps * average_node_degree). The optimal value for
the hash to fully cover the graph, is to set the steps parameter to *graph_diameter* / 2.
Right now for steps=null, we take the worse upper bound of n / 2, so the computational complexity becomes
O(n * ~(n/2) * average_node_degree).
Examples:
Directed graph:
>>> table1('''
... 1 2
... 2 3
... 3 4
... 4 5
... 5 3
... ''')
>>> sql("select graphpowerhash(null, a,b) from table1")
graphpowerhash(null, a,b)
------------------------------------------------------------------------------------------------------------------------------
["OaNj+OtIZPqcwjc3QVvKpg","Um7OU79ApcRNA2TKrdcBcA","ZyQT/AoKyjIkwWMNvceK2A","3vaHWSLU/H32HvHTVBkpUQ","+3uZjYUMSXwyZs7HFHKNVg"]
Above graph having its nodes renumbered (its powerhash is the same as above):
>>> table2('''
... 2 5
... 5 4
... 4 1
... 1 3
... 3 4
... ''')
>>> sql("select graphpowerhash(null, a,b) from table2")
graphpowerhash(null, a,b)
------------------------------------------------------------------------------------------------------------------------------
["OaNj+OtIZPqcwjc3QVvKpg","Um7OU79ApcRNA2TKrdcBcA","ZyQT/AoKyjIkwWMNvceK2A","3vaHWSLU/H32HvHTVBkpUQ","+3uZjYUMSXwyZs7HFHKNVg"]
Above graph with a small change (its hash differs from above graphs):
>>> table3('''
... 2 5
... 5 4
... 4 1
... 1 3
... 3 5
... ''')
>>> sql("select graphpowerhash(null, a,b) from table3")
graphpowerhash(null, a,b)
------------------------------------------------------------------------------------------------------------------------------
["APq1eISun1GpYjgUhiMrLA","NPPh9FLzC5cUedxldXV77Q","VVZ93zo6gePuMeRf6f00Zg","df/4yDABlitCTfOGut0NvA","lqo+lY4fcjqujlgsYr+3Yw"]
Actual testing of equality or inequality of above graphs:
>>> sql("select hashmd5( (select graphpowerhash(null, a,b) from table1) )=hashmd5( (select graphpowerhash(null, a,b) from table2) ) as grapheq")
grapheq
-------
1
>>> sql("select hashmd5( (select graphpowerhash(null, a,b) from table1) )=hashmd5( (select graphpowerhash(null, a,b) from table3) ) as grapheq")
grapheq
-------
0
Graph with only one node:
>>> sql("select graphpowerhash(null, a, null) from (select * from table1 limit 1)")
graphpowerhash(null, a, null)
-----------------------------
["TOiuilAk4RLkg01tIwyvcg"]
Undirected version of table1's graph:
>>> sql("select graphpowerhash(null, null, a,b) from table1")
graphpowerhash(null, null, a,b)
------------------------------------------------------------------------------------------------------------------------------
["JudlYSkYV7rFHjk94abY/A","W88IN4kgDSeVX9kaY36SJg","W88IN4kgDSeVX9kaY36SJg","6ez9ee0N2ogdvKJVQ8VKWA","7gz+LT/LtsyFc+GxMUlL8g"]
Same graph as above, but some of the edges have been reversed (the undirected powerhash matches the powerhash above):
>>> table4('''
... 2 1
... 2 3
... 3 4
... 4 5
... 3 5
... ''')
>>> sql("select graphpowerhash(null, null, a,b) from table4")
graphpowerhash(null, null, a,b)
------------------------------------------------------------------------------------------------------------------------------
["JudlYSkYV7rFHjk94abY/A","W88IN4kgDSeVX9kaY36SJg","W88IN4kgDSeVX9kaY36SJg","6ez9ee0N2ogdvKJVQ8VKWA","7gz+LT/LtsyFc+GxMUlL8g"]
Graph similarity, using the step parameter (value of step defines the radius of the similar subgraphs that can be found):
>>> sql("select jaccard( (select graphpowerhash(3, a, b) from table1), (select graphpowerhash(3, a, b) from table3) ) as jacsim")
jacsim
------
0.0
>>> sql("select jaccard( (select graphpowerhash(1, a, b) from table1), (select graphpowerhash(1, a, b) from table3) ) as jacsim")
jacsim
------
0.25
Powerhash of graph having details (using a chemical composition):
>>> table5('''
... 1 2 O = C
... 2 3 C = O
... ''')
First without details:
>>> sql("select graphpowerhash(null, null, a, b) from table5")
graphpowerhash(null, null, a, b)
----------------------------------------------------------------------------
["Rw3sDN24TI7YARBNOOmYSg","9m5wcZf9iUxDwgzQkzu6Ag","9m5wcZf9iUxDwgzQkzu6Ag"]
Second with all details:
>>> sql("select graphpowerhash(null, null, a, b, c, d, e) from table5")
graphpowerhash(null, null, a, b, c, d, e)
----------------------------------------------------------------------------
["CPebw+eZYzw5bWgx47/tkg","CPebw+eZYzw5bWgx47/tkg","WNn4aDDBKcoMMi+nrz5JEA"]
"""
registered=True
def __init__(self):
self.nodes={}
self.steps=None
def step(self, *args):
directed=True
argslen=len(args)
largs=args
if largs[0]!=None:
self.steps=largs[0]
if largs[1]==None:
directed=False
largs=list(largs)
del(largs[1])
argslen-=1
if directed:
if argslen>4:
edgedetailslr='1'+chr(30)+str(largs[4])
edgedetailsrl='0'+chr(30)+str(largs[4])
else:
edgedetailslr='1'
edgedetailsrl='0'
else:
if argslen>4:
edgedetailslr='1'+ chr(30)+str(largs[4])
edgedetailsrl=edgedetailslr
else:
edgedetailslr='1'
edgedetailsrl=edgedetailslr
if largs[1] not in self.nodes:
if argslen>3:
self.nodes[largs[1]]=[ [( largs[2],edgedetailslr )] , str(largs[3])]
else:
self.nodes[largs[1]]=[ [( largs[2],edgedetailslr )] , '']
else:
self.nodes[largs[1]][0].append( ( largs[2],edgedetailslr ) )
if largs[2]!=None:
if largs[2] not in self.nodes:
if argslen>5:
self.nodes[largs[2]]=[ [(largs[1],edgedetailsrl )], str(largs[5])]
else:
self.nodes[largs[2]]=[ [(largs[1],edgedetailsrl )] , '']
else:
self.nodes[largs[2]][0].append( ( largs[1],edgedetailsrl ) )
def final(self):
ncount=len(self.nodes)
for n,v in self.nodes.iteritems():
v[1]=str(len(v[0]))+chr(31)+v[1]
if ncount==1:
self.steps=1
if self.steps==None:
# Calculate approximate worse case diameter
degreeseq=set()
mindegree=ncount
maxdegree=0
invdegree=0.0
for n,v in self.nodes.iteritems():
ndegree=len(v[0])
mindegree=min(mindegree, ndegree)
maxdegree=max(maxdegree, ndegree)
degreeseq.add(ndegree)
invdegree+=1.0/ndegree
self.steps=int(min(
# Obvious upper bounds
ncount-max(2, maxdegree) + 2,
# P. Dankelmann "Diameter and inverse degree"
(3*invdegree+3)*math.log(ncount)/math.log(math.log(ncount)) if ncount>16 else ncount,
# Simon Mukwembi "A note on diameter and the degree sequence of a graph"
1+3*(ncount - len(degreeseq)+1)/float((mindegree+1)), ncount - len(degreeseq)+2))/2
if self.steps<0:
self.steps=ncount/abs(self.steps)
nhashes={}
for n,v in self.nodes.iteritems():
nhashes[n]=md5(str(v[1]+chr(30))).digest()
if ncount>1:
for s in xrange(self.steps):
nhashes1={}
nhashcount={}
for n, v in self.nodes.iteritems():
nhash=md5(v[1]+chr(30)+chr(30).join(sorted([nhashes[x]+chr(29)+y for x,y in v[0]]))).digest()
nhashes1[n]=nhash
if nhash in nhashcount:
nhashcount[nhash]+=1
else:
nhashcount[nhash]=1
nhashes=nhashes1
# TODO Find new upper bound of diameter via calculating Spanning Tree starting from distincthash
# if len(nhashcount)>0:
# distincthash=min([x for x,y in nhashcount.iteritems() if y==1])
return json.dumps([b2a_base64(x)[0:-3] for x in sorted(nhashes.values())], separators=(',',':'), ensure_ascii=False)
class graphtodot:
"""
.. function:: graphtodot(graphname, [undirected_edge], node1, node2, [node1_details, edge_details, node2_details]) -> graphviz dot graph
Returns the *Graphviz* DOT representation of the input graph.
Examples:
Directed graph:
>>> table1('''
... 1 2
... 2 3
... 3 4
... 4 5
... 5 3
... ''')
>>> sql("select graphtodot(null, a,b) from table1")
graphtodot(null, a,b)
------------------------------------------------------------------------
digraph {
"1" -> "2";
"2" -> "3";
"3" -> "4";
"4" -> "5";
"5" -> "3";
}
Undirected graph:
>>> table2('''
... 2 5
... 5 4
... 4 1
... 1 3
... 3 4
... ''')
>>> sql("select graphtodot(null, null, a,b) from table2")
graphtodot(null, null, a,b)
----------------------------------------------------------------------
graph {
"1" -- "3";
"2" -- "5";
"3" -- "4";
"4" -- "1";
"5" -- "4";
}
Graph with details:
>>> table5('''
... 1 2 O = C
... 2 3 C = O
... ''')
>>> sql("select graphtodot('chem_comp_1', null, a, b, c, d, e) from table5")
graphtodot('chem_comp_1', null, a, b, c, d, e)
------------------------------------------------------------------------------------------------------------------------
graph chem_comp_1 {
"1" [label="O"];
"1" -- "2" [label="="];
"2" [label="C"];
"2" -- "3" [label="="];
"3" [label="O"];
}
"""
registered=True
def __init__(self):
self.nodes={}
self.steps=None
self.graphname=None
self.directed=True
def step(self, *args):
directed=True
argslen=len(args)
largs=args
if largs[0]!=None:
self.graphname=largs[0]
if largs[1]==None:
self.directed=False
largs=list(largs)
del(largs[1])
argslen-=1
if argslen>4:
edgedetailslr=unicode(largs[4])
else:
edgedetailslr=None
if largs[1] not in self.nodes:
if argslen>3:
self.nodes[largs[1]]=[ [( largs[2],edgedetailslr )] , largs[3]]
else:
self.nodes[largs[1]]=[ [( largs[2],edgedetailslr )] , None]
else:
self.nodes[largs[1]][0].append( ( largs[2],edgedetailslr ) )
if largs[2]!=None:
if largs[2] not in self.nodes:
if argslen>5:
self.nodes[largs[2]]=[ [], largs[5]]
else:
self.nodes[largs[2]]=[ [] , None]
def final(self):
if self.graphname==None:
self.graphname=''
if type(self.graphname) in (int, float):
self.graphname=u'g'+unicode(self.graphname)
else:
self.graphname=unicode(self.graphname)
dot=u''
if self.directed:
dot=u'di'
if self.graphname==None:
self.graphname='""'
dot+=u'graph '+self.graphname+u' {\n'
digraph=False
for n,v in self.nodes.iteritems():
if v[1]!=None:
dot+=json.dumps(unicode(n))+' [label="'+unicode(v[1]).replace('"',"'")+'"];\n'
for e in v[0]:
dot+=json.dumps(unicode(n)) + ' '
if self.directed:
dot+='-> '
else:
dot+='-- '
dot += json.dumps(unicode(e[0]))
if e[1]!=None:
dot+=u' [label="'+unicode(e[1]).replace('"',"'")+'"]'
dot+=u';\n'
dot+='}'
return dot
class graphtotgf:
"""
.. function:: graphtotgf(node1, node2, [node1_details, edge_details, node2_details]) -> TGF graph
Returns the TGF representation of the input graph.
Examples:
>>> table1('''
... 1 2
... 2 3
... 3 4
... 4 5
... 5 3
... ''')
>>> sql("select graphtotgf(a,b) from table1") # doctest: +NORMALIZE_WHITESPACE
graphtotgf(a,b)
------------------------------------------
1
2
3
4
5
#
1 2
2 3
3 4
4 5
5 3
Graph with details:
>>> table5('''
... 1 2 O = C
... 2 3 C = O
... ''')
>>> sql("select graphtotgf(a, b, c, d, e) from table5")
graphtotgf(a, b, c, d, e)
--------------------------
1 O
2 C
3 O
#
1 2 =
2 3 =
"""
registered=True
def __init__(self):
self.nodes={}
self.steps=None
self.directed=True
def step(self, *args):
argslen=len(args)
largs=args
if argslen>3:
edgedetailslr=unicode(largs[3])
else:
edgedetailslr=None
if largs[0] not in self.nodes:
if argslen>2:
self.nodes[largs[0]]=[ [( largs[1],edgedetailslr )] , largs[2]]
else:
self.nodes[largs[0]]=[ [( largs[1],edgedetailslr )] , None]
else:
self.nodes[largs[0]][0].append( ( largs[1],edgedetailslr ) )
if largs[1]!=None:
if largs[1] not in self.nodes:
if argslen>4:
self.nodes[largs[1]]=[ [], largs[4]]
else:
self.nodes[largs[1]]=[ [] , None]
def final(self):
tgf=''
def clearname(n):
return unicode(n).replace(' ','_').replace('"',"'")
for n,v in self.nodes.iteritems():
tgf+=clearname(n) + ' ' + (clearname(v[1]) if v[1]!=None else '') +'\n'
tgf+='#\n'
for n,v in self.nodes.iteritems():
for e in v[0]:
tgf+=clearname(n)+ ' ' + clearname(e[0])+ ' '+ (clearname(e[1]) if e[1]!=None else '') + '\n'
return tgf
class graphcliques:
"""
.. function:: graphcliques(node1, node2) -> graph cliques
Finds and returns the cliques in the graph defined by the node1<->node2 links.
Examples:
>>> table1('''
... n1 n2
... n2 n3
... n1 n3
... n3 n4
... n4 n5
... n5 n3
... n1 n6
... ''')
>>> sql("select graphcliques(a,b) from table1") # doctest: +NORMALIZE_WHITESPACE
cliqueid | nodeid
-----------------
0 | n1
0 | n2
0 | n3
1 | n3
1 | n4
1 | n5
"""
registered=True
def __init__(self):
self.G = collections.defaultdict(set)
def step(self, *args):
if len(args)!=2:
raise functions.OperatorError('graphcliques', 'Two parameters should be provided')
self.G[args[0]].add(args[1])
self.G[args[1]].add(args[0])
def _bors_kerbosch(self, R, P, X):
if not P and not X: # if both are empty
if len(R) > 2:
yield sorted(R)
return
pivot = max(((len(self.G[v]), v) for v in P.union(X)))[1]
for v in P.difference(self.G[pivot]):
for c in self._bors_kerbosch(R.union((v,)), P.intersection(self.G[v]), X.intersection(self.G[v])):
yield c
P.remove(v)
X.add(v)
def final(self):
cid = 0
yield ('cliqueid', 'nodeid')
for c in self._bors_kerbosch(set([]), set(self.G.keys()), set([])):
for n in c:
yield cid, n
cid += 1
if not ('.' in __name__):
"""
This is needed to be able to test the function, put it at the end of every
new function you create
"""
import sys
import setpath
from functions import *
testfunction()
if __name__ == "__main__":
reload(sys)
sys.setdefaultencoding('utf-8')
import doctest
doctest.testmod()

View File

@ -0,0 +1,356 @@
__docformat__ = 'reStructuredText en'
import setpath
import lib.jopts as jopts
import json
from collections import OrderedDict
try:
from collections import OrderedDict
except ImportError:
# Python 2.6
from lib.collections26 import OrderedDict
class jgroup:
"""
.. function:: jgroup(columns)
Groups columns of a group into a jpack.
Example:
>>> table1('''
... word1 1
... word2 1
... word3 2
... word4 2
... ''')
>>> sql("select jgroup(a) from table1 group by b")
jgroup(a)
-----------------
["word1","word2"]
["word3","word4"]
>>> sql("select jgroup(a,b) from table1")
jgroup(a,b)
-------------------------------------------------
[["word1",1],["word2",1],["word3",2],["word4",2]]
>>> table2('''
... [1,2] 1
... [3,4] 1
... [5,6] 2
... [7,8] 2
... ''')
>>> sql("select jgroup(a) from table2")
jgroup(a)
-------------------------
[[1,2],[3,4],[5,6],[7,8]]
>>> sql("select jgroup(a,b) from table2")
jgroup(a,b)
-----------------------------------------
[[[1,2],1],[[3,4],1],[[5,6],2],[[7,8],2]]
>>> sql("select jgroup(jdict('a',a,'b',b)) from table2")
jgroup(jdict('a',a,'b',b))
-------------------------------------------------------------------------
[{"a":[1,2],"b":1},{"a":[3,4],"b":1},{"a":[5,6],"b":2},{"a":[7,8],"b":2}]
"""
registered = True #Value to define db operator
def __init__(self):
self.outgroup = []
def step(self, *args):
if len(args) == 1:
self.outgroup += (jopts.elemfromj(args[0]))
else:
self.outgroup.append(jopts.elemfromj(*args))
def final(self):
return jopts.toj(self.outgroup)
class jdictgroup:
"""
.. function:: jdictgroup(columns)
Groups columns of a group into a jdict.
Example:
>>> table1('''
... word1 1
... word2 1
... word3 2
... word4 2
... ''')
>>> sql("select jdictgroup(a) from table1 group by b")
jdictgroup(a)
---------------------------
{"word1":null,"word2":null}
{"word3":null,"word4":null}
>>> sql("select jdictgroup(a,b) from table1")
jdictgroup(a,b)
-----------------------------------------
{"word1":1,"word2":1,"word3":2,"word4":2}
>>> table2('''
... [1,2] 1
... [3,4] 1
... [5,6] 2
... [7,8] 2
... ''')
>>> sql("select jdictgroup(a) from table2")
jdictgroup(a)
-----------------------------------------------------
{"[1,2]":null,"[3,4]":null,"[5,6]":null,"[7,8]":null}
>>> sql("select jdictgroup(a,b) from table2")
jdictgroup(a,b)
-----------------------------------------
{"[1,2]":1,"[3,4]":1,"[5,6]":2,"[7,8]":2}
"""
registered = True #Value to define db operator
def __init__(self):
self.outgroup = OrderedDict()
def step(self, *args):
if len(args) == 1:
self.outgroup[args[0]] = None
else:
self.outgroup[args[0]] = jopts.fromjsingle(*args[1:])
def final(self):
return jopts.toj(self.outgroup)
class jgroupunion:
"""
.. function:: jgroupunion(columns) -> jpack
Calculates the union of the jpacks (by treating them as sets) inside a group.
Example:
>>> table1('''
... '[1,2]' 6
... '[2,3]' 7
... '[2,4]' '[8,11]'
... 5 9
... ''')
>>> sql("select jgroupunion(a,b) from table1")
jgroupunion(a,b)
----------------------
[1,2,6,3,7,4,8,11,5,9]
>>> sql("select jgroupunion(1)")
jgroupunion(1)
--------------
1
"""
registered = True #Value to define db operator
def __init__(self):
self.outgroup = OrderedDict()
self.outgroupupdate = self.outgroup.update
def step(self, *args):
self.outgroupupdate([(x, None) for x in jopts.fromj(*args)])
def final(self):
return jopts.toj(list(self.outgroup))
class jgroupintersection:
"""
.. function:: jgroupintersection(columns) -> jpack
Calculates the intersection of all jpacks (by treating them as sets) inside a group.
Example:
>>> table1('''
... '[1,2]' 2
... '[2,3]' 2
... '[2,4]' '[2,11]'
... 2 2
... ''')
>>> sql("select jgroupintersection(a,b) from table1")
jgroupintersection(a,b)
-----------------------
2
>>> sql("select jgroupintersection(1)")
jgroupintersection(1)
---------------------
1
"""
registered = True #Value to define db operator
def __init__(self):
self.outgroup = None
self.outset = None
def step(self, *args):
if self.outgroup == None:
self.outgroup = OrderedDict([(x, None) for x in jopts.fromj(args[0])])
self.outset = set(self.outgroup)
for jp in args:
for i in self.outset.difference(jopts.fromj(jp)):
del (self.outgroup[i])
self.outset = set(self.outgroup)
def final(self):
return jopts.toj(list(self.outgroup))
class jdictgroupunion:
"""
.. function:: jgroupunion(jdicts) -> jdict
Calculates the union of all jdicts inside a group. The returned jdict's key values, are
calculated as the max length of the lists (or dictionaries) that have been found inside
the individual jdicts of the group.
Example:
>>> table1('''
... '{"b":1, "a":1}'
... '{"c":1, "d":[1,2,3]}'
... '{"b":{"1":2,"3":4}, "d":1}'
... ''')
>>> sql("select jdictgroupunion(a) from table1")
jdictgroupunion(a)
-------------------------
{"b":2,"a":1,"c":1,"d":3}
"""
registered = True #Value to define db operator
def __init__(self):
self.outgroup = OrderedDict()
def step(self, *args):
for d in args:
for x, v in json.loads(d, object_pairs_hook=OrderedDict).iteritems():
vlen = 1
if type(v) in (list, OrderedDict):
vlen = len(v)
try:
if vlen > self.outgroup[x]:
self.outgroup[x] = vlen
except KeyError:
self.outgroup[x] = vlen
def final(self):
return json.dumps(self.outgroup, separators=(',', ':'), ensure_ascii=False)
class jgroupunionkeys:
"""
.. function:: jgroupunionkeys(columns) -> jpack
Calculates the union of the jdict keys. Use it with care, because for performance
reasons the input data are not checked at all. They should all be jdicts.
Example:
>>> table1('''
... '{"1":1, "2":3}' '{"a":5}'
... '{"2":1, "3":3}' '{}'
... ''')
>>> sql("select jgroupunionkeys(a,b) from table1")
jgroupunionkeys(a,b)
--------------------
["1","2","a","3"]
>>> sql("select jgroupunionkeys('{}')")
jgroupunionkeys('{}')
---------------------
[]
"""
registered = True #Value to define db operator
def __init__(self):
self.outgroup = OrderedDict()
self.outgroupset = set()
def step(self, *args):
for arg in args:
v = json.loads(arg)
if not set(v).issubset(self.outgroup):
self.outgroupset.update(v)
self.outgroup.update([(k, None) for k in json.loads(arg, object_pairs_hook=OrderedDict).iterkeys()])
def final(self):
return jopts.toj(list(self.outgroup))
class jgroupuniquelimit:
"""
.. function:: jgroupuniquelimit(jpack, k, limit) -> jpack
Returns the k where the unique values inside all jpacks have reached limit.
Example:
>>> table1('''
... '[1,2]' 1
... '[2,3,4,5]' 2
... '[2,4]' 3
... 5 4
... ''')
>>> sql("select jgroupuniquelimit(a,b,3) from table1")
jgroupuniquelimit(a,b,3)
------------------------
2
"""
registered = True #Value to define db operator
def __init__(self):
self.gset = set()
self.k = None
def step(self, *args):
if self.k is None:
self.gset.update([(x, None) for x in jopts.fromj(args[0])])
if len(self.gset) >= args[-1]:
self.k = args[1]
def final(self):
return self.k
if not ('.' in __name__):
"""
This is needed to be able to test the function, put it at the end of every
new function you create
"""
import sys
import setpath
from functions import *
testfunction()
if __name__ == "__main__":
reload(sys)
sys.setdefaultencoding('utf-8')
import doctest
doctest.testmod()

View File

@ -0,0 +1,415 @@
import re
import itertools
import setpath
import functions
import lib.jopts as jopts
from operator import itemgetter
import random
__docformat__ = 'reStructuredText en'
re_params=re.compile('(\w*):(.*)')
def consumer(func):
"""A decorator, advances func to its first yield point when called.
"""
from functools import wraps
@wraps(func)
def wrapper(*args,**kw):
gen = func(*args, **kw)
gen.next()
return gen
return wrapper
class freqitemsets:
"""
.. function:: freqitemsets(datacol, [threshold, noautothres, stats, maxlen]) -> [itemset_id:int, itemset_length:int, itemset_frequency:int, item:text]
Calculates frequent itemsets on a given column (datacol). The algorithm is tuned for the
case when we have many different items (in the order of millions), many input itemsets, but
small itemset length (10-20).
Returned table schema:
:itemset_id: Automatic itemset id
:itemset_length: Length of itemset
:itemset_frequency: How many times an itemset has been found
:item: Itemset's item value
Parameters:
:datacol:
Column on which to calculate frequent itemsets
:threshold: Default is 2
How many times an freq. itemset must appear for it to appear in the results
:noautothres: 1/0 (Default is 0)
Do not calculate the threshold automatically
:stats: 1/0 (Default is 0)
Return frequent itemset statistics
:maxlen: NUMBER (Default is no limit at all)
Maximum itemset length to search
Examples:
>>> table1('''
... 'car wood bike' 'first group'
... 'car car wood' 'first group'
... 'car wood' 'first group'
... 'car wood ice' 'first group'
... 'ice' 'second group'
... 'car ice' 'second group'
... 'car cream toy' 'second group'
... 'icecream ice car toy' 'second group'
... ''')
>>> sql("select b,freqitemsets(a, 'threshold:2', 'noautothres:1', 'maxlen:2') from table1 group by b")
b | itemset_id | itemset_length | itemset_frequency | item
---------------------------------------------------------------------
first group | 1 | 1 | 4 | wood
first group | 2 | 1 | 4 | car
first group | 3 | 2 | 4 | car
first group | 3 | 2 | 4 | wood
second group | 1 | 1 | 3 | ice
second group | 2 | 1 | 3 | car
second group | 3 | 1 | 2 | toy
second group | 4 | 2 | 2 | car
second group | 4 | 2 | 2 | ice
second group | 5 | 2 | 2 | car
second group | 5 | 2 | 2 | toy
>>> sql("select b,freqitemsets(a, 'stats:1') from table1 group by b")
b | MaxTransactionLength | CombinationCount | PassedTransactions | ValidKeywords
-------------------------------------------------------------------------------------------
first group | 3 | 2 | 3 | 2
first group | 3 | 1 | 1 | 2
first group | 3 | 0 | 0 | 0
second group | 4 | 3 | 3 | 3
second group | 4 | 0 | 3 | 0
"""
registered=True
multiset=True
def __init__(self):
self.threshold=2
self.startingthreshold=2
self.autothres=1
self.compress=0
self.initstatic=False
self.input={}
self.maxlength=0
self.kwcode={}
self.codekw={}
self.maxkwcode=0
self.overthres={}
self.belowthres={}
self.passedkw={}
self.init=True
self.itemset_id=0
self.maxlen=None
self.stats=False
def initargs(self, args):
self.init=False
for i in xrange(1, len(args)):
v=re_params.match(args[i])
if v is not None and v.groups()[0]!='' and v.groups()[1]!='' and i>0:
v=v.groups()
if v[0]=='threshold':
try:
self.threshold=int(v[1])
self.startingthreshold=self.threshold
except KeyboardInterrupt:
raise
except:
raise functions.OperatorError("FreqItemsets",'No integer value given for threshold')
if v[0]=='noautothres':
self.autothres=0
if v[0]=='compress':
self.compress=1
if v[0]=='maxlen':
self.maxlen=int(v[1])
if v[0]=='stats':
self.stats=True
def demultiplex(self, data):
iterable=None
iterpos=-1
for i in xrange(len(data)):
if hasattr(data[i],'__iter__')==True:
iterable=data[i]
iterpos=i
break
if iterpos==-1:
yield list(data)
else:
pre=list(data[0:iterpos])
post=list(data[iterpos+1:])
for i in iterable:
if hasattr(i,'__iter__')==False:
yield pre+[i]+post
else:
yield pre+list(i)+post
def insertcombfreq(self, comb, freq):
if comb in self.overthres:
self.overthres[comb]+=freq
else:
if comb in self.belowthres:
self.belowthres[comb]+=freq
else:
self.belowthres[comb]=freq
if self.belowthres[comb]>=self.threshold:
self.overthres[comb]=self.belowthres[comb]
del(self.belowthres[comb])
for k in comb:
if self.compress==0:
self.passedkw[k]=True
elif not k in self.passedkw:
self.passedkw[k]=self.overthres[comb]
else:
self.passedkw[k]+=self.overthres[comb]
def insertitemset(self, itemset):
if itemset not in self.input:
self.input[itemset]=1
else:
self.input[itemset]+=1
def cleanitemsets(self, minlength):
newitemsets={}
for k,v in self.input.iteritems():
itemset=tuple(i for i in k if i in self.passedkw)
if self.compress==1:
esoteric_itemset=tuple(i for i in itemset if self.passedkw[i]==v)
if len(esoteric_itemset)>0:
if len(itemset)>=minlength:
self.overthres[itemset]=v
itemset=tuple(i for i in itemset if self.passedkw[i]!=v)
if len(itemset)>=minlength:
if itemset not in newitemsets:
newitemsets[itemset]=v
else:
newitemsets[itemset]+=v
self.input=newitemsets
def step(self, *args):
if self.init==True:
self.initargs(args)
if len(args[0])==0:
return
itms=sorted(set(args[0].split(' ')))
itms=[x for x in itms if x!='']
li=len(itms)
if li>0:
if li>self.maxlength:
self.maxlength=li
inputkws=[]
for kw in itms:
if len(kw)==0:
print itms, args[0], len(args[0]), li
if kw not in self.kwcode:
self.kwcode[kw]=self.maxkwcode
self.codekw[self.maxkwcode]=kw
inputkws.append(self.maxkwcode)
self.insertcombfreq( (self.maxkwcode,),1 )
self.maxkwcode+=1
else:
itm=self.kwcode[kw]
self.insertcombfreq( (itm,),1 )
inputkws.append(itm)
if len(inputkws)>1:
self.insertitemset(tuple(inputkws))
def final(self):
if not self.stats:
yield ('itemset_id', 'itemset_length', 'itemset_frequency', 'item')
else:
yield ('MaxTransactionLength', 'CombinationCount', 'PassedTransactions', 'ValidKeywords')
splist=[{},{}]
del(self.kwcode)
splist[1]=self.overthres
if self.stats:
yield [self.maxlength, len(splist[1]), len(self.input), len(self.passedkw)]
if not self.stats:
for its,v in sorted(splist[1].items(), key=itemgetter(1),reverse=True):
self.itemset_id+=1
for i in self.demultiplex( (self.itemset_id, len([self.codekw[i] for i in its]), v, [self.codekw[i] for i in its]) ):
yield i
if self.maxlen==None:
self.maxlen=self.maxlength
for l in xrange(2, min(self.maxlength+1, self.maxlen+1)):
splist.append({})
self.belowthres={}
self.overthres={}
prevl=l-1
# Autothresholding
if self.autothres==1:
if len(self.input)==0 or len(self.passedkw)==0:
break
else:
self.threshold=self.startingthreshold + int(len(self.passedkw)/len(self.input))
self.cleanitemsets(l)
self.passedkw={}
prevsplist = splist[prevl]
icombs = itertools.combinations
insertcomb = self.insertcombfreq
for k,v in self.input.iteritems():
for k in icombs(k,l):
insertit=True
for i1 in icombs(k, prevl):
if i1 not in prevsplist:
insertit=False
break
if insertit:
insertcomb( k,v )
splist[l-1]={}
splist[l]=self.overthres
if self.stats:
yield [self.maxlength, len(splist[l]), len(self.input), len(self.passedkw)]
if not self.stats:
for its,v in sorted(splist[l].items(), key=itemgetter(1),reverse=True):
self.itemset_id+=1
for i in self.demultiplex( (self.itemset_id, len([self.codekw[i] for i in its]), v, [self.codekw[i] for i in its]) ):
yield i
del(self.overthres)
del(self.belowthres)
del(self.passedkw)
del(self.input)
del(self.codekw)
del(splist)
class sampledistvals:
"""
.. function:: sampledistvals(sample_size, C1, C2, C3) -> [C1, C2, C3]
Sampledistvals returns sample_size distinct values for each of the input C1..Cn columns.
>>> table1('''
... test1 2 3
... test1 2 3
... test2 4 2
... test4 2 t
... ''')
>>> sql("select sampledistvals(3, a, b, c) from table1")
C1 | C2 | C3
---------------------------------------------
["test1","test2","test4"] | [2,4] | [2,3,"t"]
"""
registered=True
def __init__(self):
self.vals=None
self.lenargs = -1
self.init=True
def step(self, *args):
if self.init:
self.lenargs = len(args)
self.vals = a=[set() for i in xrange(self.lenargs-1)]
self.init = False
for i in xrange(1, self.lenargs):
if len(self.vals[i-1])<args[0] and args[i] not in self.vals[i-1]:
self.vals[i-1].add(args[i])
def final(self):
yield tuple(['C'+str(i) for i in xrange(1, self.lenargs)] )
yield [jopts.toj(list(i)) for i in self.vals]
class samplegroup:
"""
.. function:: samplegroup(sample_size, C1, C2, C3)
Returns a random sample_size set of rows.
>>> table1('''
... test1 2 3
... test1 2 3
... test2 4 2
... test4 2 t
... ''')
>>> sql("select samplegroup(2, a, b, c) from table1") # doctest: +ELLIPSIS
C1 | C2 | C3
---------------
...
>>> sql("select samplegroup(2) from (select 5 where 5=6)") # doctest: +ELLIPSIS
"""
registered=True
def __init__(self):
self.samplelist = []
self.index = 0
self.random = random.randint
def step(self, *args):
# Generate the reservoir
if self.index < args[0]:
self.samplelist.append(args)
else:
r = self.random(0, self.index)
if r < args[0]:
self.samplelist[r] = args
self.index += 1
def final(self):
if self.samplelist == []:
yield tuple(['C1'])
else:
yield tuple(['C'+str(i) for i in xrange(1, len(self.samplelist[0]))] )
for r in self.samplelist:
yield list(r[1:])
if not ('.' in __name__):
"""
This is needed to be able to test the function, put it at the end of every
new function you create
"""
import sys
import setpath
from functions import *
testfunction()
if __name__ == "__main__":
reload(sys)
sys.setdefaultencoding('utf-8')
import doctest
doctest.testmod()

View File

@ -0,0 +1,71 @@
import functions
import operator
class partialsort:
"""
.. function:: partialsort(n,col1,col2,col3,....)
sorts the first n columns of its input
:Returned multiset schema:
Columns are automatically named as col1, col2 ...
Examples:
>>> table1('''
... aa 43
... ac 34
... ab 21
... as 23
... ''')
>>> sql("select partialsort(1,a,b) from table1")
c1 | c2
-------
aa | 43
ab | 21
ac | 34
as | 23
"""
registered=True
def __init__(self):
self.topn=[]
self.lessval=None
self.stepsnum=0
self.sortnum = None
def step(self, *args):
if len(args)<2:
raise functions.OperatorError("partialsort","Wrong number of arguments")
if not self.sortnum:
self.sortnum = tuple(i for i in xrange(args[0]))
self.topn.append(args[1:])
self.stepsnum+=1
pass
def final(self):
yield tuple('c'+str(i) for i in xrange(1,len(self.topn[0])+1))
self.topn.sort(key=operator.itemgetter(*self.sortnum))
for el in self.topn:
yield el
if not ('.' in __name__):
"""
This is needed to be able to test the function, put it at the end of every
new function you create
"""
import sys
import setpath
from functions import *
testfunction()
if __name__ == "__main__":
reload(sys)
sys.setdefaultencoding('utf-8')
import doctest
doctest.testmod()

View File

@ -0,0 +1,396 @@
import setpath
import Queue
import functions
__docformat__ = 'reStructuredText en'
class imax:
"""
.. function:: imax(i,value)
Returns the i-th max value of the group.
Examples:
>>> table1('''
... 34 la
... 18 lo
... 120.0 all
... ''')
>>> sql("select imax(1,a) as first from table1")
first
-----
120
>>> sql("select imax(3,a) as third from table1")
third
-----
18
>>> sql("select imax(2,cast( a as text)) as secstr from table1")
secstr
------
18
>>> sql("select imax(4,a) from table1")
imax(4,a)
---------
None
>>> sql("select imax(4,a) from (select 5 as a where a!=5)")
imax(4,a)
---------
None
"""
registered=True
def __init__(self):
self.topn=None
self.size=None
self.strtype=False
self.anytype=True
self.lessval=None
self.stepsnum=0
self.valarg=None
def step(self, *args):
if not args:
raise functions.OperatorError("imax","No arguments")
if len(args)<2:
raise functions.OperatorError("imax","Wrong number of arguments")
if not self.size:
try:
self.size=int(args[0])
self.topn=Queue.PriorityQueue(self.size)
except ValueError:
raise functions.OperatorError("imax","Wrong type in first argument")
curval=args[1]
if not self.topn.full():
self.topn.put_nowait(curval)
else:
curless=self.topn.get()
self.topn.put_nowait(max(curval,curless))
self.stepsnum+=1
def final(self):
if not self.size:
return
if self.stepsnum<self.size:
return None
return self.topn.get()
class q2list:
def __init__(self,queue):
self.q=queue
def __iter__(self):
return self
def next(self):
if self.q.empty():
raise StopIteration
a=self.q.get_nowait()
self.q.put_nowait(a)
return a
def typed(arg):
try:
arg=int(arg)
except ValueError:
try:
arg=float(arg)
except ValueError:
pass
return
class minrow:
"""
.. function:: minrow(compare,value)
Compares group members over the first argument (i.e. *compare*).
When the minimum is located, it returns the corresponding value in the second argument (i.e. *value*).
Examples:
>>> table1('''
... 34 la
... 18 lo
... 120.0 all
... ''')
>>> sql("select minrow(a,b) as b from table1")
b
--
lo
>>> sql("select minrow(a,a) as a from table1")
a
--
18
.. doctest::
:hide:
>>> sql("select minrow(a,a) as a from (select 5 as a where a!=5)")
a
----
None
"""
registered=True
def __init__(self):
self.minv=None
def step(self, *args):
if not args:
raise functions.OperatorError("minrow","No arguments")
if len(args)!=2:
raise functions.OperatorError("minrow","Wrong number of arguments")
if not self.minv:
self.minv=(args[0],args[1])
elif args[0]<self.minv[0]:
self.minv=(args[0],args[1])
def final(self):
if not self.minv:
return None
return self.minv[1]
class maxrow:
"""
.. function:: maxrow(compare,value)
Compares group members over the first argument (i.e. *compare*).
When the maximum is located, it returns the corresponding value in the second argument (i.e. *value*).
Examples:
>>> table1('''
... 34 la
... 18 lo
... 120.0 all
... ''')
>>> sql("select maxrow(a,b) as b from table1")
b
---
all
>>> sql("select maxrow(a,a) as a from table1")
a
---
120
>>> sql("select maxrow(b,a) as a from table1")
a
--
18
"""
registered=True
def __init__(self):
self.maxv=None
self.first=True
def step(self, *args):
if self.first:
if not args:
raise functions.OperatorError("maxrow","No arguments")
if len(args)!=2:
raise functions.OperatorError("maxrow","Wrong number of arguments")
self.maxv=(args[0],args[1])
self.first=False
return
self.maxv=max(self.maxv,args)
def final(self):
if not self.maxv:
return None
return self.maxv[1]
class groupdiff:
"""
.. function:: groupdiff(compare,values)
Compares group members over the first argument (i.e. *compare*). It keeps only the rows where *compare* changes.
It appends a column at the end containing how many times *compare* repeats.
Examples:
>>> table1('''
... 0 a
... 0 b
... 1 c
... 1 d
... 2 e
... 3 e
... 3 f
... 3 g
... ''')
>>> sql("select groupdiff(a,b) as b from table1")
b1 | b2 | b3
------------
0 | a | 2
1 | c | 2
2 | e | 1
3 | e | 3
>>> sql("select groupdiff(a) as a from table1")
a1 | a2
-------
0 | 2
1 | 2
2 | 1
3 | 3
>>> sql("select groupdiff(b,a) as a from table1")
a1 | a2 | a3
------------
a | 0 | 1
b | 0 | 1
c | 1 | 1
d | 1 | 1
e | 2 | 2
f | 3 | 1
g | 3 | 1
"""
registered=True
def __init__(self):
self.first=True
self.data=[]
self.prevcomp=None
self.size=0
self.repeat=1
def step(self, *args):
if self.first:
if not args:
raise functions.OperatorError("groupdiff","No arguments")
self.prevcomp=args[0]
self.data.append(list(args))
self.first=False
self.size=len(args)
return
if args[0]!=self.prevcomp:
self.prevcomp=args[0]
self.data[-1].append(self.repeat)
self.data.append(list(args))
self.repeat=1
else:
self.repeat+=1
def final(self):
self.data[-1].append(self.repeat)
yield tuple(["compid"]+["C"+str(i) for i in xrange(1,self.size)]+["repetition"])
for i in self.data:
yield i
class ontop:
"""
.. function:: ontop(n,compare,value1,value2,....) -> [colname1, colname2 ...]
Compares group members over the second argument (i.e. *compare*), so as to locate the top *n* members
(specified in the first argument) and then returns the corresponding data under the specified columns
*value1, value2, ....*.
:Returned multiset schema:
Columns are automatically named as *colname1 text, colname2 text...*
.. seealso::
* :ref:`tutmultiset` functions
Examples:
>>> table1('''
... 34 la
... 18 lo
... 120.0 all
... ''')
>>> sql("select ontop(1,a,b) from table1")
top1
----
all
>>> sql("select ontop(2,a,a,b) from table1")
top1 | top2
-----------
120 | all
34 | la
>>> sql("select ontop(2,a,a,b,a,b) from table1")
top1 | top2 | top3 | top4
-------------------------
120 | all | 120 | all
34 | la | 34 | la
>>> sql("select ontop(pk) from (select 5 as pk where pk!=5)")
top1
-
"""
registered=True
multiset=True
def __init__(self):
self.topn=None
self.size=None
self.lessval=None
self.stepsnum=0
self.argnum = 1
def step(self, *args):
if not args:
raise functions.OperatorError("ontop","No arguments")
if len(args)<3:
raise functions.OperatorError("ontop","Wrong number of arguments")
if not self.size:
try:
self.size=int(args[0])
self.topn=Queue.PriorityQueue(self.size)
self.argnum = len(args)-2
except ValueError:
raise functions.OperatorError("ontop","Wrong type in first argument")
inparg=args[1]
outarg=args[2:]
if not self.topn.full():
self.topn.put_nowait((inparg,outarg))
else:
inparg_old , outarg_old=self.topn.get_nowait()
self.topn.put_nowait(max((inparg,outarg),(inparg_old ,outarg_old)))
self.stepsnum+=1
def final(self):
output=[]
if self.topn:
while not self.topn.empty():
output+=[self.topn.get_nowait()[1]]
yield tuple(["top"+str(i+1) for i in xrange(self.argnum)])
for el in reversed(output):
yield el
if not ('.' in __name__):
"""
This is needed to be able to test the function, put it at the end of every
new function you create
"""
import sys
import setpath
from functions import *
testfunction()
if __name__ == "__main__":
reload(sys)
sys.setdefaultencoding('utf-8')
import doctest
doctest.testmod()

View File

@ -0,0 +1,3 @@
import sys, os
curmodulepath = os.path.dirname( os.path.abspath(__file__) )
sys.path.append(os.path.abspath(os.path.join(curmodulepath,'..','..')))

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,667 @@
import setpath
import Queue
import functions
from lib import iso8601
from operator import itemgetter
from lib import jopts
from lib.unicodeops import unistr
__docformat__ = 'reStructuredText en'
def timedelta2millisec(tdelta):
return tdelta.days*24*60*60*1000+tdelta.seconds*1000+tdelta.microseconds
class groupsum:
"""
.. function:: groupsum(n,col1,col2,col3,....)
It groups by the first n columns of the input, and sums/jsets the rest.
:Returned schema:
Columns are automatically named as col1, col2 ...
Examples:
>>> table1('''
... aa t1 43
... ac t2 34
... aa t3 12
... ab t4 21
... ac t5 14
... as t6 23
... ''')
>>> sql("select groupsum(1,a,b,c) from table1")
c1 | c2 | c3
---------------------
ac | ["t2","t5"] | 48
aa | ["t1","t3"] | 55
ab | t4 | 21
as | t6 | 23
"""
registered=True
def __init__(self):
self.notchecked = True
self.groupsdict = {}
self.grouplen = 0
self.numofargs = 0
def step(self, *args):
if self.notchecked:
if len(args)<2:
raise functions.OperatorError("groupsum","Wrong number of arguments")
self.grouplen = args[0]
self.numofargs = len(args)
self.notchecked = False
groupkey = args[1:self.grouplen+1]
try:
group = self.groupsdict[groupkey]
j = 0
for i in xrange(self.grouplen+1,self.numofargs):
group[j].append(args[i])
j += 1
except KeyError:
self.groupsdict[groupkey] = [[x] for x in args[self.grouplen+1:]]
def final(self):
yield tuple('c'+str(i) for i in xrange(1,self.numofargs))
for groupkey, sumcols in self.groupsdict.iteritems():
cols = list(groupkey)
for col in sumcols:
try:
cols.append(sum(col))
except TypeError:
cols.append(jopts.toj(sorted(set( jopts.fromj(*col) ))))
yield cols
class groupmax:
"""
.. function:: groupmax(n,col1,col2,col3,....)
It groups by the first n columns of the input, and returns the maximum value of the rest.
:Returned schema:
Columns are automatically named as col1, col2 ...
Examples:
>>> table1('''
... aa t1 43
... ac t2 34
... aa t3 12
... ab t4 21
... ac t5 14
... as t6 23
... ''')
>>> sql("select groupmax(1,a,b,c) from table1")
c1 | c2 | c3
------------
ac | t5 | 34
aa | t3 | 43
ab | t4 | 21
as | t6 | 23
"""
registered=True
def __init__(self):
self.notchecked = True
self.groupsdict = {}
self.grouplen = 0
self.numofargs = 0
def step(self, *args):
if self.notchecked:
if len(args)<2:
raise functions.OperatorError("groupmax","Wrong number of arguments")
self.grouplen = args[0]
self.numofargs = len(args)
self.notchecked = False
groupkey = args[1:self.grouplen+1]
try:
group = self.groupsdict[groupkey]
j = 0
for i in xrange(self.grouplen+1,self.numofargs):
group[j].append(args[i])
j += 1
except KeyError:
self.groupsdict[groupkey] = [[x] for x in args[self.grouplen+1:]]
def final(self):
yield tuple('c'+str(i) for i in xrange(1,self.numofargs))
for groupkey, sumcols in self.groupsdict.iteritems():
cols = list(groupkey)
for col in sumcols:
cols.append(max(col))
yield cols
class condbreak:
"""
.. function:: condbreak(groupid, C1, C2 ,...., condition, orderby) -> [bgroupid,C1,C2....]
Returns an expanded *groupid* and the *value1...valueN*, perfoming new groupings when condition is true. Rows grouped together
are the ones that order by *orderby* column have no intermediate true values for *condition*.
:Returned multiset schema:
- *bgroupid*
*groupid* appended with an integer value indicating the subgroup of the row.
- *C1, C2 ..*
The input values of the row.
.. seealso::
* :ref:`tutmultiset` functions
>>> table1('''
... 1 user1 open
... 2 user1 read
... 3 user1 close
... 4 user1 open
... 5 user1 write
... 6 user1 close
... 7 user2 open
... 8 user2 write
... ''')
>>> sql("select condbreak(b,c,c='open',a) from table1 group by b")
bgroupid | C1
----------------
user11 | open
user11 | read
user11 | close
user12 | open
user12 | write
user12 | close
user21 | open
user21 | write
>>> sql("select condbreak(b,c,c='open',a) from (select 4 as a, 6 as b, 9 as c where c!=9)")
"""
registered=True
multiset=True
def __init__(self):
self.vals=[]
def step(self, *args):
if not args:
raise functions.OperatorError("condbreak","No arguments")
if len(args)<4:
raise functions.OperatorError("condbreak","Wrong number of arguments")
self.vals.append(list(args))
def final(self):
self.vals.sort(key=lambda x:x[-1])
if self.vals==[]:
size=0
else:
size=len(self.vals[0])-2
if size<=0:
yield ("bgroupid","C1")
else:
yield tuple(["bgroupid"]+["C"+str(i+1) for i in xrange(size-1)])
counter=0
for el in self.vals:
if el[-2]==True:
counter+=1
bid=unistr(el[0])+str(counter)
yield [bid]+el[1:-2]
class datediffbreak:
"""
.. function:: datediffbreak(groupid, C1, C2 ,...., date, maxdiff[,'order',orderbycol1,orderbycol2,...]) -> [bgroupid,C1,C2....]
Returns an expanded *groupid* and the *value1...valueN*, perfoming new groupings when subsequent rows *date* values differ more than *maxdiff* milliseconds. Rows grouped together
are the ones that order by *orderby* column or if ommited by the given order have less *date* distance than *maxdiff*. Input dates should be in :ref:`ISO 8601 format <iso8601>`.
:Returned multiset schema:
- *bgroupid*
*groupid* appended with an integer value indicating the subgroup of the row.
- *C1, C2 ..*
The input values of the row.
.. seealso::
* :ref:`tutmultiset` functions
>>> table1('''
... 1 session1 '2007-01-01 00:03:13'
... 2 session1 '2007-01-01 00:03:27'
... 3 session1 '2007-01-01 00:03:36'
... 4 session2 '2007-01-01 00:04:39'
... 5 session2 '2007-01-01 00:04:40'
... 6 session3 '2007-01-01 00:04:49'
... 7 session3 '2007-01-01 00:04:59'
... ''')
>>> sql("select datediffbreak(b,a,c,10*1000,'order',c,a) from table1 group by b")
bgroupid | C1
--------------
session10 | 1
session11 | 2
session11 | 3
session20 | 4
session20 | 5
session30 | 6
session30 | 7
.. doctest::
:hide:
>>> sql("select datediffbreak(b,c,c='open',a) from (select 4 as a, 6 as b, 9 as c where c!=9)")
bgroupid | C1
---------------
None | None
>>> sql("select datediffbreak(b,a,c,10*1000,a,c) from table1 group by b") #doctest:+ELLIPSIS +NORMALIZE_WHITESPACE
Traceback (most recent call last):
...
OperatorError: Madis SQLError:
Operator DATEDIFFBREAK: Wrong date format: 1
"""
registered=True
def __init__(self):
self.vals=[]
self.init=True
self.position=None
self.comparesize=0
self.fullsize=0
def initargs(self, args):
self.init=False
if not args:
raise functions.OperatorError("datediffbreak","No arguments")
if len(args)<4:
raise functions.OperatorError("datediffbreak","Wrong number of arguments")
self.maxdiff=args[-1]
for i in xrange(len(args)):
if args[i]=='order':
self.position=i
self.maxdiff=args[i-1]
self.comparesize=len(args)-(i+1)
if len(args)<5:
raise functions.OperatorError("datediffbreak","Wrong number of arguments")
break
def step(self, *args):
if self.init:
self.initargs(args)
if not self.position:
self.vals.append(list(args[:-1]))
else:
self.vals.append(list(args[:self.position-1]+args[self.position+1:]))
def final(self):
if self.position:
self.vals.sort(key=lambda x:tuple(x[-self.comparesize:]))
if self.vals==[]:
size=0
else:
size=len(self.vals[0])-self.comparesize-1
if size<=0:
yield ("bgroupid","C1")
yield [None, None]
return
yield tuple(["bgroupid"]+["C"+str(i) for i in xrange(1,size)])
counter=0
dt=None
dtpos=self.comparesize+1
for el in self.vals:
try:
dtnew=iso8601.parse_date(el[-dtpos])
except Exception:
raise functions.OperatorError("datediffbreak","Wrong date format: %s" %(el[-dtpos]))
if dt and timedelta2millisec(dtnew-dt)>self.maxdiff:
counter+=1
dt=dtnew
bid=unistr(el[0])+str(counter)
yield [bid]+el[1:-dtpos]
class datediffnewsesid:
"""
.. function:: datediffnewsesid(maxdiff, date, groupid, C1, C2 ,....) -> [bgroupid, C1, C2, ...]
Returns only the C1, C2, ... that should be updated with bgroupid, so as for the input groups to be effectively broken on maxdiff times.
Input dates should be in :ref:`ISO 8601 format <iso8601>`.
:Returned multiset schema:
- *bgroupid*
*groupid* appended with an integer value indicating the subgroup of the row.
- *C1, C2 ..*
The input values of the row.
>>> table1('''
... 1 session1 '2007-01-01 00:03:13'
... 2 session1 '2007-01-01 00:03:27'
... 3 session1 '2007-01-01 00:03:36'
... 4 session2 '2007-01-01 00:04:39'
... 5 session2 '2007-01-01 00:05:40'
... 6 session3 '2007-01-01 00:04:49'
... 7 session3 '2007-01-01 00:06:59'
... 8 session3 '2007-01-01 00:06:59'
... 9 session4 '2007-01-01 00:04:59'
... ''')
>>> sql("select datediffnewsesid(10, c, b, a) from table1 group by b")
bgroupid | C1
--------------
session11 | 2
session11 | 3
session21 | 5
session31 | 7
session31 | 8
.. doctest::
:hide:
>>> sql("select datediffnewsesid(10, c, b, a) from (select 4 as a, 6 as b, 9 as c where c!=9)")
bgroupid | C1
---------------
None | None
>>> table2('''
... 1 session1 '2007-05-01T21:10:51Z'
... 9 session1 '2012-01-08T18:24:32Z'
... ''')
>>> sql("select datediffnewsesid(1800, c, b, a) from table2 group by b")
bgroupid | C1
--------------
session11 | 9
"""
registered=True
def __init__(self):
self.vals=[]
self.init=True
self.maxdiff=0
def initargs(self, args):
self.init=False
if not args:
raise functions.OperatorError("datediffnewsesid","No arguments")
if len(args)<4:
raise functions.OperatorError("datediffnewsesid","Wrong number of arguments")
self.maxdiff=args[0]
def step(self, *args):
if self.init:
self.initargs(args)
self.vals.append(list(args[1:]))
def final(self):
lenofvals=len(self.vals)
if lenofvals<=0:
yield ("bgroupid", "C1")
yield [None, None, None]
return
yield tuple(["bgroupid"]+["C"+str(i) for i in xrange(1,len(self.vals[0])-1)])
counter=0
if lenofvals!=1:
for el in self.vals:
try:
el.insert(0,iso8601.parse_date(el[0]))
except Exception:
raise functions.OperatorError("datediffnewsesid","Wrong date format: %s" %(el[0]))
self.vals.sort(key=itemgetter(0))
dt=self.vals[0][0]
for el in self.vals[1:]:
dtnew=el[0]
diff=dtnew-dt
dt=dtnew
if (diff.days*86400+diff.seconds)>self.maxdiff:
counter+=1
if counter!=0:
bid=unistr(el[2])+str(counter)
yield [bid]+el[3:]
class datedifffilter:
"""
.. function:: datedifffilter(maxdiff, date, C1, C2 ....) -> [date,C1,C2....]
Returns only a subset of the provided entries, performing a sort of entry clustering based on the entries date difference. Each cluster is
represented by the latest entry.
The first argument defines the time differnece threshold that is employed for entry clustering, and it is provided in seconds.
The second argument is assumed to contain the date column. Entries are assumed to be provided in an ascending order by the date column.
Input dates should be in :ref:`ISO 8601 format <iso8601>`.
All subsequent columns remain unchanged.
:Returned multiset schema:
- *date, C1, C2 ..*
The selected input values of the row.
.. seealso::
* :ref:`tutmultiset` functions
>>> table1('''
... 2010-01-01T01:32:03Z value1
... 2010-01-01T01:32:04Z value2
... 2010-01-01T01:32:06Z value3
... 2010-01-01T01:32:08Z value4
... 2010-01-01T01:32:29Z value5
... 2010-01-01T02:35:03Z value6
... 2010-01-01T02:35:04Z value7
... 2010-01-01T03:55:04Z value8
... ''')
>>> sql("select datedifffilter(20, a,b) from table1")
date | C1
-----------------------------
2010-01-01T01:32:08Z | value4
2010-01-01T01:32:29Z | value5
2010-01-01T02:35:04Z | value7
2010-01-01T03:55:04Z | value8
>>> table1('''
... 2010-01-01T01:32:03Z value1
... ''')
>>> sql("select datedifffilter(20, a,b) from table1")
date | C1
-----------------------------
2010-01-01T01:32:03Z | value1
>>> table1('''
... '2010-01-01 01:32:03' value1
... '2010-01-01 01:32:04' value2
... '2010-01-01 01:32:06' value3
... '2010-01-01 01:32:08' value4
... '2010-01-01 01:32:29' value5
... '2010-01-01 02:35:03' value6
... '2010-01-01 02:35:04' value7
... '2010-01-01 03:55:04' value8
... ''')
>>> sql("select datedifffilter(30, a,b) from table1")
date | C1
----------------------------
2010-01-01 01:32:29 | value5
2010-01-01 02:35:04 | value7
2010-01-01 03:55:04 | value8
"""
registered=True
def __init__(self):
self.init=True
self.vals=[]
self.maxdiff=0
def initargs(self, args):
self.init=False
if not args:
raise functions.OperatorError("datedifffilter","No arguments")
if len(args)<2:
raise functions.OperatorError("datedifffilter","Wrong number of arguments")
self.maxdiff=args[0]
def step(self, *args):
if self.init==True:
self.initargs(args)
self.vals.append(list(args[1:]))
def final(self):
lenofvals=len(self.vals)
if lenofvals==0:
yield ("date","C1")
yield [None,None]
return
yield tuple(["date"]+["C"+str(i) for i in xrange(1, len(self.vals[0]))])
dt=None
dtpos=0
diff=0
if lenofvals==1:
yield(self.vals[dtpos])
else:
for el in self.vals:
el.append(iso8601.parse_date(el[0]))
self.vals.sort(key=itemgetter(-1))
for el in self.vals:
if dtpos<lenofvals-1:
dt = el[-1]
dtnew =self.vals[dtpos+1][-1]
diff=dtnew-dt
dtpos+=1
if (diff.days*86400+diff.seconds)>self.maxdiff:
yield(el[0:-1])
if dtpos==lenofvals-1:
yield(self.vals[dtpos][0:-1])
class datediffgroup:
"""
.. function:: datediffgroup(maxdiff, date, C1, C2 ....) -> [groupid, date,C1,C2....]
Performing a sort of entry clustering based on the entries date difference.
The cluster id that is assigned to each entry is returned in the first column, and it is followed by the entry's original contents.
The first argument defines the time differnece threshold that is employed for entry clustering, and it is provided in seconds.
The second argument is assumed to contain the date column. Entries are assumed to be provided in an ascending order by the date column.
Input dates should be in :ref:`ISO 8601 format <iso8601>`.
All subsequent columns remain unchanged.
:Returned multiset schema:
- *date, C1, C2 ..*
The selected input values of the row.
.. seealso::
* :ref:`tutmultiset` functions
>>> table1('''
... 2010-01-01T01:32:03Z value1
... 2010-01-01T01:32:04Z value2
... 2010-01-01T01:32:06Z value3
... 2010-01-01T01:32:08Z value4
... 2010-01-01T01:32:29Z value5
... 2010-01-01T02:35:03Z value6
... 2010-01-01T02:35:04Z value7
... 2010-01-01T03:55:04Z value8
... ''')
>>> sql("select datediffgroup(20,a,b) from table1")
groupid | date | C1
---------------------------------------
1 | 2010-01-01T01:32:03Z | value1
1 | 2010-01-01T01:32:04Z | value2
1 | 2010-01-01T01:32:06Z | value3
1 | 2010-01-01T01:32:08Z | value4
2 | 2010-01-01T01:32:29Z | value5
3 | 2010-01-01T02:35:03Z | value6
3 | 2010-01-01T02:35:04Z | value7
4 | 2010-01-01T03:55:04Z | value8
"""
registered=True
multiset=True
def __init__(self):
self.init=True
self.vals=[]
self.maxdiff=0
self.counter=0
self.tablesize=0
self.groupIdCounter=1
def initargs(self, args):
self.init=False
if not args:
raise functions.OperatorError("datediffgroup","No arguments")
if len(args)<2:
raise functions.OperatorError("datediffgroup","Wrong number of arguments")
self.tablesize=len(args)-1
self.maxdiff=args[0]
def step(self, *args):
if self.init==True:
self.initargs(args)
self.vals.append(list(args[1:]))
self.counter+=1
def final(self):
if self.tablesize<=0:
yield ("groupid","date","C1")
else:
yield tuple(["groupid"]+["date"]+["C"+str(i+1) for i in xrange(self.tablesize-1)])
dt=None
dtpos=0
diff=0
for el in self.vals:
if dtpos<self.counter-1:
dt = iso8601.parse_date(el[0])
dtnew =iso8601.parse_date(self.vals[dtpos+1][0])
diff=dtnew-dt
yield [str(self.groupIdCounter)]+el
if (diff.days*24*60*60+diff.seconds)>self.maxdiff:
self.groupIdCounter+=1
dtpos+=1
if dtpos==self.counter-1:
yield [str(self.groupIdCounter)]+self.vals[dtpos]
if not ('.' in __name__):
"""
This is needed to be able to test the function, put it at the end of every
new function you create
"""
import sys
import setpath
from functions import *
testfunction()
if __name__ == "__main__":
reload(sys)
sys.setdefaultencoding('utf-8')
import doctest
doctest.testmod()

Some files were not shown because too many files have changed in this diff Show More