xref: /inferno-os/appl/math/powers.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsythimplement Powers;
2*37da2899SCharles.Forsyth
3*37da2899SCharles.Forsythinclude "sys.m";
4*37da2899SCharles.Forsyth	sys: Sys;
5*37da2899SCharles.Forsythinclude "draw.m";
6*37da2899SCharles.Forsythinclude "arg.m";
7*37da2899SCharles.Forsythinclude "lock.m";
8*37da2899SCharles.Forsyth	lockm: Lock;
9*37da2899SCharles.Forsyth	Semaphore: import lockm;
10*37da2899SCharles.Forsyth
11*37da2899SCharles.ForsythPowers: module
12*37da2899SCharles.Forsyth{
13*37da2899SCharles.Forsyth	init: fn(nil: ref Draw->Context, nil: list of string);
14*37da2899SCharles.Forsyth};
15*37da2899SCharles.Forsyth
16*37da2899SCharles.ForsythMAXNODES: con (1<<20)/4;
17*37da2899SCharles.Forsyth
18*37da2899SCharles.Forsythverbose: int;
19*37da2899SCharles.Forsyth
20*37da2899SCharles.Forsyth# Doing
21*37da2899SCharles.Forsyth# 	powers -p 3
22*37da2899SCharles.Forsyth# gives
23*37da2899SCharles.Forsyth# 	[2] 1729 = 1**3 + 12**3 = 9**3 + 10**3
24*37da2899SCharles.Forsyth# 	[2] 4104 = 2**3 + 16**3 = 9**3 + 15**3
25*37da2899SCharles.Forsyth
26*37da2899SCharles.Forsyth# ie 1729 can be written in two ways as the sum of 2 cubes as can 4104.
27*37da2899SCharles.Forsyth
28*37da2899SCharles.Forsyth# The options are
29*37da2899SCharles.Forsyth
30*37da2899SCharles.Forsyth# -p	the power to use - default 2
31*37da2899SCharles.Forsyth# -n	the number of powers summed - default 2
32*37da2899SCharles.Forsyth# -f	the minimum number of ways found before reporting it - default 2
33*37da2899SCharles.Forsyth# -l	the least number to consider - default 0
34*37da2899SCharles.Forsyth# -m	the greatest number to consider - default 8192
35*37da2899SCharles.Forsyth
36*37da2899SCharles.Forsyth# Thus
37*37da2899SCharles.Forsyth# 	pow -p 4 -n 3 -f 3 -l 0 -m 1000000
38*37da2899SCharles.Forsyth# gives
39*37da2899SCharles.Forsyth# 	[3] 811538 = 12**4 + 17**4 + 29**4 = 7**4 + 21**4 + 28**4 = 4**4 + 23**4 + 27**4
40*37da2899SCharles.Forsyth
41*37da2899SCharles.Forsyth# ie fourth powers, 3 in each sum, minimum of 3 representations, numbers from 0-1000000.
42*37da2899SCharles.Forsyth
43*37da2899SCharles.Forsyth# [2] 25
44*37da2899SCharles.Forsyth# [3] 325
45*37da2899SCharles.Forsyth# [4] 1105
46*37da2899SCharles.Forsyth# [5] 4225
47*37da2899SCharles.Forsyth# [6] 5525
48*37da2899SCharles.Forsyth# [7] 203125
49*37da2899SCharles.Forsyth# [8] 27625
50*37da2899SCharles.Forsyth# [9] 71825
51*37da2899SCharles.Forsyth# [10] 138125
52*37da2899SCharles.Forsyth# [11] 2640625
53*37da2899SCharles.Forsyth# [12] 160225
54*37da2899SCharles.Forsyth# [13] 17850625
55*37da2899SCharles.Forsyth# [14] 1221025
56*37da2899SCharles.Forsyth# [15] 1795625
57*37da2899SCharles.Forsyth# [16] 801125
58*37da2899SCharles.Forsyth# [18] 2082925
59*37da2899SCharles.Forsyth# [20] 4005625
60*37da2899SCharles.Forsyth# [23] 30525625
61*37da2899SCharles.Forsyth# [24] 5928325
62*37da2899SCharles.Forsyth# [32] 29641625
63*37da2899SCharles.Forsyth
64*37da2899SCharles.Forsyth# [24] 5928325 = 63**2 + 2434**2 = 94**2 + 2433**2 = 207**2 + 2426**2 = 294**2 + 2417**2 = 310**2 + 2415**2 = 465**2 + 2390**2 = 490**2 + 2385**2 = 591**2 + 2362**2 = 690**2 + 2335**2 = 742**2 + 2319**2 = 849**2 + 2282**2 = 878**2 + 2271**2 = 959**2 + 2238**2 = 1039**2 + 2202**2 = 1062**2 + 2191**2 = 1201**2 + 2118**2 = 1215**2 + 2110**2 = 1290**2 + 2065**2 = 1410**2 + 1985**2 = 1454**2 + 1953**2 = 1535**2 + 1890**2 = 1614**2 + 1823**2 = 1633**2 + 1806**2 = 1697**2 + 1746**2
65*37da2899SCharles.Forsyth
66*37da2899SCharles.Forsyth# [32] 29641625 = 67**2 + 5444**2 = 124**2 + 5443**2 = 284**2 + 5437**2 = 320**2 + 5435**2 = 515**2 + 5420**2 = 584**2 + 5413**2 = 835**2 + 5380**2 = 955**2 + 5360**2 = 1180**2 + 5315**2 = 1405**2 + 5260**2 = 1460**2 + 5245**2 = 1648**2 + 5189**2 = 1795**2 + 5140**2 = 1829**2 + 5128**2 = 1979**2 + 5072**2 = 2012**2 + 5059**2 = 2032**2 + 5051**2 = 2245**2 + 4960**2 = 2308**2 + 4931**2 = 2452**2 + 4861**2 = 2560**2 + 4805**2 = 2621**2 + 4772**2 = 2840**2 + 4645**2 = 3005**2 + 4540**2 = 3035**2 + 4520**2 = 3320**2 + 4315**2 = 3365**2 + 4280**2 = 3517**2 + 4156**2 = 3544**2 + 4133**2 = 3664**2 + 4027**2 = 3715**2 + 3980**2 = 3803**2 + 3896**2
67*37da2899SCharles.Forsyth
68*37da2899SCharles.Forsyth# [2] 1729 = 1**3 + 12**3 = 9**3 + 10**3
69*37da2899SCharles.Forsyth# [2] 4104 = 2**3 + 16**3 = 9**3 + 15**3
70*37da2899SCharles.Forsyth# [3] 87539319 = 167**3 + 436**3 = 228**3 + 423**3 = 255**3 + 414**3
71*37da2899SCharles.Forsyth
72*37da2899SCharles.Forsyth# [2] 635318657 = 59**4 + 158**4 = 133**4 + 134**4
73*37da2899SCharles.Forsyth# [2] 3262811042 = 7**4 + 239**4 = 157**4 + 227**4
74*37da2899SCharles.Forsyth# [2] 8657437697 = 193**4 + 292**4 = 256**4 + 257**4
75*37da2899SCharles.Forsyth# [2] 68899596497 = 271**4 + 502**4 = 298**4 + 497**4
76*37da2899SCharles.Forsyth# [2] 86409838577 = 103**4 + 542**4 = 359**4 + 514**4
77*37da2899SCharles.Forsyth# [2] 160961094577 = 222**4 + 631**4 = 503**4 + 558**4
78*37da2899SCharles.Forsyth# [2] 2094447251857 = 76**4 + 1203**4 = 653**4 + 1176**4
79*37da2899SCharles.Forsyth# [2] 4231525221377 = 878**4 + 1381**4 = 997**4 + 1342**4
80*37da2899SCharles.Forsyth# [2] 26033514998417 = 1324**4 + 2189**4 = 1784**4 + 1997**4
81*37da2899SCharles.Forsyth# [2] 37860330087137 = 1042**4 + 2461**4 = 2026**4 + 2141**4
82*37da2899SCharles.Forsyth# [2] 61206381799697 = 248**4 + 2797**4 = 2131**4 + 2524**4
83*37da2899SCharles.Forsyth# [2] 76773963505537 = 1034**4 + 2949**4 = 1797**4 + 2854**4
84*37da2899SCharles.Forsyth# [2] 109737827061041 = 1577**4 + 3190**4 = 2345**4 + 2986**4
85*37da2899SCharles.Forsyth# [2] 155974778565937 = 1623**4 + 3494**4 = 2338**4 + 3351**4
86*37da2899SCharles.Forsyth# [2] 156700232476402 = 661**4 + 3537**4 = 2767**4 + 3147**4
87*37da2899SCharles.Forsyth# [2] 621194785437217 = 2694**4 + 4883**4 = 3966**4 + 4397**4
88*37da2899SCharles.Forsyth# [2] 652057426144337 = 604**4 + 5053**4 = 1283**4 + 5048**4
89*37da2899SCharles.Forsyth# [2] 680914892583617 = 3364**4 + 4849**4 = 4288**4 + 4303**4
90*37da2899SCharles.Forsyth# [2] 1438141494155441 = 2027**4 + 6140**4 = 4840**4 + 5461**4
91*37da2899SCharles.Forsyth# [2] 1919423464573697 = 274**4 + 6619**4 = 5093**4 + 5942**4
92*37da2899SCharles.Forsyth# [2] 2089568089060657 = 498**4 + 6761**4 = 5222**4 + 6057**4
93*37da2899SCharles.Forsyth# [2] 2105144161376801 = 2707**4 + 6730**4 = 3070**4 + 6701**4
94*37da2899SCharles.Forsyth# [2] 3263864585622562 = 1259**4 + 7557**4 = 4661**4 + 7269**4
95*37da2899SCharles.Forsyth# [2] 4063780581008977 = 5181**4 + 7604**4 = 6336**4 + 7037**4
96*37da2899SCharles.Forsyth# [2] 6315669699408737 = 1657**4 + 8912**4 = 7432**4 + 7559**4
97*37da2899SCharles.Forsyth# [2] 6884827518602786 = 635**4 + 9109**4 = 3391**4 + 9065**4
98*37da2899SCharles.Forsyth# [2] 7191538859126257 = 4903**4 + 9018**4 = 6842**4 + 8409**4
99*37da2899SCharles.Forsyth# [2] 7331928977565937 = 1104**4 + 9253**4 = 5403**4 + 8972**4
100*37da2899SCharles.Forsyth# [2] 7362748995747617 = 5098**4 + 9043**4 = 6742**4 + 8531**4
101*37da2899SCharles.Forsyth# [2] 7446891977980337 = 1142**4 + 9289**4 = 4946**4 + 9097**4
102*37da2899SCharles.Forsyth# [2] 7532132844821777 = 173**4 + 9316**4 = 4408**4 + 9197**4
103*37da2899SCharles.Forsyth# [2] 7985644522300177 = 6262**4 + 8961**4 = 7234**4 + 8511**4
104*37da2899SCharles.Forsyth
105*37da2899SCharles.Forsyth# 5, 6, 7, 8, 9, 10, 11 none
106*37da2899SCharles.Forsyth
107*37da2899SCharles.ForsythBtree: adt{
108*37da2899SCharles.Forsyth	sum: big;
109*37da2899SCharles.Forsyth	left: cyclic ref Btree;
110*37da2899SCharles.Forsyth	right: cyclic ref Btree;
111*37da2899SCharles.Forsyth};
112*37da2899SCharles.Forsyth
113*37da2899SCharles.ForsythDtree: adt{
114*37da2899SCharles.Forsyth	sum: big;
115*37da2899SCharles.Forsyth	freq: int;
116*37da2899SCharles.Forsyth	lst: list of array of int;
117*37da2899SCharles.Forsyth	left: cyclic ref Dtree;
118*37da2899SCharles.Forsyth	right: cyclic ref Dtree;
119*37da2899SCharles.Forsyth};
120*37da2899SCharles.Forsyth
121*37da2899SCharles.ForsythnCr(n: int, r: int): int
122*37da2899SCharles.Forsyth{
123*37da2899SCharles.Forsyth	if(r > n-r)
124*37da2899SCharles.Forsyth		r = n-r;
125*37da2899SCharles.Forsyth
126*37da2899SCharles.Forsyth	# f := g := 1;
127*37da2899SCharles.Forsyth	# for(i := 0; i < r; i++){
128*37da2899SCharles.Forsyth	# 	f *= n-i;
129*37da2899SCharles.Forsyth	# 	g *= i+1;
130*37da2899SCharles.Forsyth	# }
131*37da2899SCharles.Forsyth	# return f/g;
132*37da2899SCharles.Forsyth
133*37da2899SCharles.Forsyth	num := array[r] of int;
134*37da2899SCharles.Forsyth	den := array[r] of int;
135*37da2899SCharles.Forsyth	for(i := 0; i < r; i++){
136*37da2899SCharles.Forsyth		num[i] = n-i;
137*37da2899SCharles.Forsyth		den[i] = i+1;
138*37da2899SCharles.Forsyth	}
139*37da2899SCharles.Forsyth	for(i = 0; i < r; i++){
140*37da2899SCharles.Forsyth		for(j := 0; den[i] != 1; j++){
141*37da2899SCharles.Forsyth			if(num[j] == 1)
142*37da2899SCharles.Forsyth				continue;
143*37da2899SCharles.Forsyth			k := hcf(num[j], den[i]);
144*37da2899SCharles.Forsyth			if(k != 1){
145*37da2899SCharles.Forsyth				num[j] /= k;
146*37da2899SCharles.Forsyth				den[i] /= k;
147*37da2899SCharles.Forsyth			}
148*37da2899SCharles.Forsyth		}
149*37da2899SCharles.Forsyth	}
150*37da2899SCharles.Forsyth	f := 1;
151*37da2899SCharles.Forsyth	for(i = 0; i < r; i++)
152*37da2899SCharles.Forsyth		f *= num[i];
153*37da2899SCharles.Forsyth	return f;
154*37da2899SCharles.Forsyth}
155*37da2899SCharles.Forsyth
156*37da2899SCharles.ForsythnHr(n: int, r: int): int
157*37da2899SCharles.Forsyth{
158*37da2899SCharles.Forsyth	if(n == 0)
159*37da2899SCharles.Forsyth		return 0;
160*37da2899SCharles.Forsyth	return nCr(n+r-1, r);
161*37da2899SCharles.Forsyth}
162*37da2899SCharles.Forsyth
163*37da2899SCharles.ForsythnSr(n: int, i: int, j: int): int
164*37da2899SCharles.Forsyth{
165*37da2899SCharles.Forsyth	return nHr(j, n)-nHr(i, n);
166*37da2899SCharles.Forsyth	# s := 0;
167*37da2899SCharles.Forsyth	# for(k := i; k < j; k++)
168*37da2899SCharles.Forsyth	# 	s += nHr(k+1, n-1);
169*37da2899SCharles.Forsyth	# return s;
170*37da2899SCharles.Forsyth}
171*37da2899SCharles.Forsyth
172*37da2899SCharles.ForsythnSrmax(n: int, i: int, m: int): int
173*37da2899SCharles.Forsyth{
174*37da2899SCharles.Forsyth	s := 0;
175*37da2899SCharles.Forsyth	for(k := i; ; k++){
176*37da2899SCharles.Forsyth		s += nHr(k+1, n-1);
177*37da2899SCharles.Forsyth		if(s > m)
178*37da2899SCharles.Forsyth			break;
179*37da2899SCharles.Forsyth	}
180*37da2899SCharles.Forsyth	if(k == i)
181*37da2899SCharles.Forsyth		return i+1;
182*37da2899SCharles.Forsyth	return k;
183*37da2899SCharles.Forsyth}
184*37da2899SCharles.Forsyth
185*37da2899SCharles.Forsythkth(c: array of int, n: int, i: int, j: int, k: int)
186*37da2899SCharles.Forsyth{
187*37da2899SCharles.Forsyth	l, u: int;
188*37da2899SCharles.Forsyth
189*37da2899SCharles.Forsyth	m := nSr(n, i, j);
190*37da2899SCharles.Forsyth	if(k < 0)
191*37da2899SCharles.Forsyth		k = 0;
192*37da2899SCharles.Forsyth	if(k >= m)
193*37da2899SCharles.Forsyth		k = m-1;
194*37da2899SCharles.Forsyth	p := 0;
195*37da2899SCharles.Forsyth	for(q := 0; q < n; q++){
196*37da2899SCharles.Forsyth		if(q == 0){
197*37da2899SCharles.Forsyth			l = i;
198*37da2899SCharles.Forsyth			u = j-1;
199*37da2899SCharles.Forsyth		}
200*37da2899SCharles.Forsyth		else{
201*37da2899SCharles.Forsyth			l = 0;
202*37da2899SCharles.Forsyth			u = c[q-1];
203*37da2899SCharles.Forsyth		}
204*37da2899SCharles.Forsyth		for(x := l; x <= u; x++){
205*37da2899SCharles.Forsyth			m = nHr(x+1, n-q-1);
206*37da2899SCharles.Forsyth			p += m;
207*37da2899SCharles.Forsyth			if(p > k){
208*37da2899SCharles.Forsyth				p -= m;
209*37da2899SCharles.Forsyth				break;
210*37da2899SCharles.Forsyth			}
211*37da2899SCharles.Forsyth		}
212*37da2899SCharles.Forsyth		c[q] = x;
213*37da2899SCharles.Forsyth	}
214*37da2899SCharles.Forsyth}
215*37da2899SCharles.Forsyth
216*37da2899SCharles.Forsythpos(c: array of int, n: int): int
217*37da2899SCharles.Forsyth{
218*37da2899SCharles.Forsyth	p := 0;
219*37da2899SCharles.Forsyth	for(q := 0; q < n; q++)
220*37da2899SCharles.Forsyth		p += nSr(n-q, 0, c[q]);
221*37da2899SCharles.Forsyth	return p;
222*37da2899SCharles.Forsyth}
223*37da2899SCharles.Forsyth
224*37da2899SCharles.Forsythmin(c: array of int, n: int, p: int): big
225*37da2899SCharles.Forsyth{
226*37da2899SCharles.Forsyth	s := big(0);
227*37da2899SCharles.Forsyth	for(i := 0; i < n; i++)
228*37da2899SCharles.Forsyth		s += big(c[i])**p;
229*37da2899SCharles.Forsyth	m := s;
230*37da2899SCharles.Forsyth	for(i = n-1; i > 0; i--){
231*37da2899SCharles.Forsyth		s -= big(c[i])**p;
232*37da2899SCharles.Forsyth		s -= big(c[i-1])**p;
233*37da2899SCharles.Forsyth		c[i]--;
234*37da2899SCharles.Forsyth		c[i-1]++;
235*37da2899SCharles.Forsyth		s += big(c[i-1])**p;
236*37da2899SCharles.Forsyth		if(s < m)
237*37da2899SCharles.Forsyth			m = s;
238*37da2899SCharles.Forsyth	}
239*37da2899SCharles.Forsyth	c[0]--;
240*37da2899SCharles.Forsyth	c[n-1]++;
241*37da2899SCharles.Forsyth	# m--;
242*37da2899SCharles.Forsyth	return m;
243*37da2899SCharles.Forsyth}
244*37da2899SCharles.Forsyth
245*37da2899SCharles.Forsythhcf(a, b: int): int
246*37da2899SCharles.Forsyth{
247*37da2899SCharles.Forsyth	if(b == 0)
248*37da2899SCharles.Forsyth		return a;
249*37da2899SCharles.Forsyth	for(;;){
250*37da2899SCharles.Forsyth		if(a == 0)
251*37da2899SCharles.Forsyth			break;
252*37da2899SCharles.Forsyth		if(a < b)
253*37da2899SCharles.Forsyth			(a, b) = (b, a);
254*37da2899SCharles.Forsyth		a %= b;
255*37da2899SCharles.Forsyth		# a -= (a/b)*b;
256*37da2899SCharles.Forsyth	}
257*37da2899SCharles.Forsyth	return b;
258*37da2899SCharles.Forsyth}
259*37da2899SCharles.Forsyth
260*37da2899SCharles.Forsythgcd(l: list of array of int): int
261*37da2899SCharles.Forsyth{
262*37da2899SCharles.Forsyth	g := (hd l)[0];
263*37da2899SCharles.Forsyth	for(; l != nil; l = tl l){
264*37da2899SCharles.Forsyth		d := hd l;
265*37da2899SCharles.Forsyth		n := len d;
266*37da2899SCharles.Forsyth		for(i := 0; i < n; i++)
267*37da2899SCharles.Forsyth			g = hcf(d[i], g);
268*37da2899SCharles.Forsyth	}
269*37da2899SCharles.Forsyth	return g;
270*37da2899SCharles.Forsyth}
271*37da2899SCharles.Forsyth
272*37da2899SCharles.Forsythadddup(s: big, root: ref Dtree): int
273*37da2899SCharles.Forsyth{
274*37da2899SCharles.Forsyth	n, p, lp: ref Dtree;
275*37da2899SCharles.Forsyth
276*37da2899SCharles.Forsyth	p = root;
277*37da2899SCharles.Forsyth	while(p != nil){
278*37da2899SCharles.Forsyth		if(s == p.sum)
279*37da2899SCharles.Forsyth			return ++p.freq;
280*37da2899SCharles.Forsyth		lp = p;
281*37da2899SCharles.Forsyth		if(s < p.sum)
282*37da2899SCharles.Forsyth			p = p.left;
283*37da2899SCharles.Forsyth		else
284*37da2899SCharles.Forsyth			p = p.right;
285*37da2899SCharles.Forsyth	}
286*37da2899SCharles.Forsyth	n = ref Dtree(s, 2, nil, nil, nil);
287*37da2899SCharles.Forsyth	if(s < lp.sum)
288*37da2899SCharles.Forsyth		lp.left = n;
289*37da2899SCharles.Forsyth	else
290*37da2899SCharles.Forsyth		lp.right = n;
291*37da2899SCharles.Forsyth	return n.freq;
292*37da2899SCharles.Forsyth}
293*37da2899SCharles.Forsyth
294*37da2899SCharles.Forsythcp(c: array of int): array of int
295*37da2899SCharles.Forsyth{
296*37da2899SCharles.Forsyth	n := len c;
297*37da2899SCharles.Forsyth	m := 0;
298*37da2899SCharles.Forsyth	for(i := 0; i < n; i++)
299*37da2899SCharles.Forsyth		if(c[i] != 0)
300*37da2899SCharles.Forsyth			m++;
301*37da2899SCharles.Forsyth	nc := array[m] of int;
302*37da2899SCharles.Forsyth	nc[0: ] = c[0: m];
303*37da2899SCharles.Forsyth	return nc;
304*37da2899SCharles.Forsyth}
305*37da2899SCharles.Forsyth
306*37da2899SCharles.Forsythfinddup(s: big, c: array of int, root: ref Dtree, f: int)
307*37da2899SCharles.Forsyth{
308*37da2899SCharles.Forsyth	p: ref Dtree;
309*37da2899SCharles.Forsyth
310*37da2899SCharles.Forsyth	p = root;
311*37da2899SCharles.Forsyth	while(p != nil){
312*37da2899SCharles.Forsyth		if(s == p.sum){
313*37da2899SCharles.Forsyth			if(p.freq >= f)
314*37da2899SCharles.Forsyth				p.lst = cp(c) :: p.lst;
315*37da2899SCharles.Forsyth			return;
316*37da2899SCharles.Forsyth		}
317*37da2899SCharles.Forsyth		if(s < p.sum)
318*37da2899SCharles.Forsyth			p = p.left;
319*37da2899SCharles.Forsyth		else
320*37da2899SCharles.Forsyth			p = p.right;
321*37da2899SCharles.Forsyth	}
322*37da2899SCharles.Forsyth}
323*37da2899SCharles.Forsyth
324*37da2899SCharles.Forsythprintdup(p: ref Dtree, pow: int, ix: int)
325*37da2899SCharles.Forsyth{
326*37da2899SCharles.Forsyth	if(p == nil)
327*37da2899SCharles.Forsyth		return;
328*37da2899SCharles.Forsyth	printdup(p.left, pow, ix);
329*37da2899SCharles.Forsyth	if((l := p.lst) != nil){
330*37da2899SCharles.Forsyth		if(gcd(l) == 1){
331*37da2899SCharles.Forsyth			min1 := min2 := 16r7fffffff;
332*37da2899SCharles.Forsyth			for(; l != nil; l = tl l){
333*37da2899SCharles.Forsyth				n := len hd l;
334*37da2899SCharles.Forsyth				if(n < min1){
335*37da2899SCharles.Forsyth					min2 = min1;
336*37da2899SCharles.Forsyth					min1 = n;
337*37da2899SCharles.Forsyth				}
338*37da2899SCharles.Forsyth				else if(n < min2)
339*37da2899SCharles.Forsyth					min2 = n;
340*37da2899SCharles.Forsyth			}
341*37da2899SCharles.Forsyth			i := min1+min2-pow;
342*37da2899SCharles.Forsyth			if(i <= ix){
343*37da2899SCharles.Forsyth				sys->print("[%d, %d] %bd", i, p.freq, p.sum);
344*37da2899SCharles.Forsyth				for(l = p.lst; l != nil; l = tl l){
345*37da2899SCharles.Forsyth					d := hd l;
346*37da2899SCharles.Forsyth					n := len d;
347*37da2899SCharles.Forsyth					sys->print(" = ");
348*37da2899SCharles.Forsyth					for(j := n-1; j >= 0; j--){
349*37da2899SCharles.Forsyth						sys->print("%d**%d", d[j], pow);
350*37da2899SCharles.Forsyth						if(j > 0)
351*37da2899SCharles.Forsyth							sys->print(" + ");
352*37da2899SCharles.Forsyth					}
353*37da2899SCharles.Forsyth				}
354*37da2899SCharles.Forsyth				sys->print("\n");
355*37da2899SCharles.Forsyth				if(i < 0){
356*37da2899SCharles.Forsyth					sys->print("****************\n");
357*37da2899SCharles.Forsyth					exit;
358*37da2899SCharles.Forsyth				}
359*37da2899SCharles.Forsyth			}
360*37da2899SCharles.Forsyth		}
361*37da2899SCharles.Forsyth	}
362*37da2899SCharles.Forsyth	printdup(p.right, pow, ix);
363*37da2899SCharles.Forsyth}
364*37da2899SCharles.Forsyth
365*37da2899SCharles.Forsythaddsum(s: big, root: ref Btree, root1: ref Dtree): int
366*37da2899SCharles.Forsyth{
367*37da2899SCharles.Forsyth	n, p, lp: ref Btree;
368*37da2899SCharles.Forsyth
369*37da2899SCharles.Forsyth	p = root;
370*37da2899SCharles.Forsyth	while(p != nil){
371*37da2899SCharles.Forsyth		if(s == p.sum)
372*37da2899SCharles.Forsyth			return adddup(s, root1);
373*37da2899SCharles.Forsyth		lp = p;
374*37da2899SCharles.Forsyth		if(s < p.sum)
375*37da2899SCharles.Forsyth			p = p.left;
376*37da2899SCharles.Forsyth		else
377*37da2899SCharles.Forsyth			p = p.right;
378*37da2899SCharles.Forsyth	}
379*37da2899SCharles.Forsyth	n = ref Btree(s, nil, nil);
380*37da2899SCharles.Forsyth	if(s < lp.sum)
381*37da2899SCharles.Forsyth		lp.left = n;
382*37da2899SCharles.Forsyth	else
383*37da2899SCharles.Forsyth		lp.right = n;
384*37da2899SCharles.Forsyth	return 1;
385*37da2899SCharles.Forsyth}
386*37da2899SCharles.Forsyth
387*37da2899SCharles.Forsythoiroot(x: big, p: int): int
388*37da2899SCharles.Forsyth{
389*37da2899SCharles.Forsyth	for(i := 0; ; i++){
390*37da2899SCharles.Forsyth		n := big(i)**p;
391*37da2899SCharles.Forsyth		if(n > x)
392*37da2899SCharles.Forsyth			break;
393*37da2899SCharles.Forsyth	}
394*37da2899SCharles.Forsyth	return i-1;
395*37da2899SCharles.Forsyth}
396*37da2899SCharles.Forsyth
397*37da2899SCharles.Forsythiroot(x: big, p: int): int
398*37da2899SCharles.Forsyth{
399*37da2899SCharles.Forsyth	m: big;
400*37da2899SCharles.Forsyth
401*37da2899SCharles.Forsyth	if(x == big(0) || x == big(1))
402*37da2899SCharles.Forsyth		return int x;
403*37da2899SCharles.Forsyth	v := x;
404*37da2899SCharles.Forsyth	n := 0;
405*37da2899SCharles.Forsyth	for(i := 32; i > 0; i >>= 1){
406*37da2899SCharles.Forsyth		m = ((big(1)<<i)-big(1))<<i;
407*37da2899SCharles.Forsyth		if((v&m) != big(0)){
408*37da2899SCharles.Forsyth			n += i;
409*37da2899SCharles.Forsyth			v >>= i;
410*37da2899SCharles.Forsyth		}
411*37da2899SCharles.Forsyth	}
412*37da2899SCharles.Forsyth	a := big(1) << (n/p);
413*37da2899SCharles.Forsyth	b := a<<1;
414*37da2899SCharles.Forsyth	while(a < b){
415*37da2899SCharles.Forsyth		m = (a+b+big(1))/big(2);
416*37da2899SCharles.Forsyth		y := m**p;
417*37da2899SCharles.Forsyth		if(y > x)
418*37da2899SCharles.Forsyth			b = m-big(1);
419*37da2899SCharles.Forsyth		else if(y < x)
420*37da2899SCharles.Forsyth			a = m;
421*37da2899SCharles.Forsyth		else
422*37da2899SCharles.Forsyth			a = b = m;
423*37da2899SCharles.Forsyth	}
424*37da2899SCharles.Forsyth	if(a**p <= x && (a+big(1))**p > x)
425*37da2899SCharles.Forsyth		;
426*37da2899SCharles.Forsyth	else{
427*37da2899SCharles.Forsyth		sys->print("fatal: %bd %d -> %bd\n", x, p, a);
428*37da2899SCharles.Forsyth		exit;
429*37da2899SCharles.Forsyth	}
430*37da2899SCharles.Forsyth	return int a;
431*37da2899SCharles.Forsyth}
432*37da2899SCharles.Forsyth
433*37da2899SCharles.Forsythinitval(c: array of int, n: int, p: int, v: int): big
434*37da2899SCharles.Forsyth{
435*37da2899SCharles.Forsyth	for(i := 0; i < n; i++)
436*37da2899SCharles.Forsyth		c[i] = 0;
437*37da2899SCharles.Forsyth	c[0] = v;
438*37da2899SCharles.Forsyth	return big(v)**p;
439*37da2899SCharles.Forsyth}
440*37da2899SCharles.Forsyth
441*37da2899SCharles.Forsythnxtval(c: array of int, n: int, p: int, s: big): big
442*37da2899SCharles.Forsyth{
443*37da2899SCharles.Forsyth	for(k := n-1; k >= 0; k--){
444*37da2899SCharles.Forsyth		s -= big(c[k])**p;
445*37da2899SCharles.Forsyth		c[k]++;
446*37da2899SCharles.Forsyth		if(k == 0){
447*37da2899SCharles.Forsyth			s += big(c[k])**p;
448*37da2899SCharles.Forsyth			break;
449*37da2899SCharles.Forsyth		}
450*37da2899SCharles.Forsyth		else{
451*37da2899SCharles.Forsyth			if(c[k] <= c[k-1]){
452*37da2899SCharles.Forsyth				s += big(c[k])**p;
453*37da2899SCharles.Forsyth				break;
454*37da2899SCharles.Forsyth			}
455*37da2899SCharles.Forsyth			c[k] = 0;
456*37da2899SCharles.Forsyth		}
457*37da2899SCharles.Forsyth	}
458*37da2899SCharles.Forsyth	return s;
459*37da2899SCharles.Forsyth}
460*37da2899SCharles.Forsyth
461*37da2899SCharles.Forsythpowers(p: int, n: int, f: int, ix: int, lim0: big, lim: big, ch: chan of int, lock: ref Semaphore)
462*37da2899SCharles.Forsyth{
463*37da2899SCharles.Forsyth	root := ref Btree(big(-1), nil, nil);
464*37da2899SCharles.Forsyth	root1 := ref Dtree(big(-1), 0, nil, nil, nil);
465*37da2899SCharles.Forsyth
466*37da2899SCharles.Forsyth	min := max := lim0;
467*37da2899SCharles.Forsyth
468*37da2899SCharles.Forsyth	c := array[n] of int;
469*37da2899SCharles.Forsyth
470*37da2899SCharles.Forsyth	for(;;){
471*37da2899SCharles.Forsyth		imin := iroot((min+big(n-1))/big(n), p);
472*37da2899SCharles.Forsyth		imax := nSrmax(n, imin, MAXNODES);
473*37da2899SCharles.Forsyth		max = big(imax)**p - big(1);
474*37da2899SCharles.Forsyth		while(max <= min){	# could do better
475*37da2899SCharles.Forsyth			imax++;
476*37da2899SCharles.Forsyth			max = big(imax)**p - big(1);
477*37da2899SCharles.Forsyth		}
478*37da2899SCharles.Forsyth		if(max > lim){
479*37da2899SCharles.Forsyth			max = lim;
480*37da2899SCharles.Forsyth			imax = iroot(max, p)+1;
481*37da2899SCharles.Forsyth		}
482*37da2899SCharles.Forsyth
483*37da2899SCharles.Forsyth		if(verbose)
484*37da2899SCharles.Forsyth			sys->print("searching in %d-%d(%bd-%bd)\n", imin, imax, min, max);
485*37da2899SCharles.Forsyth
486*37da2899SCharles.Forsyth		m := mm := 0;
487*37da2899SCharles.Forsyth		maxf := 0;
488*37da2899SCharles.Forsyth		s := initval(c, n, p, imin);
489*37da2899SCharles.Forsyth		for(;;){
490*37da2899SCharles.Forsyth			mm++;
491*37da2899SCharles.Forsyth			if(s >= min && s < max){
492*37da2899SCharles.Forsyth				fr := addsum(s, root, root1);
493*37da2899SCharles.Forsyth				if(fr > maxf)
494*37da2899SCharles.Forsyth					maxf = fr;
495*37da2899SCharles.Forsyth				m++;
496*37da2899SCharles.Forsyth			}
497*37da2899SCharles.Forsyth			s = nxtval(c, n, p, s);
498*37da2899SCharles.Forsyth			if(c[0] == imax)
499*37da2899SCharles.Forsyth				break;
500*37da2899SCharles.Forsyth		}
501*37da2899SCharles.Forsyth
502*37da2899SCharles.Forsyth		root.left = root.right = nil;
503*37da2899SCharles.Forsyth
504*37da2899SCharles.Forsyth		if(maxf >= f){
505*37da2899SCharles.Forsyth			if(verbose)
506*37da2899SCharles.Forsyth				sys->print("finding duplicates\n");
507*37da2899SCharles.Forsyth
508*37da2899SCharles.Forsyth			s = initval(c, n, p, imin);
509*37da2899SCharles.Forsyth			for(;;){
510*37da2899SCharles.Forsyth				if(s >= min && s < max)
511*37da2899SCharles.Forsyth					finddup(s, c, root1, f);
512*37da2899SCharles.Forsyth				s = nxtval(c, n, p, s);
513*37da2899SCharles.Forsyth				if(c[0] == imax)
514*37da2899SCharles.Forsyth					break;
515*37da2899SCharles.Forsyth			}
516*37da2899SCharles.Forsyth
517*37da2899SCharles.Forsyth			if(lock != nil)
518*37da2899SCharles.Forsyth				lock.obtain();
519*37da2899SCharles.Forsyth			printdup(root1, p, ix);
520*37da2899SCharles.Forsyth			if(lock != nil)
521*37da2899SCharles.Forsyth				lock.release();
522*37da2899SCharles.Forsyth
523*37da2899SCharles.Forsyth			root1.left = root1.right = nil;
524*37da2899SCharles.Forsyth		}
525*37da2899SCharles.Forsyth
526*37da2899SCharles.Forsyth		if(verbose)
527*37da2899SCharles.Forsyth			sys->print("%d(%d) nodes searched\n", m, mm);
528*37da2899SCharles.Forsyth
529*37da2899SCharles.Forsyth		if(mm != nSr(n, imin, imax)){
530*37da2899SCharles.Forsyth			sys->print("**fatal**\n");
531*37da2899SCharles.Forsyth			exit;
532*37da2899SCharles.Forsyth		}
533*37da2899SCharles.Forsyth
534*37da2899SCharles.Forsyth		min = max;
535*37da2899SCharles.Forsyth		if(min >= lim)
536*37da2899SCharles.Forsyth			break;
537*37da2899SCharles.Forsyth	}
538*37da2899SCharles.Forsyth	if(ch != nil)
539*37da2899SCharles.Forsyth		ch <-= 0;
540*37da2899SCharles.Forsyth}
541*37da2899SCharles.Forsyth
542*37da2899SCharles.Forsythusage()
543*37da2899SCharles.Forsyth{
544*37da2899SCharles.Forsyth	sys->print("usage: powers -p power -n number -f frequency -i index -l minimum -m maximum -s procs -v\n");
545*37da2899SCharles.Forsyth	exit;
546*37da2899SCharles.Forsyth}
547*37da2899SCharles.Forsyth
548*37da2899SCharles.Forsythpartition(p: int, n: int, l: big, m: big, s: int): array of big
549*37da2899SCharles.Forsyth{
550*37da2899SCharles.Forsyth	a := array[s+1] of big;
551*37da2899SCharles.Forsyth	a[0] = big(iroot(l, p))**n;
552*37da2899SCharles.Forsyth	a[s] = (big(iroot(m, p))+big(1))**n;
553*37da2899SCharles.Forsyth	nn := a[s]-a[0];
554*37da2899SCharles.Forsyth	q := nn/big(s);
555*37da2899SCharles.Forsyth	r := nn-q*big(s);
556*37da2899SCharles.Forsyth	t := big(0);
557*37da2899SCharles.Forsyth	lb := a[0];
558*37da2899SCharles.Forsyth	for(i := 0; i < s; i++){
559*37da2899SCharles.Forsyth		ub := lb+q;
560*37da2899SCharles.Forsyth		t += r;
561*37da2899SCharles.Forsyth		if(t >= big(s)){
562*37da2899SCharles.Forsyth			ub++;
563*37da2899SCharles.Forsyth			t -= big(s);
564*37da2899SCharles.Forsyth		}
565*37da2899SCharles.Forsyth		a[i+1] = ub;
566*37da2899SCharles.Forsyth		lb = ub;
567*37da2899SCharles.Forsyth	}
568*37da2899SCharles.Forsyth	if(a[s] != a[0]+nn){
569*37da2899SCharles.Forsyth		sys->print("fatal: a[s]\n");
570*37da2899SCharles.Forsyth		exit;
571*37da2899SCharles.Forsyth	}
572*37da2899SCharles.Forsyth	for(i = 0; i < s; i++){
573*37da2899SCharles.Forsyth		# sys->print("%bd %bd\n", a[i], a[i]**p);
574*37da2899SCharles.Forsyth		a[i] = big(iroot(a[i], n))**p;
575*37da2899SCharles.Forsyth	}
576*37da2899SCharles.Forsyth	a[0] = l;
577*37da2899SCharles.Forsyth	a[s] = m;
578*37da2899SCharles.Forsyth	while(a[0] >= a[1]){
579*37da2899SCharles.Forsyth		a[1] = a[0];
580*37da2899SCharles.Forsyth		a = a[1: ];
581*37da2899SCharles.Forsyth		--s;
582*37da2899SCharles.Forsyth	}
583*37da2899SCharles.Forsyth	while(a[s] <= a[s-1]){
584*37da2899SCharles.Forsyth		a[s-1] = a[s];
585*37da2899SCharles.Forsyth		a = a[0: s];
586*37da2899SCharles.Forsyth		--s;
587*37da2899SCharles.Forsyth	}
588*37da2899SCharles.Forsyth	return a;
589*37da2899SCharles.Forsyth}
590*37da2899SCharles.Forsyth
591*37da2899SCharles.Forsythinit(nil: ref Draw->Context, args: list of string)
592*37da2899SCharles.Forsyth{
593*37da2899SCharles.Forsyth	sys = load Sys Sys->PATH;
594*37da2899SCharles.Forsyth	arg := load Arg Arg->PATH;
595*37da2899SCharles.Forsyth	lockm = load Lock Lock->PATH;
596*37da2899SCharles.Forsyth
597*37da2899SCharles.Forsyth	lockm->init();
598*37da2899SCharles.Forsyth	lock := Semaphore.new();
599*37da2899SCharles.Forsyth
600*37da2899SCharles.Forsyth	p := n := f := 2;
601*37da2899SCharles.Forsyth	ix := 1<<30;
602*37da2899SCharles.Forsyth	l := m := big(0);
603*37da2899SCharles.Forsyth	s := 1;
604*37da2899SCharles.Forsyth
605*37da2899SCharles.Forsyth	arg->init(args);
606*37da2899SCharles.Forsyth	while((c := arg->opt()) != 0){
607*37da2899SCharles.Forsyth		case c {
608*37da2899SCharles.Forsyth			'p' =>
609*37da2899SCharles.Forsyth				p = int arg->arg();
610*37da2899SCharles.Forsyth			'n' =>
611*37da2899SCharles.Forsyth				n = int arg->arg();
612*37da2899SCharles.Forsyth			'f' =>
613*37da2899SCharles.Forsyth				f = int arg->arg();
614*37da2899SCharles.Forsyth			'i' =>
615*37da2899SCharles.Forsyth				ix = int arg->arg();
616*37da2899SCharles.Forsyth			'l' =>
617*37da2899SCharles.Forsyth				l = big(arg->arg());
618*37da2899SCharles.Forsyth			'm' =>
619*37da2899SCharles.Forsyth				m = big(arg->arg())+big(1);
620*37da2899SCharles.Forsyth			's' =>
621*37da2899SCharles.Forsyth				s = int arg->arg();
622*37da2899SCharles.Forsyth			'v' =>
623*37da2899SCharles.Forsyth				verbose = 1;
624*37da2899SCharles.Forsyth			* =>
625*37da2899SCharles.Forsyth				usage();
626*37da2899SCharles.Forsyth		}
627*37da2899SCharles.Forsyth	}
628*37da2899SCharles.Forsyth	if(arg->argv() != nil)
629*37da2899SCharles.Forsyth		usage();
630*37da2899SCharles.Forsyth
631*37da2899SCharles.Forsyth	if(p < 2){
632*37da2899SCharles.Forsyth		p = 2;
633*37da2899SCharles.Forsyth		sys->print("setting p = %d\n", p);
634*37da2899SCharles.Forsyth	}
635*37da2899SCharles.Forsyth	if(n < 2){
636*37da2899SCharles.Forsyth		n = 2;
637*37da2899SCharles.Forsyth		sys->print("setting n = %d\n", n);
638*37da2899SCharles.Forsyth	}
639*37da2899SCharles.Forsyth	if(f < 2){
640*37da2899SCharles.Forsyth		f = 2;
641*37da2899SCharles.Forsyth		sys->print("setting f = %d\n", f);
642*37da2899SCharles.Forsyth	}
643*37da2899SCharles.Forsyth	if(l < big(0)){
644*37da2899SCharles.Forsyth		l = big(0);
645*37da2899SCharles.Forsyth		sys->print("setting l = %bd\n", l);
646*37da2899SCharles.Forsyth	}
647*37da2899SCharles.Forsyth	if(m <= big(0)){
648*37da2899SCharles.Forsyth		m = big((1<<13)+1);
649*37da2899SCharles.Forsyth		sys->print("setting m = %bd\n", m-big(1));
650*37da2899SCharles.Forsyth	}
651*37da2899SCharles.Forsyth	if(l >= m)
652*37da2899SCharles.Forsyth		exit;
653*37da2899SCharles.Forsyth
654*37da2899SCharles.Forsyth	if(s <= 1)
655*37da2899SCharles.Forsyth		powers(p, n, f, ix, l, m, nil, nil);
656*37da2899SCharles.Forsyth	else{
657*37da2899SCharles.Forsyth		nproc := 0;
658*37da2899SCharles.Forsyth		ch := chan of int;
659*37da2899SCharles.Forsyth		a := partition(p, n, l, m, s);
660*37da2899SCharles.Forsyth		lb := a[0];
661*37da2899SCharles.Forsyth		for(i := 0; i < s; i++){
662*37da2899SCharles.Forsyth			ub := a[i+1];
663*37da2899SCharles.Forsyth			if(lb < ub){
664*37da2899SCharles.Forsyth				nproc++;
665*37da2899SCharles.Forsyth				spawn powers(p, n, f, ix, lb, ub, ch, lock);
666*37da2899SCharles.Forsyth			}
667*37da2899SCharles.Forsyth			lb = ub;
668*37da2899SCharles.Forsyth		}
669*37da2899SCharles.Forsyth		for( ; nproc != 0; nproc--)
670*37da2899SCharles.Forsyth			<- ch;
671*37da2899SCharles.Forsyth	}
672*37da2899SCharles.Forsyth}
673