1: // -----------------------------------------------------------
2: // -- An Asymptote package for drawing orbitals.
3: // -- Free under any GNU public license.
4: // -- (C) Copyright: Peter Luschny, 2008
5: // -- Version 1 Release 1
6: // -----------------------------------------------------------
7: // --
8: // -- This file is accompanying the package orbital.asy and
9: // -- provides structures and routines to generate orbitals.
10: // -- See also the file orbitalusage.asy, which illustrates
11: // -- the use of the structure 'orbitalgenerator'.
12: // --
13: // -- For more information see
14: // -- http://www.luschny.de/math/swing/orbital/orbitaldoc.pdf
15: // --
16: // -----------------------------------------------------------
17:
18: typedef void VISIT(int[]);
19:
20: struct OrbitalGenerator
21: {
22: private VISIT userhook;
23: private int N, n, t, count;
24: private bool isOdd;
25:
26: private void write(int[] jump)
27: {
28: string s;
29: for(int j : jump) { s += (string)j + ","; }
30: write(s);
31: }
32:
33: private void visit(int[] jump)
34: {
35: count = count + 1;
36:
37: if(userhook != null)
38: {
39: userhook(jump);
40: }
41: else { this.write(jump); }
42: }
43:
44: private void assemble(int[] c)
45: {
46: int[] q = new int[N];
47:
48: for(int i = 0; i < N; ++i){ q[i] = 1; }
49: for(int i = 0; i < t; ++i){ q[N-c[i+1]-1] = -1; }
50:
51: if(isOdd)
52: {
53: int[] s = {0};
54: for(int i = 0; i < n; ++i)
55: {
56: visit(concat(q[0:i],s,q[i:n]));
57: }
58: }
59: else { visit(q); }
60: }
61:
62: restricted static OrbitalGenerator
63: OrbitalGenerator(int len, VISIT hook = null)
64: {
65: if(len > 12)
66: {
67: write("Error! n is too big, n <= 12 required.");
68: write("I set n = 1.");
69: len = 1;
70: }
71:
72: OrbitalGenerator og = new OrbitalGenerator;
73:
74: bool isodd = len % 2 == 1;
75: int Len = isodd ? len - 1 : len;
76:
77: og.isOdd = isodd;
78: og.n = len;
79: og.N = Len;
80: og.t = quotient(Len, 2);
81: og.count = 0;
82: og.userhook = hook;
83:
84: return og;
85: }
86:
87: public int generate()
88: {
89: int[] c = new int[t + 3];
90: for(int j = 1; j <= t; ++j) { c[j] = j - 1; }
91: c[t + 1] = N; c[t + 2] = 0;
92:
93: // -- Algorithm L in Donald E. Knuth TAOCP 7.2.1.3
94: while(true)
95: {
96: assemble(c);
97: int j = 1;
98: while(c[j] + 1 == c[j + 1]) { c[j] = j - 1; ++j; }
99: if(j > t) { break; }
100: c[j] += 1 ;
101: }
102:
103: return count;
104: }
105:
106: } from OrbitalGenerator unravel OrbitalGenerator;
107:
108:
109: // ------------- End of struct OrbitalGenerator --------------
110:
111:
112: struct PrimeOrbital
113: {
114: restricted int[] jumps;
115: restricted int numer, denom;
116: restricted real balance;
117:
118: private static int[] primes = {
119: 2,3,5,7,11,13,17,19,23,29,31,37,41};
120:
121: private void primorial(int[] jump)
122: {
123: int i = 0; numer = 1; denom = 1;
124:
125: for(int j : jump)
126: {
127: if(j > 0) numer *= primes[i];
128: else if(j < 0) denom *= primes[i];
129: ++i;
130: }
131: balance = numer / denom ;
132: }
133:
134: restricted static PrimeOrbital PrimeOrbital(int[] jumps)
135: {
136: PrimeOrbital o = new PrimeOrbital;
137: o.jumps = jumps;
138: o.primorial(jumps);
139: return o;
140: }
141:
142: public void write()
143: {
144: string s;
145: for(int j : jumps) { s += (string)j + " " ; }
146:
147: string p = " ["+(string)numer+ "/" +(string)denom+"] "
148: +" "+format("%.3g", balance);
149:
150: write(s + p);
151: }
152:
153: } from PrimeOrbital unravel PrimeOrbital;
154:
155:
156: // --------------- End of struct PrimeOrbital ----------------
157:
158:
159: struct PrimeOrbitalGenerator
160: {
161: private PrimeOrbital[] urbi;
162: private OrbitalGenerator og;
163: private int urbI;
164:
165: private void insertOrbit(int[] jumps)
166: {
167: urbi[++urbI] = PrimeOrbital(jumps);
168: if(urbI == 0) return;
169:
170: PrimeOrbital temp;
171:
172: for(int top = 0; top < urbI; ++top)
173: {
174: for(int j = top ; j >= 0; --j)
175: {
176: if(urbi[j].balance < urbi[j+1].balance)
177: {
178: break;
179: }
180: temp = urbi[j];
181: urbi[j] = urbi[j+1];
182: urbi[j+1] = temp;
183: }
184: }
185: }
186:
187: private void visit(int[] jumps)
188: {
189: insertOrbit(jumps);
190: }
191:
192: restricted static PrimeOrbitalGenerator
193: PrimeOrbitalGenerator(int len)
194: {
195: PrimeOrbitalGenerator psog = new PrimeOrbitalGenerator;
196: psog.og = OrbitalGenerator(len, psog.visit);
197: return psog;
198: }
199:
200: public PrimeOrbital[] generate()
201: {
202: urbI = -1;
203: og.generate();
204: return urbi;
205: }
206:
207: public void write()
208: {
209: for(PrimeOrbital po : urbi) po.write();
210: }
211:
212: } from PrimeOrbitalGenerator unravel PrimeOrbitalGenerator;
213:
214:
215: // ----------- End of struct PrimeOrbitalGenerator -----------