* modulo() and pmodulo() support integers & hypermatrices
[scilab.git] / scilab / modules / elementary_functions / macros / pmodulo.sci
1 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
2 // Copyright (C) INRIA
3 // Copyright (C) DIGITEO - 2011 - Allan CORNET
4 // Copyright (C) 2012 - Scilab Enterprises - Adeline CARNIS
5 // Copyright (C) 2013 - Samuel GOUGEON :  : bugs 12373 & 13002
6 //
7 // This file must be used under the terms of the CeCILL.
8 // This source file is licensed as described in the file COPYING, which
9 // you should have received as part of this distribution.  The terms
10 // are also available at
11 // http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
12
13 function i = pmodulo(n, m)
14     //i=pmodulo(n,m) the "positive modulo" of m et n.
15     //i=n-floor(n./m).*m
16
17     [lhs, rhs] = argn(0);
18     if rhs <> 2 then
19         msg = _("%s: Wrong number of input argument(s): %d expected.\n")
20         error(msprintf(msg, "pmodulo", 2))
21     end
22
23     mt = type(m($))
24     nt = type(n($))
25
26     // -----------------------  Checking arguments --------------------------
27
28     if or(type(n)==[15 16]) | and(nt <> [1 2 8]) | (nt==1 & ~isreal(n)) then
29         msg = _("%s: Wrong type for input argument #%d: Reals, encoded integers or polynomials expected.\n")
30         error(msprintf(msg, "pmodulo", 1))
31     end
32
33     if or(type(m)==[15 16]) | and(mt <> [1 2 8]) | (mt==1 & ~isreal(m)) then
34         msg = _("%s: Wrong type for input argument #%d: Reals, encoded integers or polynomials expected.\n")
35         error(msprintf(msg, "pmodulo", 2))
36     end
37
38     if (nt==8 | mt==8)  & nt~=mt
39         msg = _("%s: Incompatible input arguments: Same types expected.\n")
40         error(msprintf(msg, "pmodulo"))
41     end
42
43     // --------------------------  Processing ----------------------------
44
45     if  nt==2 then
46         [i,q] = pdiv(n, m)
47     else
48         ms = size(m)
49         ns = size(n)
50         m = m(:)
51         n = n(:)
52         m = abs(m)  // else returns i<0 for m<0 : http://bugzilla.scilab.org/12373
53         if length(n)>1 & length(m)>1 & or(ns<>ms) then
54             msg = _("%s: Wrong size for input arguments: Same size expected.\n")
55             error(msprintf(msg, "pmodulo"))
56         end
57         i = n - floor(n ./ m) .* m
58         k = find(i<0)           // this may occur for encoded integers
59         if length(m)>1 then
60             i(k) = i(k) + m(k)
61             i = iconvert(i, inttype(n))
62             i = matrix(i, ms)
63         else
64             i(k) = i(k) + m
65             i = iconvert(i, inttype(n))
66             i = matrix(i, ns)
67         end
68     end
69
70 endfunction