Merge remote-tracking branch 'origin/master' into windows
[scilab.git] / scilab / modules / interpolation / sci_gateway / cpp / sci_interp3d.cpp
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2011 - DIGITEO - Cedric DELAMARRE
4 *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13 *
14 */
15 /*--------------------------------------------------------------------------*/
16 #include "interpolation_gw.hxx"
17 #include "function.hxx"
18 #include "double.hxx"
19 #include "string.hxx"
20 #include "tlist.hxx"
21
22 extern "C"
23 {
24 #include "sci_malloc.h"
25 #include "localization.h"
26 #include "Scierror.h"
27 #include "interpolation_functions.h"
28 }
29 /*--------------------------------------------------------------------------*/
30
31 types::Function::ReturnValue sci_interp3d(types::typed_list &in, int _iRetCount, types::typed_list &out)
32 {
33     // input
34     types::Double* pDblXYZ[3]       = {NULL, NULL, NULL};
35     types::TList* pTList            = NULL;
36     types::Double* pDblX            = NULL;
37     types::Double* pDblY            = NULL;
38     types::Double* pDblZ            = NULL;
39     types::Double* pDblOrder        = NULL;
40     types::Double* pDblCoef         = NULL;
41     types::Double* pDblXyzminmax    = NULL;
42
43     // output
44     types::Double* pDblFp   = NULL;
45     types::Double* pDblFpdx = NULL;
46     types::Double* pDblFpdy = NULL;
47     types::Double* pDblFpdz = NULL;
48
49     int iType = 0;
50     int order[3];
51     int sizeOfXp;
52
53     // *** check the minimal number of input args. ***
54     if ((in.size() < 4) || (5 < in.size()))
55     {
56         Scierror(77, _("%s: Wrong number of input argument(s): %d expected.\n"), "interp3d", 4);
57         return types::Function::Error;
58     }
59
60     // *** check number of output args according the methode. ***
61     if (_iRetCount > 4)
62     {
63         Scierror(78, _("%s: Wrong number of output argument(s): %d to %d expected.\n"), "interp3d", 1, 4);
64         return types::Function::Error;
65     }
66
67     // *** check type of input args and get it. ***
68     // xp yp zp
69     for (int i = 0; i < 3; i++)
70     {
71         if (in[i]->isDouble() == false)
72         {
73             Scierror(999, _("%s: Wrong type for input argument #%d : A matrix expected.\n"), "interp3d", i + 1);
74             return types::Function::Error;
75         }
76
77         pDblXYZ[i] = in[i]->getAs<types::Double>();
78
79         if (pDblXYZ[0]->getRows() != pDblXYZ[i]->getRows() || pDblXYZ[0]->getCols() != pDblXYZ[i]->getCols())
80         {
81             Scierror(999, _("%s: Wrong size for input argument #%d : Same size as argument %d expected.\n"), "interp3d", i + 1, 1);
82             return types::Function::Error;
83         }
84
85         if (pDblXYZ[i]->isComplex())
86         {
87             Scierror(999, _("%s: Wrong type for argument #%d: Real matrix expected.\n"), "interp3d", i + 1);
88             return types::Function::Error;
89         }
90     }
91
92     sizeOfXp = pDblXYZ[0]->getSize();
93
94     if (in[3]->isTList() == false)
95     {
96         Scierror(999, _("%s: Wrong type for input argument #%d : A tlist of type %s expected.\n"), "interp3d", 4, "tensbs3d");
97     }
98
99     pTList = in[3]->getAs<types::TList>();
100
101     if (pTList->getTypeStr() != "tensbs3d")
102     {
103         Scierror(999, _("%s: Wrong type for input argument #%d: A %s tlist expected.\n"), "interp3d", 4, "tensbs3d");
104         return types::Function::Error;
105     }
106
107     pDblX = pTList->getField("tx")->getAs<types::Double>();
108     pDblY = pTList->getField("ty")->getAs<types::Double>();
109     pDblZ = pTList->getField("tz")->getAs<types::Double>();
110     pDblOrder = pTList->getField("order")->getAs<types::Double>();
111     pDblCoef = pTList->getField("bcoef")->getAs<types::Double>();
112     pDblXyzminmax = pTList->getField("xyzminmax")->getAs<types::Double>();
113
114     if (in.size() == 5)
115     {
116         if (in[4]->isString() == false)
117         {
118             Scierror(999, _("%s: Wrong type for input argument #%d : string expected.\n"), "interp3d", 5);
119             return types::Function::Error;
120         }
121
122         char* type = in[4]->getAs<types::String>()->get(0);
123
124         if (strcmp(type, "C0") == 0)
125         {
126             iType = 8;
127         }
128         else if (strcmp(type, "by_zero") == 0)
129         {
130             iType = 7;
131         }
132         else if (strcmp(type, "periodic") == 0)
133         {
134             iType = 3;
135         }
136         else if (strcmp(type, "by_nan") == 0)
137         {
138             iType = 10;
139         }
140         else // undefined
141         {
142             Scierror(999, _("%s: Wrong values for input argument #%d : '%s' is an unknown '%s' type.\n"), "interp3d", 5, type, "outmode");
143             return types::Function::Error;
144         }
145     }
146     else
147     {
148         //"C0"
149         iType = 8;
150     }
151
152     // *** Perform operation. ***
153     pDblFp = new types::Double(pDblXYZ[0]->getRows(), pDblXYZ[0]->getCols());
154
155     order[0] = static_cast<int>(pDblOrder->get(0));
156     order[1] = static_cast<int>(pDblOrder->get(1));
157     order[2] = static_cast<int>(pDblOrder->get(2));
158
159     int sizeOfX = pDblX->getRows() - order[0];
160     int sizeOfY = pDblY->getRows() - order[1];
161     int sizeOfZ = pDblZ->getRows() - order[2];
162
163     double* minmax = pDblXyzminmax->get();
164
165     int workSize = order[1] * order[2] + 3 * std::max(order[0], std::max(order[1], order[2])) + order[2];
166     double* work = new double[workSize];
167
168     if (_iRetCount == 1)
169     {
170         C2F(driverdb3val)(pDblXYZ[0]->get(), pDblXYZ[1]->get(), pDblXYZ[2]->get(), pDblFp->get(), &sizeOfXp,
171                           pDblX->get(), pDblY->get(), pDblZ->get(), &sizeOfX, &sizeOfY, &sizeOfZ,
172                           &order[0], &order[1], &order[2], pDblCoef->get(), work,
173                           &minmax[0], &minmax[1], &minmax[2], &minmax[3], &minmax[4], &minmax[5], &iType);
174     }
175     else // _iRetCount == 4
176     {
177         pDblFpdx = new types::Double(pDblXYZ[0]->getRows(), pDblXYZ[0]->getCols());
178         pDblFpdy = new types::Double(pDblXYZ[0]->getRows(), pDblXYZ[0]->getCols());
179         pDblFpdz = new types::Double(pDblXYZ[0]->getRows(), pDblXYZ[0]->getCols());
180
181         C2F(driverdb3valwithgrad)(pDblXYZ[0]->get(), pDblXYZ[1]->get(), pDblXYZ[2]->get(),
182                                   pDblFp->get(), pDblFpdx->get(), pDblFpdy->get(), pDblFpdz->get(),
183                                   &sizeOfXp, pDblX->get(), pDblY->get(), pDblZ->get(),
184                                   &sizeOfX, &sizeOfY, &sizeOfZ, &order[0], &order[1], &order[2], pDblCoef->get(), work,
185                                   &minmax[0], &minmax[1], &minmax[2], &minmax[3], &minmax[4], &minmax[5], &iType);
186     }
187
188     delete[] work;
189
190     // *** Return result in Scilab. ***
191     switch (_iRetCount)
192     {
193         case 4 :
194             out.insert(out.begin(), pDblFpdz);
195         case 3 :
196             out.insert(out.begin(), pDblFpdy);
197         case 2 :
198             out.insert(out.begin(), pDblFpdx);
199         default :
200             break;
201     }
202
203     out.insert(out.begin(), pDblFp);
204
205     return types::Function::OK;
206 }
207