summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntoine ELIAS <antoine.elias@esi-group.com>2020-03-05 09:45:13 +0100
committerClement DAVID <clement.david@esi-group.com>2020-03-10 10:33:51 +0100
commit5c5f20c776e4d8dbc833fbcd3851e115f008938f (patch)
tree92b4edca1af97dcce97f7f3235e760ec0c115eb4
parent54d399b6bbf065082b29db8fdbe573c85b636249 (diff)
downloadscilab-5c5f20c776e4d8dbc833fbcd3851e115f008938f.zip
scilab-5c5f20c776e4d8dbc833fbcd3851e115f008938f.tar.gz
improve strcat, strsubst, part performance
//strcat a = ones(1,300000); b = string(a); tic();strcat(b);toc() //strsubst A = string(rand(100, 100)); tic;B = strcat(A);toc tic;strsubst(B, "3", "X");toc tic;strsubst(B, "30", "X");toc tic;strsubst(B, "3", "XYZ");toc //part c = 1e5; str = strcat(string(int(rand(1, c) * 10))); idx = int(rand(1, c) * c + 1); tic;part(str, idx);toc Change-Id: I8f2635cf3ce2e3ab257690935ddf0961b403ea40
-rw-r--r--scilab/CHANGES.md4
-rw-r--r--scilab/modules/string/sci_gateway/cpp/sci_part.cpp39
-rw-r--r--scilab/modules/string/sci_gateway/cpp/sci_strcat.cpp102
-rw-r--r--scilab/modules/string/sci_gateway/cpp/sci_strsubst.cpp49
-rw-r--r--scilab/modules/string/tests/benchmarks/bench_part2.tst20
5 files changed, 114 insertions, 100 deletions
diff --git a/scilab/CHANGES.md b/scilab/CHANGES.md
index 4a5bdb5..64c2623 100644
--- a/scilab/CHANGES.md
+++ b/scilab/CHANGES.md
@@ -265,6 +265,10 @@ Bug Fixes
265--------- 265---------
266 266
267### Bugs fixed in 6.1.0: 267### Bugs fixed in 6.1.0:
268* [#16342](https://bugzilla.scilab.org/16342): `strcat()` was much slower in Scilab 6.0.2.
269
270
271### Bugs fixed in 6.1.0:
268* [#2694](https://bugzilla.scilab.org/2694): `bitget` did not accept positive integers of types int8, int16 or int32. 272* [#2694](https://bugzilla.scilab.org/2694): `bitget` did not accept positive integers of types int8, int16 or int32.
269* [#5824](https://bugzilla.scilab.org/5824): The `datafit` algorithm was not documented. 273* [#5824](https://bugzilla.scilab.org/5824): The `datafit` algorithm was not documented.
270* [#6070](https://bugzilla.scilab.org/6070): How to make multiscaled plots was not documented. 274* [#6070](https://bugzilla.scilab.org/6070): How to make multiscaled plots was not documented.
diff --git a/scilab/modules/string/sci_gateway/cpp/sci_part.cpp b/scilab/modules/string/sci_gateway/cpp/sci_part.cpp
index 81c24ab..5c6c028 100644
--- a/scilab/modules/string/sci_gateway/cpp/sci_part.cpp
+++ b/scilab/modules/string/sci_gateway/cpp/sci_part.cpp
@@ -79,23 +79,44 @@ types::Function::ReturnValue sci_part(types::typed_list &in, int _iRetCount, typ
79 return types::Function::Error; 79 return types::Function::Error;
80 } 80 }
81 81
82 int* piIndex = new int[pD->getSize()]; 82 size_t i_len = pD->getSize();
83 for (int i = 0 ; i < pD->getSize() ; i++) 83 std::vector<int> index(i_len);
84 for (int i = 0 ; i < i_len; i++)
84 { 85 {
85 piIndex[i] = static_cast<int>(pD->getReal()[i]); 86 int idx = static_cast<int>(pD->get()[i]);
86 if (piIndex[i] < 1) 87 if (idx < 1)
87 { 88 {
88 Scierror(36, _("%s: Wrong values for input argument #%d: Must be >= 1.\n"), "part", 2); 89 Scierror(36, _("%s: Wrong values for input argument #%d: Must be >= 1.\n"), "part", 2);
89 delete[] piIndex;
90 return types::Function::Error; 90 return types::Function::Error;
91 } 91 }
92
93 index[i] = idx;
92 } 94 }
93 95
94 wchar_t** pwstOut = partfunctionW(pS->get(), pS->getRows(), pS->getCols(), piIndex, pD->getSize()); 96 //wchar_t** pwstOut = partfunctionW(pS->get(), pS->getRows(), pS->getCols(), piIndex, pD->getSize());
95 delete[] piIndex;
96 types::String* pOut = new types::String(pS->getRows(), pS->getCols()); 97 types::String* pOut = new types::String(pS->getRows(), pS->getCols());
97 pOut->set(pwstOut); 98 std::wstring string_in;
98 freeArrayOfWideString(pwstOut, pOut->getSize()); 99 std::wstring string_out;
100
101 for (int i = 0; i < pS->getSize(); ++i)
102 {
103 string_in.assign(pS->get()[i]);
104 size_t s_len = string_in.size();
105 string_out.assign(i_len, L' ');
106
107 for (int j = 0; j < i_len; ++j)
108 {
109 if (index[j] > s_len)
110 {
111 continue;
112 }
113
114 string_out[j] = string_in[index[j] - 1];
115 }
116
117 pOut->set(i, string_out.data());
118 }
119
99 out.push_back(pOut); 120 out.push_back(pOut);
100 return types::Function::OK; 121 return types::Function::OK;
101} 122}
diff --git a/scilab/modules/string/sci_gateway/cpp/sci_strcat.cpp b/scilab/modules/string/sci_gateway/cpp/sci_strcat.cpp
index e44a112..23cdefa 100644
--- a/scilab/modules/string/sci_gateway/cpp/sci_strcat.cpp
+++ b/scilab/modules/string/sci_gateway/cpp/sci_strcat.cpp
@@ -40,13 +40,6 @@ extern "C"
40#define ONE_CHAR 1 40#define ONE_CHAR 1
41#define EMPTY_CHAR "" 41#define EMPTY_CHAR ""
42/*-------------------------------------------------------------------------------------*/ 42/*-------------------------------------------------------------------------------------*/
43static int sci_strcat_three_rhs(char *fname);
44static int sci_strcat_two_rhs(char *fname);
45static int sci_strcat_one_rhs(char *fname);
46static int sci_strcat_rhs_one_is_a_matrix(char *fname);
47static int sumlengthstring(int rhspos);
48static int *lengthEachString(int rhspos, int *sizeArrayReturned);
49/*-------------------------------------------------------------------------------------*/
50types::Function::ReturnValue sci_strcat(types::typed_list &in, int _iRetCount, types::typed_list &out) 43types::Function::ReturnValue sci_strcat(types::typed_list &in, int _iRetCount, types::typed_list &out)
51{ 44{
52 int iMode = 0; 45 int iMode = 0;
@@ -118,47 +111,25 @@ types::Function::ReturnValue sci_strcat(types::typed_list &in, int _iRetCount, t
118 111
119 int size = pS->getSize(); 112 int size = pS->getSize();
120 wchar_t** s = pS->get(); 113 wchar_t** s = pS->get();
114 std::wstring string_out(s[0]);
121 115
122 int insertLen = 0;
123 if (pwstToInsert)
124 {
125 insertLen = (int)wcslen(pwstToInsert);
126 }
127
128 /*compute final size*/
129 int iLen = 1; //L'\0'
130 for (int i = 0 ; i < size ; i++)
131 {
132 iLen += (int)wcslen(s[i]);
133 }
134
135 if (pwstToInsert != NULL)
136 {
137 iLen += insertLen * (size - 1);
138 }
139
140 wchar_t* pwstOut = (wchar_t*)MALLOC(sizeof(wchar_t) * iLen);
141 pwstOut[0] = L'\0';
142
143 wcscpy(pwstOut, s[0]);
144 if (pwstToInsert) 116 if (pwstToInsert)
145 { 117 {
146 for (int i = 1; i < size; ++i) 118 for (int i = 1; i < size; ++i)
147 { 119 {
148 wcscat(pwstOut, pwstToInsert); 120 string_out += pwstToInsert;
149 wcscat(pwstOut, s[i]); 121 string_out += s[i];
150 } 122 }
151 } 123 }
152 else 124 else
153 { 125 {
154 for (int i = 1; i < size; ++i) 126 for (int i = 1; i < size; ++i)
155 { 127 {
156 wcscat(pwstOut, s[i]); 128 string_out += s[i];
157 } 129 }
158 } 130 }
159 131
160 pOut->set(0, pwstOut); 132 pOut->set(0, string_out.data());
161 FREE(pwstOut);
162 } 133 }
163 break; 134 break;
164 case 1 : //"r" 135 case 1 : //"r"
@@ -169,48 +140,29 @@ types::Function::ReturnValue sci_strcat(types::typed_list &in, int _iRetCount, t
169 140
170 pOut = new types::String(1, cols); 141 pOut = new types::String(1, cols);
171 142
172 int insertLen = 0;
173 if (pwstToInsert)
174 {
175 insertLen = (int)wcslen(pwstToInsert);
176 }
177
178 /*compute final size*/ 143 /*compute final size*/
144 std::wstring string_out;
179 for (int i = 0 ; i < cols ; ++i) 145 for (int i = 0 ; i < cols ; ++i)
180 { 146 {
181 int iLen = 1; //L'\0' 147 string_out.assign(s[i * rows]);
182 for (int j = 0 ; j < rows; ++j)
183 {
184 iLen += (int)wcslen(s[i * rows + j]);
185 }
186
187 if (pwstToInsert != NULL)
188 {
189 iLen += insertLen * (rows - 1);
190 }
191 148
192 wchar_t* pwstOut = (wchar_t*)MALLOC(sizeof(wchar_t) * iLen);
193 pwstOut[0] = L'\0';
194
195 wcscpy(pwstOut, s[i * rows]);
196 if (pwstToInsert) 149 if (pwstToInsert)
197 { 150 {
198 for (int j = 1; j < rows; ++j) 151 for (int j = 1; j < rows; ++j)
199 { 152 {
200 wcscat(pwstOut, pwstToInsert); 153 string_out += pwstToInsert;
201 wcscat(pwstOut, s[i * rows + j]); 154 string_out += s[i * rows + j];
202 } 155 }
203 } 156 }
204 else 157 else
205 { 158 {
206 for (int j = 1; j < rows; ++j) 159 for (int j = 1; j < rows; ++j)
207 { 160 {
208 wcscat(pwstOut, s[i * rows + j]); 161 string_out += s[i * rows + j];
209 } 162 }
210 } 163 }
211 164
212 pOut->set(0, i, pwstOut); 165 pOut->set(0, i, string_out.data());
213 FREE(pwstOut);
214 } 166 }
215 break; 167 break;
216 } 168 }
@@ -222,48 +174,28 @@ types::Function::ReturnValue sci_strcat(types::typed_list &in, int _iRetCount, t
222 174
223 pOut = new types::String(rows, 1); 175 pOut = new types::String(rows, 1);
224 176
225 int insertLen = 0;
226 if (pwstToInsert)
227 {
228 insertLen = (int)wcslen(pwstToInsert);
229 }
230
231 /*compute final size*/ 177 /*compute final size*/
178 std::wstring string_out;
232 for (int i = 0 ; i < rows ; ++i) 179 for (int i = 0 ; i < rows ; ++i)
233 { 180 {
234 int iLen = 1; //L'\0' 181 string_out.assign(s[i]);
235 for (int j = 0 ; j < cols ; ++j)
236 {
237 iLen += (int)wcslen(s[j * rows + i]);
238 }
239
240 if (pwstToInsert != NULL)
241 {
242 iLen += insertLen * (cols - 1);
243 }
244
245 wchar_t* pwstOut = (wchar_t*)MALLOC(sizeof(wchar_t) * iLen);
246 pwstOut[0] = L'\0';
247
248 wcscpy(pwstOut, s[i]);
249 if (pwstToInsert) 182 if (pwstToInsert)
250 { 183 {
251 for (int j = 1; j < cols; ++j) 184 for (int j = 1; j < cols; ++j)
252 { 185 {
253 wcscat(pwstOut, pwstToInsert); 186 string_out += pwstToInsert;
254 wcscat(pwstOut, s[j * rows + i]); 187 string_out += s[j * rows + i];
255 } 188 }
256 } 189 }
257 else 190 else
258 { 191 {
259 for (int j = 1; j < cols; ++j) 192 for (int j = 1; j < cols; ++j)
260 { 193 {
261 wcscat(pwstOut, s[j * rows + i]); 194 string_out += s[j * rows + i];
262 } 195 }
263 } 196 }
264 197
265 pOut->set(i, 0, pwstOut); 198 pOut->set(i, 0, string_out.data());
266 FREE(pwstOut);
267 } 199 }
268 break; 200 break;
269 } 201 }
diff --git a/scilab/modules/string/sci_gateway/cpp/sci_strsubst.cpp b/scilab/modules/string/sci_gateway/cpp/sci_strsubst.cpp
index 1dc6b59..c888fc2 100644
--- a/scilab/modules/string/sci_gateway/cpp/sci_strsubst.cpp
+++ b/scilab/modules/string/sci_gateway/cpp/sci_strsubst.cpp
@@ -93,14 +93,12 @@ types::Function::ReturnValue sci_strsubst(types::typed_list &in, int _iRetCount,
93 } 93 }
94 94
95 types::String* pS = in[0]->getAs<types::String>(); 95 types::String* pS = in[0]->getAs<types::String>();
96
97 types::String* pOut = new types::String(pS->getRows(), pS->getCols()); 96 types::String* pOut = new types::String(pS->getRows(), pS->getCols());
98 wchar_t** pwstOutput = NULL;
99 97
100 if (bRegExp) 98 if (bRegExp)
101 { 99 {
102 int iErr = 0; 100 int iErr = 0;
103 pwstOutput = wcssubst_reg(const_cast<const wchar_t**>(pS->get()), pS->getSize(), pwstSearch, pwstReplace, &iErr); 101 wchar_t** pwstOutput = wcssubst_reg(const_cast<const wchar_t**>(pS->get()), pS->getSize(), pwstSearch, pwstReplace, &iErr);
104 if (iErr != NO_MATCH && iErr != PCRE_FINISHED_OK && iErr != PCRE_EXIT) 102 if (iErr != NO_MATCH && iErr != PCRE_FINISHED_OK && iErr != PCRE_EXIT)
105 { 103 {
106 freeArrayOfWideString(pwstOutput, pOut->getSize()); 104 freeArrayOfWideString(pwstOutput, pOut->getSize());
@@ -108,14 +106,53 @@ types::Function::ReturnValue sci_strsubst(types::typed_list &in, int _iRetCount,
108 delete pOut; 106 delete pOut;
109 return types::Function::Error; 107 return types::Function::Error;
110 } 108 }
109
110 pOut->set(pwstOutput);
111 freeArrayOfWideString(pwstOutput, pOut->getSize());
111 } 112 }
112 else 113 else
113 { 114 {
114 pwstOutput = wcssubst(const_cast<const wchar_t**>(pS->get()), pS->getSize(), pwstSearch, pwstReplace); 115 std::wstring search = pwstSearch;
116 std::wstring replace = pwstReplace;
117 size_t s_len = search.size();
118 size_t r_len = replace.size();
119
120 // on empty search string, convert only empty string to the replace
121 if (s_len == 0)
122 {
123 for (int i = 0; i < pS->getSize(); ++i)
124 {
125 wchar_t* wcs = pS->get()[i];
126 if (wcslen(wcs) > 0)
127 {
128 pOut->set(i, wcs);
129 }
130 else
131 {
132 pOut->set(i, pwstReplace);
133 }
134 }
135 out.push_back(pOut);
136 return types::Function::OK;
137 }
138
139 // regular string search
140 std::wstring string_out;
141 for (int i = 0; i < pS->getSize(); ++i)
142 {
143 string_out.assign(pS->get()[i]);
144
145 size_t pos = string_out.find(search);
146 while (pos != std::string::npos)
147 {
148 string_out.replace(pos, s_len, replace);
149 pos = string_out.find(search, pos + r_len);
150 }
151
152 pOut->set(i, string_out.data());
153 }
115 } 154 }
116 155
117 pOut->set(pwstOutput);
118 freeArrayOfWideString(pwstOutput, pOut->getSize());
119 out.push_back(pOut); 156 out.push_back(pOut);
120 return types::Function::OK; 157 return types::Function::OK;
121} 158}
diff --git a/scilab/modules/string/tests/benchmarks/bench_part2.tst b/scilab/modules/string/tests/benchmarks/bench_part2.tst
new file mode 100644
index 0000000..6048ba6
--- /dev/null
+++ b/scilab/modules/string/tests/benchmarks/bench_part2.tst
@@ -0,0 +1,20 @@
1// =============================================================================
2// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3// Copyright (C) 2020 - ESI Group - Antoine ELIAS
4//
5// This file is distributed under the same license as the Scilab package.
6// =============================================================================
7
8//==============================================================================
9// Benchmark for part function
10//==============================================================================
11
12// <-- BENCH NB RUN : 10000 -->
13
14c = 1e5;
15str = strcat(string(int(rand(1, c) * 10)));
16idx = int(rand(1, c) * c + 1);
17
18// <-- BENCH START -->
19part(str, idx);
20// <-- BENCH END -->