1d5ac70f0Sopenharmony_ci/*
2d5ac70f0Sopenharmony_ci *  Interval functions
3d5ac70f0Sopenharmony_ci *  Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
4d5ac70f0Sopenharmony_ci *
5d5ac70f0Sopenharmony_ci *
6d5ac70f0Sopenharmony_ci *   This library is free software; you can redistribute it and/or modify
7d5ac70f0Sopenharmony_ci *   it under the terms of the GNU Lesser General Public License as
8d5ac70f0Sopenharmony_ci *   published by the Free Software Foundation; either version 2.1 of
9d5ac70f0Sopenharmony_ci *   the License, or (at your option) any later version.
10d5ac70f0Sopenharmony_ci *
11d5ac70f0Sopenharmony_ci *   This program is distributed in the hope that it will be useful,
12d5ac70f0Sopenharmony_ci *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13d5ac70f0Sopenharmony_ci *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14d5ac70f0Sopenharmony_ci *   GNU Lesser General Public License for more details.
15d5ac70f0Sopenharmony_ci *
16d5ac70f0Sopenharmony_ci *   You should have received a copy of the GNU Lesser General Public
17d5ac70f0Sopenharmony_ci *   License along with this library; if not, write to the Free Software
18d5ac70f0Sopenharmony_ci *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19d5ac70f0Sopenharmony_ci *
20d5ac70f0Sopenharmony_ci */
21d5ac70f0Sopenharmony_ci
22d5ac70f0Sopenharmony_ci#define SND_INTERVAL_C
23d5ac70f0Sopenharmony_ci#define SND_INTERVAL_INLINE
24d5ac70f0Sopenharmony_ci
25d5ac70f0Sopenharmony_ci#include "pcm_local.h"
26d5ac70f0Sopenharmony_ci#include <sys/types.h>
27d5ac70f0Sopenharmony_ci#include <limits.h>
28d5ac70f0Sopenharmony_ci
29d5ac70f0Sopenharmony_cistatic inline void div64_32(uint64_t *n, uint32_t d, uint32_t *rem)
30d5ac70f0Sopenharmony_ci{
31d5ac70f0Sopenharmony_ci	*rem = *n % d;
32d5ac70f0Sopenharmony_ci	*n /= d;
33d5ac70f0Sopenharmony_ci}
34d5ac70f0Sopenharmony_ci
35d5ac70f0Sopenharmony_cistatic inline unsigned int div32(unsigned int a, unsigned int b,
36d5ac70f0Sopenharmony_ci				 unsigned int *r)
37d5ac70f0Sopenharmony_ci{
38d5ac70f0Sopenharmony_ci	if (b == 0) {
39d5ac70f0Sopenharmony_ci		*r = 0;
40d5ac70f0Sopenharmony_ci		return UINT_MAX;
41d5ac70f0Sopenharmony_ci	}
42d5ac70f0Sopenharmony_ci	*r = a % b;
43d5ac70f0Sopenharmony_ci	return a / b;
44d5ac70f0Sopenharmony_ci}
45d5ac70f0Sopenharmony_ci
46d5ac70f0Sopenharmony_cistatic inline unsigned int div_down(unsigned int a, unsigned int b)
47d5ac70f0Sopenharmony_ci{
48d5ac70f0Sopenharmony_ci	if (b == 0)
49d5ac70f0Sopenharmony_ci		return UINT_MAX;
50d5ac70f0Sopenharmony_ci	return a / b;
51d5ac70f0Sopenharmony_ci}
52d5ac70f0Sopenharmony_ci
53d5ac70f0Sopenharmony_cistatic inline unsigned int div_up(unsigned int a, unsigned int b)
54d5ac70f0Sopenharmony_ci{
55d5ac70f0Sopenharmony_ci	unsigned int r;
56d5ac70f0Sopenharmony_ci	unsigned int q;
57d5ac70f0Sopenharmony_ci	if (b == 0)
58d5ac70f0Sopenharmony_ci		return UINT_MAX;
59d5ac70f0Sopenharmony_ci	q = div32(a, b, &r);
60d5ac70f0Sopenharmony_ci	if (r)
61d5ac70f0Sopenharmony_ci		++q;
62d5ac70f0Sopenharmony_ci	return q;
63d5ac70f0Sopenharmony_ci}
64d5ac70f0Sopenharmony_ci
65d5ac70f0Sopenharmony_cistatic inline unsigned int mul(unsigned int a, unsigned int b)
66d5ac70f0Sopenharmony_ci{
67d5ac70f0Sopenharmony_ci	if (a == 0)
68d5ac70f0Sopenharmony_ci		return 0;
69d5ac70f0Sopenharmony_ci	if (div_down(UINT_MAX, a) < b)
70d5ac70f0Sopenharmony_ci		return UINT_MAX;
71d5ac70f0Sopenharmony_ci	return a * b;
72d5ac70f0Sopenharmony_ci}
73d5ac70f0Sopenharmony_ci
74d5ac70f0Sopenharmony_cistatic inline unsigned int add(unsigned int a, unsigned int b)
75d5ac70f0Sopenharmony_ci{
76d5ac70f0Sopenharmony_ci	if (a >= UINT_MAX - b)
77d5ac70f0Sopenharmony_ci		return UINT_MAX;
78d5ac70f0Sopenharmony_ci	return a + b;
79d5ac70f0Sopenharmony_ci}
80d5ac70f0Sopenharmony_ci
81d5ac70f0Sopenharmony_cistatic inline unsigned int sub(unsigned int a, unsigned int b)
82d5ac70f0Sopenharmony_ci{
83d5ac70f0Sopenharmony_ci	if (a > b)
84d5ac70f0Sopenharmony_ci		return a - b;
85d5ac70f0Sopenharmony_ci	return 0;
86d5ac70f0Sopenharmony_ci}
87d5ac70f0Sopenharmony_ci
88d5ac70f0Sopenharmony_cistatic inline unsigned int muldiv32(unsigned int a, unsigned int b,
89d5ac70f0Sopenharmony_ci				    unsigned int c, unsigned int *r)
90d5ac70f0Sopenharmony_ci{
91d5ac70f0Sopenharmony_ci	uint64_t n = (uint64_t) a * b;
92d5ac70f0Sopenharmony_ci	if (c == 0) {
93d5ac70f0Sopenharmony_ci		assert(n > 0);
94d5ac70f0Sopenharmony_ci		*r = 0;
95d5ac70f0Sopenharmony_ci		return UINT_MAX;
96d5ac70f0Sopenharmony_ci	}
97d5ac70f0Sopenharmony_ci	div64_32(&n, c, r);
98d5ac70f0Sopenharmony_ci	if (n >= UINT_MAX) {
99d5ac70f0Sopenharmony_ci		*r = 0;
100d5ac70f0Sopenharmony_ci		return UINT_MAX;
101d5ac70f0Sopenharmony_ci	}
102d5ac70f0Sopenharmony_ci	return n;
103d5ac70f0Sopenharmony_ci}
104d5ac70f0Sopenharmony_ci
105d5ac70f0Sopenharmony_ciint snd_interval_refine_min(snd_interval_t *i, unsigned int min, int openmin)
106d5ac70f0Sopenharmony_ci{
107d5ac70f0Sopenharmony_ci	int changed = 0;
108d5ac70f0Sopenharmony_ci	if (snd_interval_empty(i))
109d5ac70f0Sopenharmony_ci		return -ENOENT;
110d5ac70f0Sopenharmony_ci	if (i->min < min) {
111d5ac70f0Sopenharmony_ci		i->min = min;
112d5ac70f0Sopenharmony_ci		i->openmin = openmin;
113d5ac70f0Sopenharmony_ci		changed = 1;
114d5ac70f0Sopenharmony_ci	} else if (i->min == min && !i->openmin && openmin) {
115d5ac70f0Sopenharmony_ci		i->openmin = 1;
116d5ac70f0Sopenharmony_ci		changed = 1;
117d5ac70f0Sopenharmony_ci	}
118d5ac70f0Sopenharmony_ci	if (i->integer) {
119d5ac70f0Sopenharmony_ci		if (i->openmin) {
120d5ac70f0Sopenharmony_ci			i->min++;
121d5ac70f0Sopenharmony_ci			i->openmin = 0;
122d5ac70f0Sopenharmony_ci		}
123d5ac70f0Sopenharmony_ci	}
124d5ac70f0Sopenharmony_ci	if (snd_interval_checkempty(i)) {
125d5ac70f0Sopenharmony_ci		snd_interval_none(i);
126d5ac70f0Sopenharmony_ci		return -EINVAL;
127d5ac70f0Sopenharmony_ci	}
128d5ac70f0Sopenharmony_ci	return changed;
129d5ac70f0Sopenharmony_ci}
130d5ac70f0Sopenharmony_ci
131d5ac70f0Sopenharmony_ciint snd_interval_refine_max(snd_interval_t *i, unsigned int max, int openmax)
132d5ac70f0Sopenharmony_ci{
133d5ac70f0Sopenharmony_ci	int changed = 0;
134d5ac70f0Sopenharmony_ci	if (snd_interval_empty(i))
135d5ac70f0Sopenharmony_ci		return -ENOENT;
136d5ac70f0Sopenharmony_ci	if (i->max > max) {
137d5ac70f0Sopenharmony_ci		i->max = max;
138d5ac70f0Sopenharmony_ci		i->openmax = openmax;
139d5ac70f0Sopenharmony_ci		changed = 1;
140d5ac70f0Sopenharmony_ci	} else if (i->max == max && !i->openmax && openmax) {
141d5ac70f0Sopenharmony_ci		i->openmax = 1;
142d5ac70f0Sopenharmony_ci		changed = 1;
143d5ac70f0Sopenharmony_ci	}
144d5ac70f0Sopenharmony_ci	if (i->integer) {
145d5ac70f0Sopenharmony_ci		if (i->openmax) {
146d5ac70f0Sopenharmony_ci			i->max--;
147d5ac70f0Sopenharmony_ci			i->openmax = 0;
148d5ac70f0Sopenharmony_ci		}
149d5ac70f0Sopenharmony_ci	}
150d5ac70f0Sopenharmony_ci	if (snd_interval_checkempty(i)) {
151d5ac70f0Sopenharmony_ci		snd_interval_none(i);
152d5ac70f0Sopenharmony_ci		return -EINVAL;
153d5ac70f0Sopenharmony_ci	}
154d5ac70f0Sopenharmony_ci	return changed;
155d5ac70f0Sopenharmony_ci}
156d5ac70f0Sopenharmony_ci
157d5ac70f0Sopenharmony_ci/* r <- v */
158d5ac70f0Sopenharmony_ciint snd_interval_refine(snd_interval_t *i, const snd_interval_t *v)
159d5ac70f0Sopenharmony_ci{
160d5ac70f0Sopenharmony_ci	int changed = 0;
161d5ac70f0Sopenharmony_ci	if (snd_interval_empty(i))
162d5ac70f0Sopenharmony_ci		return -ENOENT;
163d5ac70f0Sopenharmony_ci	if (i->min < v->min) {
164d5ac70f0Sopenharmony_ci		i->min = v->min;
165d5ac70f0Sopenharmony_ci		i->openmin = v->openmin;
166d5ac70f0Sopenharmony_ci		changed = 1;
167d5ac70f0Sopenharmony_ci	} else if (i->min == v->min && !i->openmin && v->openmin) {
168d5ac70f0Sopenharmony_ci		i->openmin = 1;
169d5ac70f0Sopenharmony_ci		changed = 1;
170d5ac70f0Sopenharmony_ci	}
171d5ac70f0Sopenharmony_ci	if (i->max > v->max) {
172d5ac70f0Sopenharmony_ci		i->max = v->max;
173d5ac70f0Sopenharmony_ci		i->openmax = v->openmax;
174d5ac70f0Sopenharmony_ci		changed = 1;
175d5ac70f0Sopenharmony_ci	} else if (i->max == v->max && !i->openmax && v->openmax) {
176d5ac70f0Sopenharmony_ci		i->openmax = 1;
177d5ac70f0Sopenharmony_ci		changed = 1;
178d5ac70f0Sopenharmony_ci	}
179d5ac70f0Sopenharmony_ci	if (!i->integer && v->integer) {
180d5ac70f0Sopenharmony_ci		i->integer = 1;
181d5ac70f0Sopenharmony_ci		changed = 1;
182d5ac70f0Sopenharmony_ci	}
183d5ac70f0Sopenharmony_ci	if (i->integer) {
184d5ac70f0Sopenharmony_ci		if (i->openmin) {
185d5ac70f0Sopenharmony_ci			i->min++;
186d5ac70f0Sopenharmony_ci			i->openmin = 0;
187d5ac70f0Sopenharmony_ci		}
188d5ac70f0Sopenharmony_ci		if (i->openmax) {
189d5ac70f0Sopenharmony_ci			i->max--;
190d5ac70f0Sopenharmony_ci			i->openmax = 0;
191d5ac70f0Sopenharmony_ci		}
192d5ac70f0Sopenharmony_ci	} else if (!i->openmin && !i->openmax && i->min == i->max)
193d5ac70f0Sopenharmony_ci		i->integer = 1;
194d5ac70f0Sopenharmony_ci	if (snd_interval_checkempty(i)) {
195d5ac70f0Sopenharmony_ci		snd_interval_none(i);
196d5ac70f0Sopenharmony_ci		return -EINVAL;
197d5ac70f0Sopenharmony_ci	}
198d5ac70f0Sopenharmony_ci	return changed;
199d5ac70f0Sopenharmony_ci}
200d5ac70f0Sopenharmony_ci
201d5ac70f0Sopenharmony_ciint snd_interval_refine_first(snd_interval_t *i)
202d5ac70f0Sopenharmony_ci{
203d5ac70f0Sopenharmony_ci	const unsigned int last_max = i->max;
204d5ac70f0Sopenharmony_ci
205d5ac70f0Sopenharmony_ci	if (snd_interval_empty(i))
206d5ac70f0Sopenharmony_ci		return -ENOENT;
207d5ac70f0Sopenharmony_ci	if (snd_interval_single(i))
208d5ac70f0Sopenharmony_ci		return 0;
209d5ac70f0Sopenharmony_ci	i->max = i->min;
210d5ac70f0Sopenharmony_ci	if (i->openmin)
211d5ac70f0Sopenharmony_ci		i->max++;
212d5ac70f0Sopenharmony_ci	/* only exclude max value if also excluded before refine */
213d5ac70f0Sopenharmony_ci	i->openmax = (i->openmax && i->max >= last_max);
214d5ac70f0Sopenharmony_ci	return 1;
215d5ac70f0Sopenharmony_ci}
216d5ac70f0Sopenharmony_ci
217d5ac70f0Sopenharmony_ciint snd_interval_refine_last(snd_interval_t *i)
218d5ac70f0Sopenharmony_ci{
219d5ac70f0Sopenharmony_ci	const unsigned int last_min = i->min;
220d5ac70f0Sopenharmony_ci
221d5ac70f0Sopenharmony_ci	if (snd_interval_empty(i))
222d5ac70f0Sopenharmony_ci		return -ENOENT;
223d5ac70f0Sopenharmony_ci	if (snd_interval_single(i))
224d5ac70f0Sopenharmony_ci		return 0;
225d5ac70f0Sopenharmony_ci	i->min = i->max;
226d5ac70f0Sopenharmony_ci	if (i->openmax)
227d5ac70f0Sopenharmony_ci		i->min--;
228d5ac70f0Sopenharmony_ci	/* only exclude min value if also excluded before refine */
229d5ac70f0Sopenharmony_ci	i->openmin = (i->openmin && i->min <= last_min);
230d5ac70f0Sopenharmony_ci	return 1;
231d5ac70f0Sopenharmony_ci}
232d5ac70f0Sopenharmony_ci
233d5ac70f0Sopenharmony_ciint snd_interval_refine_set(snd_interval_t *i, unsigned int val)
234d5ac70f0Sopenharmony_ci{
235d5ac70f0Sopenharmony_ci	snd_interval_t t;
236d5ac70f0Sopenharmony_ci	t.empty = 0;
237d5ac70f0Sopenharmony_ci	t.min = t.max = val;
238d5ac70f0Sopenharmony_ci	t.openmin = t.openmax = 0;
239d5ac70f0Sopenharmony_ci	t.integer = 1;
240d5ac70f0Sopenharmony_ci	return snd_interval_refine(i, &t);
241d5ac70f0Sopenharmony_ci}
242d5ac70f0Sopenharmony_ci
243d5ac70f0Sopenharmony_civoid snd_interval_add(const snd_interval_t *a, const snd_interval_t *b, snd_interval_t *c)
244d5ac70f0Sopenharmony_ci{
245d5ac70f0Sopenharmony_ci	if (a->empty || b->empty) {
246d5ac70f0Sopenharmony_ci		snd_interval_none(c);
247d5ac70f0Sopenharmony_ci		return;
248d5ac70f0Sopenharmony_ci	}
249d5ac70f0Sopenharmony_ci	c->empty = 0;
250d5ac70f0Sopenharmony_ci	c->min = add(a->min, b->min);
251d5ac70f0Sopenharmony_ci	c->openmin = (a->openmin || b->openmin);
252d5ac70f0Sopenharmony_ci	c->max = add(a->max,  b->max);
253d5ac70f0Sopenharmony_ci	c->openmax = (a->openmax || b->openmax);
254d5ac70f0Sopenharmony_ci	c->integer = (a->integer && b->integer);
255d5ac70f0Sopenharmony_ci}
256d5ac70f0Sopenharmony_ci
257d5ac70f0Sopenharmony_civoid snd_interval_sub(const snd_interval_t *a, const snd_interval_t *b, snd_interval_t *c)
258d5ac70f0Sopenharmony_ci{
259d5ac70f0Sopenharmony_ci	if (a->empty || b->empty) {
260d5ac70f0Sopenharmony_ci		snd_interval_none(c);
261d5ac70f0Sopenharmony_ci		return;
262d5ac70f0Sopenharmony_ci	}
263d5ac70f0Sopenharmony_ci	c->empty = 0;
264d5ac70f0Sopenharmony_ci	c->min = sub(a->min, b->max);
265d5ac70f0Sopenharmony_ci	c->openmin = (a->openmin || b->openmax);
266d5ac70f0Sopenharmony_ci	c->max = add(a->max,  b->min);
267d5ac70f0Sopenharmony_ci	c->openmax = (a->openmax || b->openmin);
268d5ac70f0Sopenharmony_ci	c->integer = (a->integer && b->integer);
269d5ac70f0Sopenharmony_ci}
270d5ac70f0Sopenharmony_ci
271d5ac70f0Sopenharmony_civoid snd_interval_mul(const snd_interval_t *a, const snd_interval_t *b, snd_interval_t *c)
272d5ac70f0Sopenharmony_ci{
273d5ac70f0Sopenharmony_ci	if (a->empty || b->empty) {
274d5ac70f0Sopenharmony_ci		snd_interval_none(c);
275d5ac70f0Sopenharmony_ci		return;
276d5ac70f0Sopenharmony_ci	}
277d5ac70f0Sopenharmony_ci	c->empty = 0;
278d5ac70f0Sopenharmony_ci	c->min = mul(a->min, b->min);
279d5ac70f0Sopenharmony_ci	c->openmin = (a->openmin || b->openmin);
280d5ac70f0Sopenharmony_ci	c->max = mul(a->max,  b->max);
281d5ac70f0Sopenharmony_ci	c->openmax = (a->openmax || b->openmax);
282d5ac70f0Sopenharmony_ci	c->integer = (a->integer && b->integer);
283d5ac70f0Sopenharmony_ci}
284d5ac70f0Sopenharmony_ci
285d5ac70f0Sopenharmony_civoid snd_interval_div(const snd_interval_t *a, const snd_interval_t *b, snd_interval_t *c)
286d5ac70f0Sopenharmony_ci{
287d5ac70f0Sopenharmony_ci	unsigned int r;
288d5ac70f0Sopenharmony_ci	if (a->empty || b->empty) {
289d5ac70f0Sopenharmony_ci		snd_interval_none(c);
290d5ac70f0Sopenharmony_ci		return;
291d5ac70f0Sopenharmony_ci	}
292d5ac70f0Sopenharmony_ci	c->empty = 0;
293d5ac70f0Sopenharmony_ci	c->min = div32(a->min, b->max, &r);
294d5ac70f0Sopenharmony_ci	c->openmin = (r || a->openmin || b->openmax);
295d5ac70f0Sopenharmony_ci	if (b->min > 0) {
296d5ac70f0Sopenharmony_ci		c->max = div32(a->max, b->min, &r);
297d5ac70f0Sopenharmony_ci		if (r) {
298d5ac70f0Sopenharmony_ci			c->max++;
299d5ac70f0Sopenharmony_ci			c->openmax = 1;
300d5ac70f0Sopenharmony_ci		} else
301d5ac70f0Sopenharmony_ci			c->openmax = (a->openmax || b->openmin);
302d5ac70f0Sopenharmony_ci	} else {
303d5ac70f0Sopenharmony_ci		c->max = UINT_MAX;
304d5ac70f0Sopenharmony_ci		c->openmax = 0;
305d5ac70f0Sopenharmony_ci	}
306d5ac70f0Sopenharmony_ci	c->integer = 0;
307d5ac70f0Sopenharmony_ci}
308d5ac70f0Sopenharmony_ci
309d5ac70f0Sopenharmony_ci/* a * b / c */
310d5ac70f0Sopenharmony_civoid snd_interval_muldiv(const snd_interval_t *a, const snd_interval_t *b,
311d5ac70f0Sopenharmony_ci		     const snd_interval_t *c, snd_interval_t *d)
312d5ac70f0Sopenharmony_ci{
313d5ac70f0Sopenharmony_ci	unsigned int r;
314d5ac70f0Sopenharmony_ci	if (a->empty || b->empty || c->empty) {
315d5ac70f0Sopenharmony_ci		snd_interval_none(d);
316d5ac70f0Sopenharmony_ci		return;
317d5ac70f0Sopenharmony_ci	}
318d5ac70f0Sopenharmony_ci	d->empty = 0;
319d5ac70f0Sopenharmony_ci	d->min = muldiv32(a->min, b->min, c->max, &r);
320d5ac70f0Sopenharmony_ci	d->openmin = (r || a->openmin || b->openmin || c->openmax);
321d5ac70f0Sopenharmony_ci	d->max = muldiv32(a->max, b->max, c->min, &r);
322d5ac70f0Sopenharmony_ci	if (r) {
323d5ac70f0Sopenharmony_ci		d->max++;
324d5ac70f0Sopenharmony_ci		d->openmax = 1;
325d5ac70f0Sopenharmony_ci	} else
326d5ac70f0Sopenharmony_ci		d->openmax = (a->openmax || b->openmax || c->openmin);
327d5ac70f0Sopenharmony_ci	d->integer = 0;
328d5ac70f0Sopenharmony_ci}
329d5ac70f0Sopenharmony_ci
330d5ac70f0Sopenharmony_ci/* a * b / k */
331d5ac70f0Sopenharmony_civoid snd_interval_muldivk(const snd_interval_t *a, const snd_interval_t *b,
332d5ac70f0Sopenharmony_ci		      unsigned int k, snd_interval_t *c)
333d5ac70f0Sopenharmony_ci{
334d5ac70f0Sopenharmony_ci	unsigned int r;
335d5ac70f0Sopenharmony_ci	if (a->empty || b->empty) {
336d5ac70f0Sopenharmony_ci		snd_interval_none(c);
337d5ac70f0Sopenharmony_ci		return;
338d5ac70f0Sopenharmony_ci	}
339d5ac70f0Sopenharmony_ci	c->empty = 0;
340d5ac70f0Sopenharmony_ci	c->min = muldiv32(a->min, b->min, k, &r);
341d5ac70f0Sopenharmony_ci	c->openmin = (r || a->openmin || b->openmin);
342d5ac70f0Sopenharmony_ci	c->max = muldiv32(a->max, b->max, k, &r);
343d5ac70f0Sopenharmony_ci	if (r) {
344d5ac70f0Sopenharmony_ci		c->max++;
345d5ac70f0Sopenharmony_ci		c->openmax = 1;
346d5ac70f0Sopenharmony_ci	} else
347d5ac70f0Sopenharmony_ci		c->openmax = (a->openmax || b->openmax);
348d5ac70f0Sopenharmony_ci	c->integer = 0;
349d5ac70f0Sopenharmony_ci}
350d5ac70f0Sopenharmony_ci
351d5ac70f0Sopenharmony_ci/* a * k / b */
352d5ac70f0Sopenharmony_civoid snd_interval_mulkdiv(const snd_interval_t *a, unsigned int k,
353d5ac70f0Sopenharmony_ci		      const snd_interval_t *b, snd_interval_t *c)
354d5ac70f0Sopenharmony_ci{
355d5ac70f0Sopenharmony_ci	unsigned int r;
356d5ac70f0Sopenharmony_ci	if (a->empty || b->empty) {
357d5ac70f0Sopenharmony_ci		snd_interval_none(c);
358d5ac70f0Sopenharmony_ci		return;
359d5ac70f0Sopenharmony_ci	}
360d5ac70f0Sopenharmony_ci	c->empty = 0;
361d5ac70f0Sopenharmony_ci	c->min = muldiv32(a->min, k, b->max, &r);
362d5ac70f0Sopenharmony_ci	c->openmin = (r || a->openmin || b->openmax);
363d5ac70f0Sopenharmony_ci	if (b->min > 0) {
364d5ac70f0Sopenharmony_ci		c->max = muldiv32(a->max, k, b->min, &r);
365d5ac70f0Sopenharmony_ci		if (r) {
366d5ac70f0Sopenharmony_ci			c->max++;
367d5ac70f0Sopenharmony_ci			c->openmax = 1;
368d5ac70f0Sopenharmony_ci		} else
369d5ac70f0Sopenharmony_ci			c->openmax = (a->openmax || b->openmin);
370d5ac70f0Sopenharmony_ci	} else {
371d5ac70f0Sopenharmony_ci		c->max = UINT_MAX;
372d5ac70f0Sopenharmony_ci		c->openmax = 0;
373d5ac70f0Sopenharmony_ci	}
374d5ac70f0Sopenharmony_ci	c->integer = 0;
375d5ac70f0Sopenharmony_ci}
376d5ac70f0Sopenharmony_ci
377d5ac70f0Sopenharmony_civoid snd_interval_print(const snd_interval_t *i, snd_output_t *out)
378d5ac70f0Sopenharmony_ci{
379d5ac70f0Sopenharmony_ci	if (snd_interval_empty(i))
380d5ac70f0Sopenharmony_ci		snd_output_printf(out, "NONE");
381d5ac70f0Sopenharmony_ci	else if (i->min == 0 && i->openmin == 0 &&
382d5ac70f0Sopenharmony_ci		 i->max == UINT_MAX && i->openmax == 0)
383d5ac70f0Sopenharmony_ci		snd_output_printf(out, "ALL");
384d5ac70f0Sopenharmony_ci	else if (snd_interval_single(i) && i->integer)
385d5ac70f0Sopenharmony_ci		snd_output_printf(out, "%u", snd_interval_value(i));
386d5ac70f0Sopenharmony_ci	else
387d5ac70f0Sopenharmony_ci		snd_output_printf(out, "%c%u %u%c",
388d5ac70f0Sopenharmony_ci				i->openmin ? '(' : '[',
389d5ac70f0Sopenharmony_ci				i->min, i->max,
390d5ac70f0Sopenharmony_ci				i->openmax ? ')' : ']');
391d5ac70f0Sopenharmony_ci}
392d5ac70f0Sopenharmony_ci
393d5ac70f0Sopenharmony_ci#if 0
394d5ac70f0Sopenharmony_cistatic void boundary_abs(int a, int adir, int *b, int *bdir)
395d5ac70f0Sopenharmony_ci{
396d5ac70f0Sopenharmony_ci	if (a < 0 || (a == 0 && adir < 0)) {
397d5ac70f0Sopenharmony_ci		*b = -a;
398d5ac70f0Sopenharmony_ci		*bdir = -adir;
399d5ac70f0Sopenharmony_ci	} else {
400d5ac70f0Sopenharmony_ci		*b = a;
401d5ac70f0Sopenharmony_ci		*bdir = adir;
402d5ac70f0Sopenharmony_ci	}
403d5ac70f0Sopenharmony_ci}
404d5ac70f0Sopenharmony_ci#endif
405d5ac70f0Sopenharmony_ci
406d5ac70f0Sopenharmony_civoid boundary_sub(int a, int adir, int b, int bdir, int *c, int *cdir)
407d5ac70f0Sopenharmony_ci{
408d5ac70f0Sopenharmony_ci	adir = adir < 0 ? -1 : (adir > 0 ? 1 : 0);
409d5ac70f0Sopenharmony_ci	bdir = bdir < 0 ? -1 : (bdir > 0 ? 1 : 0);
410d5ac70f0Sopenharmony_ci	*c = a - b;
411d5ac70f0Sopenharmony_ci	*cdir = adir - bdir;
412d5ac70f0Sopenharmony_ci	if (*cdir == -2) {
413d5ac70f0Sopenharmony_ci		assert(*c > INT_MIN);
414d5ac70f0Sopenharmony_ci		(*c)--;
415d5ac70f0Sopenharmony_ci	} else if (*cdir == 2) {
416d5ac70f0Sopenharmony_ci		assert(*c < INT_MAX);
417d5ac70f0Sopenharmony_ci		(*c)++;
418d5ac70f0Sopenharmony_ci	}
419d5ac70f0Sopenharmony_ci}
420d5ac70f0Sopenharmony_ci
421d5ac70f0Sopenharmony_ciint boundary_lt(unsigned int a, int adir, unsigned int b, int bdir)
422d5ac70f0Sopenharmony_ci{
423d5ac70f0Sopenharmony_ci	assert(a > 0 || adir >= 0);
424d5ac70f0Sopenharmony_ci	assert(b > 0 || bdir >= 0);
425d5ac70f0Sopenharmony_ci	if (adir < 0) {
426d5ac70f0Sopenharmony_ci		a--;
427d5ac70f0Sopenharmony_ci		adir = 1;
428d5ac70f0Sopenharmony_ci	} else if (adir > 0)
429d5ac70f0Sopenharmony_ci		adir = 1;
430d5ac70f0Sopenharmony_ci	if (bdir < 0) {
431d5ac70f0Sopenharmony_ci		b--;
432d5ac70f0Sopenharmony_ci		bdir = 1;
433d5ac70f0Sopenharmony_ci	} else if (bdir > 0)
434d5ac70f0Sopenharmony_ci		bdir = 1;
435d5ac70f0Sopenharmony_ci	return a < b || (a == b && adir < bdir);
436d5ac70f0Sopenharmony_ci}
437d5ac70f0Sopenharmony_ci
438d5ac70f0Sopenharmony_ci/* Return 1 if min is nearer to best than max */
439d5ac70f0Sopenharmony_ciint boundary_nearer(int min, int mindir, int best, int bestdir, int max, int maxdir)
440d5ac70f0Sopenharmony_ci{
441d5ac70f0Sopenharmony_ci	int dmin, dmindir;
442d5ac70f0Sopenharmony_ci	int dmax, dmaxdir;
443d5ac70f0Sopenharmony_ci	boundary_sub(best, bestdir, min, mindir, &dmin, &dmindir);
444d5ac70f0Sopenharmony_ci	boundary_sub(max, maxdir, best, bestdir, &dmax, &dmaxdir);
445d5ac70f0Sopenharmony_ci	return boundary_lt(dmin, dmindir, dmax, dmaxdir);
446d5ac70f0Sopenharmony_ci}
447d5ac70f0Sopenharmony_ci
448