1/***
2  @groupdef stdlib.arithmetic Arithmetic Builtins
3
4  These builtins implement arithmetic operations.
5*/
6
7/** @group stdlib.arithmetic Return \a x + \a y */
8function     int:   '+'(    int: x,     int: y);
9/** @group stdlib.arithmetic Return \a x + \a y */
10function var int:   '+'(var int: x,  var int: y);
11/** @group stdlib.arithmetic Return \a x + \a y */
12function     float: '+'(    float: x,    float: y);
13/** @group stdlib.arithmetic Return \a x + \a y */
14function var float: '+'(var float: x,var float: y);
15/** @group stdlib.arithmetic Optional addition. Return sum of \a x and \a y, with absent replaced by 0. */
16function var int: '+'(var opt int: x, var opt int: y) ::promise_total =
17  if occurs(x) then deopt(x) else 0 endif + if occurs(y) then deopt(y) else 0 endif;
18/** @group stdlib.arithmetic Optional addition. Return sum of \a x and \a y, with absent replaced by 0. */
19function int: '+'(opt int: x, opt int: y) ::promise_total =
20  if occurs(x) then deopt(x) else 0 endif + if occurs(y) then deopt(y) else 0 endif;
21/** @group stdlib.arithmetic Optional addition. Return sum of \a x and \a y, with absent replaced by 0. */
22function var float: '+'(var opt float: x, var opt float: y) ::promise_total =
23  if occurs(x) then deopt(x) else 0 endif + if occurs(y) then deopt(y) else 0 endif;
24/** @group stdlib.arithmetic Optional addition. Return sum of \a x and \a y, with absent replaced by 0. */
25function float: '+'(opt float: x, opt float: y) ::promise_total =
26  if occurs(x) then deopt(x) else 0 endif + if occurs(y) then deopt(y) else 0 endif;
27
28/** @group stdlib.arithmetic Return \a x - \a y */
29function     int:   '-'(    int: x,     int: y);
30/** @group stdlib.arithmetic Return \a x - \a y */
31function var int:   '-'(var int: x,  var int: y);
32/** @group stdlib.arithmetic Return \a x - \a y */
33function     float: '-'(    float: x,    float: y);
34/** @group stdlib.arithmetic Return \a x - \a y */
35function var float: '-'(var float: x,var float: y);
36/** @group stdlib.arithmetic Optional subtraction. Return absent if \a x is absent, \a x if \a y is absent,
37  difference of \a x and \a y if both are present. */
38function var opt int: '-'(var opt int: x, var opt int: y) ::promise_total =
39  if absent(x) then <> elseif absent(y) then deopt(x) else deopt(x)-deopt(y) endif;
40function var int: '-'(var int: x, var opt int: y) ::promise_total =
41  if absent(y) then x else x-deopt(y) endif;
42/** @group stdlib.arithmetic Optional subtraction. Return absent if \a x is absent, \a x if \a y is absent,
43  difference of \a x and \a y if both are present. */
44function var opt float: '-'(var opt float: x, var opt float: y) ::promise_total =
45  if absent(x) then <> elseif absent(y) then deopt(x) else deopt(x)-deopt(y) endif;
46function var float: '-'(var float: x, var opt float: y) ::promise_total =
47  if absent(y) then x else x-deopt(y) endif;
48/** @group stdlib.arithmetic Optional subtraction. Return absent if \a x is absent, \a x if \a y is absent,
49  difference of \a x and \a y if both are present. */
50function opt int: '-'(opt int: x, opt int: y) ::promise_total =
51  if absent(x) then <> elseif absent(y) then deopt(x) else deopt(x)-deopt(y) endif;
52function int: '-'(int: x, opt int: y) ::promise_total =
53  if absent(y) then x else x-deopt(y) endif;
54/** @group stdlib.arithmetic Optional subtraction. Return absent if \a x is absent, \a x if \a y is absent,
55  difference of \a x and \a y if both are present. */
56function opt float: '-'(opt float: x, opt float: y) ::promise_total =
57  if absent(x) then <> elseif absent(y) then deopt(x) else deopt(x)-deopt(y) endif;
58function float: '-'(float: x, opt float: y) ::promise_total =
59  if absent(y) then x else x-deopt(y) endif;
60
61
62/** @group stdlib.arithmetic Return \a x * \a y */
63function     int:   '*'(    int: x,     int: y);
64/** @group stdlib.arithmetic Return \a x * \a y */
65function var int:   '*'(var int: x,  var int: y);
66/** @group stdlib.arithmetic Optional multiplication. Return product of \a x and \a y, with absent replaced by 1. */
67function var int: '*'(var opt int: x, var opt int: y) ::promise_total =
68  if occurs(x) then deopt(x) else 1 endif * if occurs(y) then deopt(y) else 1 endif;
69/** @group stdlib.arithmetic Optional multiplication. Return product of \a x and \a y, with absent replaced by 1. */
70function int: '*'(opt int: x, opt int: y) ::promise_total =
71  if occurs(x) then deopt(x) else 1 endif * if occurs(y) then deopt(y) else 1 endif;
72/** @group stdlib.arithmetic Optional multiplication. Return product of \a x and \a y, with absent replaced by 1. */
73function var float: '*'(var opt float: x, var opt float: y) ::promise_total =
74  if occurs(x) then deopt(x) else 1 endif * if occurs(y) then deopt(y) else 1 endif;
75/** @group stdlib.arithmetic Optional multiplication. Return product of \a x and \a y, with absent replaced by 1. */
76function float: '*'(opt float: x, opt float: y) ::promise_total =
77  if occurs(x) then deopt(x) else 1 endif * if occurs(y) then deopt(y) else 1 endif;
78
79
80/** @group stdlib.arithmetic Return \(\a x ^ {\a y}\) */
81function     int:   '^'(    int: x,     int: y);
82/** @group stdlib.arithmetic Return \(\a x ^ {\a y}\) */
83function var int:   '^'(var int: x,  var int: y);
84/** @group stdlib.arithmetic Return \a x * \a y */
85function     float: '*'(    float: x,    float: y);
86/** @group stdlib.arithmetic Return \a x * \a y */
87function var float: '*'(var float: x,var float: y);
88/** @group stdlib.arithmetic Return \(\a x ^ {\a y}\) */
89function     float: '^'(    float: x,    float: y);
90/** @group stdlib.arithmetic Return \(\a x ^ {\a y}\) */
91function var float: '^'(var float: x,var float: y);
92/** @group stdlib.arithmetic Return negative \a x */
93function     int:   '-'(    int: x);
94/** @group stdlib.arithmetic Return negative \a x */
95function var int:   '-'(var int: x);
96/** @group stdlib.arithmetic Return negative \a x */
97function     float: '-'(    float: x);
98/** @group stdlib.arithmetic Return negative \a x */
99function var float: '-'(var float: x);
100
101/** @group stdlib.arithmetic Return result of integer division \a x / \a y */
102function     int: 'div'(int: x,int: y);
103
104/** @group stdlib.arithmetic Return result of integer division \a x / \a y */
105function var int: 'div'(var int: x,var int: y) =
106  if mzn_in_root_context(y) then div_t(x,y)
107  elseif not (0 in dom(y)) then div_t(x,y)
108  else let { constraint y != 0 } in div_mt(x,y) endif;
109
110/** @group stdlib.arithmetic Optional division. Return absent if \a x is absent, \a x if \a y is absent,
111  \a x divided by \a y if both are present. */
112function var opt int: 'div'(var opt int: x, var opt int: y) =
113  if absent(x) then <> elseif absent(y) then deopt(x) else deopt(x) div deopt(y) endif;
114
115function var int: 'div'(var int: x, var opt int: y) =
116  if absent(y) then x else x div deopt(y) endif;
117
118/** @group stdlib.arithmetic Optional division. Return absent if \a x is absent, \a x if \a y is absent,
119  \a x divided by \a y if both are present. */
120function opt int: 'div'(opt int: x, opt int: y) =
121  if absent(x) then <> elseif absent(y) then deopt(x) else deopt(x) div deopt(y) endif;
122
123function int: 'div'(int: x, opt int: y) =
124  if absent(y) then x else x div deopt(y) endif;
125/** @group stdlib.arithmetic Return remainder of integer division \a x % \a y */
126function     int: 'mod'(int: x,int: y);
127
128/** @group stdlib.arithmetic Return remainder of integer division \a x % \a y */
129function var int: 'mod'(var int: x,var int: y) =
130  if mzn_in_root_context(y) then mod_t(x,y)
131  elseif not (0 in dom(y)) then mod_t(x,y)
132  else let { constraint y != 0 } in mod_mt(x,y) endif;
133
134/** @group stdlib.arithmetic Optional modulo. Return absent if \a x or \a y is absent,
135  \a x modulo \a y if both are present. */
136function var opt int: 'mod'(var opt int: x, var opt int: y) =
137  if occurs(x) /\ occurs(y) then deopt(x) mod deopt(y) else <> endif;
138
139/** @group stdlib.arithmetic Optional modulo. Return absent if \a x or \a y is absent,
140  \a x modulo \a y if both are present. */
141function opt int: 'mod'(opt int: x, opt int: y) =
142  if occurs(x) /\ occurs(y) then deopt(x) mod deopt(y) else <> endif;
143
144
145/** @group stdlib.arithmetic Return result of floating point division \a x / \a y */
146function     float: '/'(    float: x,    float: y);
147/** @group stdlib.arithmetic Return result of floating point division \a x / \a y */
148function var float: '/'(var float: x,var float: y) =
149  if mzn_in_root_context(y) then fldiv_t(x,y)
150  elseif lb(y) > 0.0 \/ ub(y) < 0.0 then fldiv_t(x,y)
151  else let { constraint y != 0.0 } in fldiv_mt(x,y) endif;
152/** @group stdlib.arithmetic Optional division. Return absent if \a x is absent, \a x if \a y is absent,
153  \a x divided by \a y if both are present. */
154function var opt float: '/'(var opt float: x, var opt float: y) =
155  if absent(x) then <> elseif absent(y) then deopt(x) else deopt(x) / deopt(y) endif;
156function var float: '/'(var float: x, var opt float: y) =
157  if absent(y) then x else x / deopt(y) endif;
158/** @group stdlib.arithmetic Optional division. Return absent if \a x is absent, \a x if \a y is absent,
159  \a x divided by \a y if both are present. */
160function opt float: '/'(opt float: x, opt float: y) =
161  if absent(x) then <> elseif absent(y) then deopt(x) else deopt(x) / deopt(y) endif;
162function float: '/'(float: x, opt float: y) =
163  if absent(y) then x else x / deopt(y) endif;
164
165
166/** @group stdlib.arithmetic Return number of true elments in array \a x */
167function int:  count(array[$T] of bool: x) = sum([bool2int(y) | y in array1d(x)]);
168/** @group stdlib.arithmetic Return number of true elments in array \a x */
169function var int:  count(array[$T] of var bool: x) = sum([bool2int(y) | y in array1d(x)]);
170
171/** @group stdlib.arithmetic Return sum of elements in array \a x */
172function     int:   sum(array[$T] of     int: x);
173/** @group stdlib.arithmetic Return sum of elements in array \a x */
174function var int:   sum(array[$T] of var int: x);
175/** @group stdlib.arithmetic Return sum of elements in array \a x */
176function     float: sum(array[$T] of     float: x);
177/** @group stdlib.arithmetic Return sum of elements in array \a x */
178function var float: sum(array[$T] of var float: x);
179/** @group stdlib.arithmetic Return sum of non-absent elements of \a x. */
180function var int: sum(array[int] of var opt int: x) =
181  sum (i in index_set(x)) (let { var int: dx = deopt(x[i]) } in if occurs(x[i]) then dx else 0 endif);
182/** @group stdlib.arithmetic Return sum of non-absent elements of \a x. */
183function int: sum(array[int] of opt int: x) =
184  sum (i in index_set(x)) (if occurs(x[i]) then deopt(x[i]) else 0 endif);
185/** @group stdlib.arithmetic Return sum of non-absent elements of \a x. */
186function var float: sum(array[int] of var opt float: x) =
187  sum (i in index_set(x)) (let { var float: dx = deopt(x[i]) } in if occurs(x[i]) then dx else 0 endif);
188/** @group stdlib.arithmetic Return sum of non-absent elements of \a x. */
189function float: sum(array[int] of opt float: x) =
190  sum (i in index_set(x)) (if occurs(x[i]) then deopt(x[i]) else 0 endif);
191
192
193/** @group stdlib.arithmetic Return product of elements in array \a x */
194function     int:   product(array[$T] of     int: x);
195/** @group stdlib.arithmetic Return product of elements in array \a x */
196function var int:   product(array[$T] of var int: x) =
197  product_rec(array1d(x));
198/** @group stdlib.arithmetic Return product of non-absent elements of \a x. */
199function var int: product(array[int] of var opt int: x) =
200  product (i in index_set(x)) (let { var int: dx = deopt(x[i]) } in if occurs(x[i]) then dx else 1 endif);
201/** @group stdlib.arithmetic Return product of non-absent elements of \a x. */
202function int: product(array[int] of opt int: x) =
203  product (i in index_set(x)) (if occurs(x[i]) then deopt(x[i]) else 1 endif);
204/** @group stdlib.arithmetic Return product of elements in array \a x */
205function     float: product(array[$T] of     float: x);
206/** @group stdlib.arithmetic Return product of elements in array \a x */
207function var float: product(array[$T] of var float: x) =
208  product_rec(array1d(x));
209/** @group stdlib.arithmetic Return product of non-absent elements of \a x. */
210function var float: product(array[int] of var opt float: x) =
211  product (i in index_set(x)) (let { var float: dx = deopt(x[i]) } in if occurs(x[i]) then dx else 1 endif);
212/** @group stdlib.arithmetic Return product of non-absent elements of \a x. */
213function float: product(array[int] of opt float: x) =
214  product (i in index_set(x)) (if occurs(x[i]) then deopt(x[i]) else 1 endif);
215
216
217/** @group stdlib.arithmetic Return minimum of \a x and \a y */
218function     $T: min(    $T: x,     $T: y);
219/** @group stdlib.arithmetic Return minimum of elements in array \a x */
220function     $T: min(array[$U] of     par $T: x);
221/** @group stdlib.arithmetic Return minimum of elements in \a x that are not absent. */
222function var int: min(array[int] of var opt int: x) =
223    let {
224        var lb_array(x)..ub_array(x): xmax = max(xi in x)(deopt(xi));
225        % Array cannot be empty, otherwise min is undefined
226        constraint exists(xi in x)(occurs(xi));
227    } in min([if occurs(xi) then deopt(xi) else xmax endif | xi in x]);
228/** @group stdlib.arithmetic Return minimum of elements in \a x that are not absent. */
229function var float: min(array[int] of var opt float: x) =
230    let {
231        var lb_array(x)..ub_array(x): xmax = max(xi in x)(deopt(xi));
232        % Array cannot be empty, otherwise min is undefined
233        constraint exists(xi in x)(occurs(xi));
234    } in min([if occurs(xi) then deopt(xi) else xmax endif | xi in x]);
235
236/** @group stdlib.arithmetic Return maximum of \a x and \a y */
237function     $T: max(    $T: x,     $T: y);
238/** @group stdlib.arithmetic Return maximum of elements in array \a x */
239function     $T: max(array[$U] of     $T: x);
240/** @group stdlib.arithmetic Return maximum of elements in \a x that are not absent, or
241absent if all elements in \a x are absent. */
242function var int: max(array[int] of var opt int: x) =
243    let {
244        var lb_array(x)..ub_array(x): xmin = min(xi in x)(deopt(xi));
245        constraint exists (xi in x) (occurs(xi));
246    } in max([if occurs(xi) then deopt(xi) else xmin endif | xi in x]);
247/** @group stdlib.arithmetic Return minimum of elements in set \a x */
248function $$E: min(set of $$E: x);
249/** @group stdlib.arithmetic Return maximum of elements in set \a x */
250function $$E: max(set of $$E: x);
251
252/** @group stdlib.arithmetic Return maximum of \a x and \a y */
253function var int: max(var int: x, var int: y) :: promise_total =
254  let { var max(lb(x),lb(y))..max(ub(x),ub(y)): m ::is_defined_var;
255        constraint int_max(x,y,m) ::defines_var(m);
256  } in m;
257
258/** @group stdlib.arithmetic Return maximum of elements in array \a x */
259function var int: max(array[$U] of var int: x) =
260  let {
261    array[int] of var int: xx = array1d(x);
262    constraint length(x) >= 1;
263  } in max_t(xx);
264/** @group stdlib.arithmetic Return maximum of elements in \a x that are not absent. */
265function var float: max(array[int] of var opt float: x) =
266    let {
267        var lb_array(x)..ub_array(x): xmin = min(xi in x)(deopt(xi));
268        constraint exists (xi in x) (occurs(xi));
269    } in max([if occurs(xi) then deopt(xi) else xmin endif | xi in x]);
270
271/** @group stdlib.arithmetic Return minimum of \a x and \a y */
272function var int: min(var int: x, var int: y) :: promise_total =
273  let { var min(lb(x),lb(y))..min(ub(x),ub(y)): m ::is_defined_var;
274        constraint int_min(x,y,m) ::defines_var(m);
275  } in m;
276
277/** @group stdlib.arithmetic Return minimum of elements in array \a x */
278function var int: min(array[$U] of var int: x) =
279  let {
280    array[int] of var int: xx = array1d(x);
281    constraint length(x) >= 1;
282  } in min_t(xx);
283
284% Floating point min and max
285% TODO: add bounds reasoning
286
287/** @group stdlib.arithmetic Return maximum of \a x and \a y */
288function var float: max(var float: x, var float: y) :: promise_total =
289  if has_bounds(x) /\ has_bounds(y) then
290  let { var max(lb(x),lb(y))..max(ub(x),ub(y)): m ::is_defined_var;
291        constraint float_max(x,y,m) ::defines_var(m);
292  } in m
293  else
294  let { var float: m ::is_defined_var;
295        constraint float_max(x,y,m) ::defines_var(m);
296  } in m
297  endif;
298
299/** @group stdlib.arithmetic Return maximum of elements in array \a x */
300function var float: max(array[$U] of var float: x) =
301  let {
302    array[int] of var float: xx = array1d(x);
303    constraint length(x) >= 1;
304  } in max_t(xx);
305
306/** @group stdlib.arithmetic Return minimum of \a x and \a y */
307function var float: min(var float: x, var float: y) :: promise_total =
308  if has_bounds(x) /\ has_bounds(y) then
309  let { var min(lb(x),lb(y))..min(ub(x),ub(y)): m ::is_defined_var;
310        constraint float_min(x,y,m) ::defines_var(m);
311  } in m
312  else
313  let { var float: m ::is_defined_var;
314        constraint float_min(x,y,m) ::defines_var(m);
315  } in m
316  endif;
317
318/** @group stdlib.arithmetic Return minimum of elements in array \a x */
319function var float: min(array[$U] of var float: x) =
320  let {
321    array[int] of var float: xx = array1d(x);
322    constraint length(x) >= 1;
323  } in min_t(xx);
324
325
326/** @group stdlib.arithmetic
327    Returns the index of the minimum value in the array \a x.
328    When breaking ties the least index is returned.
329*/
330function $$E: arg_min(array[$$E] of bool: x);
331/** @group stdlib.arithmetic
332    Returns the index of the minimum value in the array \a x.
333    When breaking ties the least index is returned.
334*/
335function $$E: arg_min(array[$$E] of int: x);
336/** @group stdlib.arithmetic
337    Returns the index of the minimum value in the array \a x.
338    When breaking ties the least index is returned.
339*/
340function $$E: arg_min(array[$$E] of float: x);
341/** @group stdlib.arithmetic
342    Returns the index of the maximum value in the array \a x.
343    When breaking ties the least index is returned.
344*/
345function $$E: arg_max(array[$$E] of bool: x);
346/** @group stdlib.arithmetic
347    Returns the index of the maximum value in the array \a x.
348    When breaking ties the least index is returned.
349*/
350function $$E: arg_max(array[$$E] of int: x);
351/** @group stdlib.arithmetic
352    Returns the index of the maximum value in the array \a x.
353    When breaking ties the least index is returned.
354*/
355function $$E: arg_max(array[$$E] of float: x);
356
357/** @group stdlib.arithmetic Return absolute value of \a x */
358function int: abs(int: x);
359
360/** @group stdlib.arithmetic Return absolute value of \a x */
361function var int: abs(var int: x) :: promise_total =
362  if has_bounds(x) /\ lb(x) >= 0 then x
363  elseif has_bounds(x) /\ ub(x) <= 0 then -x else
364  let { var 0..max(-lb(x),ub(x)): m ::is_defined_var;
365        constraint int_abs(x,m) ::defines_var(m);
366  } in m
367  endif;
368
369/** @group stdlib.arithmetic Return absolute value of \a x */
370function float: abs(float: x);
371/** @group stdlib.arithmetic Return absolute value of \a x */
372function var float: abs(var float: x) :: promise_total =
373  if has_bounds(x) then
374    if lb(x) >= 0.0 then x
375    elseif ub(x) <= 0.0 then -x else
376    let { var 0.0..max(-lb(x),ub(x)): m ::is_defined_var;
377          constraint float_abs(x,m) ::defines_var(m);
378    } in m
379    endif
380  else
381    let { var float: m ::is_defined_var;
382          constraint m >= 0.0;
383          constraint float_abs(x,m) ::defines_var(m);
384    } in m
385  endif;
386
387/** @group stdlib.arithmetic Return \(\sqrt{\a x}\) */
388function float: sqrt(float: x);
389/** @group stdlib.arithmetic Return \(\sqrt{\a x}\) */
390function var float: sqrt(var float: x) =
391  let {
392    constraint x >= 0.0;
393  } in sqrt_t(x);
394
395function var float: sqrt_t(var float: x) ::promise_total =
396  let {
397    var float: r;
398    var float: xx;
399    constraint x < 0.0 -> xx = 1.0;
400    constraint x < 0.0 \/ xx = x;
401    constraint float_sqrt(xx,r);
402  } in r;
403
404/** @group stdlib.arithmetic Return \(\a x ^ {\a y}\) */
405function int: pow(int: x, int: y);
406
407/** @group stdlib.arithmetic Return \(\a x ^ {\a y}\) */
408function var int: pow(var int: x, var int: y) =
409  let {
410    int: yy = if is_fixed(y) then fix(y) else -1 endif;
411  } in
412  if yy = 0 then 1
413  elseif yy = 1 then x
414  elseif 0..1==dom(x) then x
415  elseif -1..1==dom(x) /\ is_fixed(y) /\ 1 == fix(y) mod 2 then x else
416  let { var int: r ::is_defined_var;
417        constraint if is_fixed(y) then int_pow_fixed(x,fix(y),r) ::defines_var(r) else int_pow(x,y,r) ::defines_var(r) endif;
418  } in r
419  endif;
420
421
422/** @group stdlib.arithmetic Return \(\a x ^ {\a y}\) */
423function float: pow(float: x, float: y);
424
425/** @group stdlib.arithmetic Return \(\a x ^ {\a y}\) */
426function var float: pow(var float: x, var float: y) =
427  let {
428    float: yy = if is_fixed(y) then fix(y) else -1.0 endif
429  } in
430  if yy = 0.0 then 1.0
431  elseif yy = 1.0 then x else
432  let { var float: r ::is_defined_var;
433        constraint float_pow(x,y,r) ::defines_var(r);
434  } in r
435  endif;
436
437/***
438  @groupdef stdlib.explog Exponential and logarithmic builtins
439
440  These builtins implement exponential and logarithmic functions.
441*/
442
443/** @group stdlib.explog Return \(e ^ {\a x}\) */
444function float: exp(float: x);
445/** @group stdlib.explog Return \(e ^ {\a x}\) */
446function var float: exp(var float: x) ::promise_total =
447  let {
448    var float: r ::is_defined_var;
449    constraint float_exp(x,r) ::defines_var(r);
450  } in r;
451
452/** @group stdlib.explog Return \(\ln \a x\) */
453function float: ln(float: x);
454/** @group stdlib.explog Return \(\ln \a x\) */
455function var float: ln(var float: x) ::promise_total =
456  let {
457    var float: r ::is_defined_var;
458    constraint float_ln(x,r) ::defines_var(r);
459  } in r;
460
461/** @group stdlib.explog Return \(\log_{10} \a x\) */
462function float: log10(float: x);
463/** @group stdlib.explog Return \(\log_{10} \a x\) */
464function var float: log10(var float: x) ::promise_total =
465  let {
466    var float: r ::is_defined_var;
467    constraint float_log10(x,r) ::defines_var(r);
468  } in r;
469
470/** @group stdlib.explog Return \(\log_{2} \a x\) */
471function float: log2(float: x);
472/** @group stdlib.explog Return \(\log_{2} \a x\) */
473function var float: log2(var float: x) ::promise_total =
474  let {
475    var float: r ::is_defined_var;
476    constraint float_log2(x,r) ::defines_var(r);
477  } in r;
478
479/** @group stdlib.explog Return \(\log_{\a x} \a y\) */
480function float: log(float: x, float: y);
481
482/***
483  @groupdef stdlib.trigonometric Trigonometric functions
484
485  These builtins implement the standard trigonometric functions.
486*/
487
488/** @group stdlib.trigonometric Return \(\sin \a x\) */
489function float: sin(float: x);
490/** @group stdlib.trigonometric Return \(\sin \a x\) */
491function var float: sin(var float: x) ::promise_total =
492  let {
493    var -1.0..1.0: r ::is_defined_var;
494    constraint float_sin(x,r) ::defines_var(r);
495  } in r;
496
497/** @group stdlib.trigonometric Return \(\cos \a x\) */
498function float: cos(float: x);
499/** @group stdlib.trigonometric Return \(\cos \a x\) */
500function var float: cos(var float: x) ::promise_total =
501  let {
502    var -1.0..1.0: r ::is_defined_var;
503    constraint float_cos(x,r) ::defines_var(r);
504  } in r;
505
506/** @group stdlib.trigonometric Return \(\tan \a x\) */
507function float: tan(float: x);
508/** @group stdlib.trigonometric Return \(\tan \a x\) */
509function var float: tan(var float: x) ::promise_total =
510  let {
511    var float: r ::is_defined_var;
512    constraint float_tan(x,r) ::defines_var(r);
513  } in r;
514
515/** @group stdlib.trigonometric Return \(\mbox{asin}\ \a x\) */
516function float: asin(float: x);
517/** @group stdlib.trigonometric Return \(\mbox{asin}\ \a x\) */
518function var float: asin(var float: x) ::promise_total =
519  let {
520    var float: r ::is_defined_var;
521    constraint float_asin(x,r) ::defines_var(r);
522  } in r;
523
524/** @group stdlib.trigonometric Return \(\mbox{acos}\ \a x\) */
525function float: acos(float: x);
526/** @group stdlib.trigonometric Return \(\mbox{acos}\ \a x\) */
527function var float: acos(var float: x) ::promise_total =
528  let {
529    var float: r ::is_defined_var;
530    constraint float_acos(x,r) ::defines_var(r);
531  } in r;
532
533/** @group stdlib.trigonometric Return \(\mbox{atan}\ \a x\) */
534function float: atan(float: x);
535/** @group stdlib.trigonometric Return \(\mbox{atan}\ \a x\) */
536function var float: atan(var float: x) ::promise_total =
537  let {
538    var float: r ::is_defined_var;
539    constraint float_atan(x,r) ::defines_var(r);
540  } in r;
541
542/** @group stdlib.trigonometric Return \(\sinh \a x\) */
543function float: sinh(float: x);
544/** @group stdlib.trigonometric Return \(\sinh \a x\) */
545function var float: sinh(var float: x) ::promise_total =
546  let {
547    var float: r ::is_defined_var;
548    constraint float_sinh(x,r) ::defines_var(r);
549  } in r;
550
551/** @group stdlib.trigonometric Return \(\cosh \a x\) */
552function float: cosh(float: x);
553/** @group stdlib.trigonometric Return \(\cosh \a x\) */
554function var float: cosh(var float: x) ::promise_total =
555  let {
556    var float: r ::is_defined_var;
557    constraint float_cosh(x,r) ::defines_var(r);
558  } in r;
559
560/** @group stdlib.trigonometric Return \(\tanh \a x\) */
561function float: tanh(float: x);
562/** @group stdlib.trigonometric Return \(\tanh \a x\) */
563function var float: tanh(var float: x) ::promise_total =
564  let {
565    var float: r ::is_defined_var;
566    constraint float_tanh(x,r) ::defines_var(r);
567  } in r;
568
569/** @group stdlib.trigonometric Return \(\mbox{asinh}\ \a x\) */
570function float: asinh(float: x);
571/** @group stdlib.trigonometric Return \(\mbox{asinh}\ \a x\) */
572function var float: asinh(var float: x) ::promise_total =
573  let {
574    var float: r ::is_defined_var;
575    constraint float_asinh(x,r) ::defines_var(r);
576  } in r;
577
578/** @group stdlib.trigonometric Return \(\mbox{acosh}\ \a x\) */
579function float: acosh(float: x);
580/** @group stdlib.trigonometric Return \(\mbox{acosh}\ \a x\) */
581function var float: acosh(var float: x) ::promise_total =
582  let {
583    var float: r ::is_defined_var;
584    constraint float_acosh(x,r) ::defines_var(r);
585  } in r;
586
587/** @group stdlib.trigonometric Return \(\mbox{atanh}\ \a x\) */
588function float: atanh(float: x);
589/** @group stdlib.trigonometric Return \(\mbox{atanh}\ \a x\) */
590function var float: atanh(var float: x) ::promise_total =
591  let {
592    var float: r ::is_defined_var;
593    constraint float_atanh(x,r) ::defines_var(r);
594  } in r;
595
596