Skip to content

Commit f9a199d

Browse files
authored
Merge pull request #13 from bokuweb/use-flat
use flat
2 parents d7f323f + 5febfa3 commit f9a199d

File tree

4 files changed

+86
-97
lines changed

4 files changed

+86
-97
lines changed

lib/index.ts

+16-8
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export default function diff<T>(A: T[], B: T[]): DiffResult<T>[] {
5757
}
5858

5959
function createFP(slide: FarthestPoint, down: FarthestPoint, k: number, M: number, N: number): FarthestPoint {
60-
if (slide && slide.y === -1 && (down && down.y === -1)) return { y: 0, id: 0 };
60+
if (slide && slide.y === -1 && down && down.y === -1) return { y: 0, id: 0 };
6161
if ((down && down.y === -1) || k === M || (slide && slide.y) > (down && down.y) + 1) {
6262
const prev = slide.id;
6363
ptr++;
@@ -108,11 +108,11 @@ export default function diff<T>(A: T[], B: T[]): DiffResult<T>[] {
108108
const offset = N;
109109
const delta = M - N;
110110
const size = M + N + 1;
111-
const fp = new Array(size).fill({ y: -1 });
111+
let fp = new Array(size).fill({ y: -1 });
112112
// INFO: This buffer is used to save memory and improve performance.
113113
// The first half is used to save route and last half is used to save diff type.
114114
// This is because, when I kept new uint8array area to save type, performance worsened.
115-
const routes = new Uint32Array((M * N + size + 1) * 2);
115+
let routes = new Uint32Array((M * N + size + 1) * 2);
116116
const diffTypesPtrOffset = routes.length / 2;
117117
let ptr = 0;
118118
let p = -1;
@@ -126,9 +126,17 @@ export default function diff<T>(A: T[], B: T[]): DiffResult<T>[] {
126126
}
127127
fp[delta + offset] = snake(delta, fp[delta - 1 + offset], fp[delta + 1 + offset], offset, A, B);
128128
}
129-
return [
130-
...prefixCommon.map(c => ({ type: 'common' as DiffType, value: c })),
131-
...backTrace(A, B, fp[delta + offset], swapped),
132-
...suffixCommon.map(c => ({ type: 'common' as DiffType, value: c })),
133-
];
129+
const pre = prefixCommon.map(c => ({ type: 'common' as DiffType, value: c }));
130+
const traced = backTrace(A, B, fp[delta + offset], swapped);
131+
const suf = suffixCommon.map(c => ({ type: 'common' as DiffType, value: c }));
132+
133+
// cleanup
134+
(routes as any) = null;
135+
(fp as any) = null;
136+
137+
if ('flat' in Array.prototype) {
138+
return [pre, traced, suf].flat();
139+
} else {
140+
return [...pre, ...traced, ...suf];
141+
}
134142
}

package.json

+8-8
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,28 @@
66
"author": "bokuweb <[email protected]>",
77
"license": "MIT",
88
"scripts": {
9-
"build": "tsc --outDir dist",
9+
"build": "tsc -p tsconfig.json --outDir dist",
1010
"clean": "rimraf ./dist",
1111
"example": "npm run build && node examples/example.js",
12-
"test": "tsc --outDir dist && ava dist/*.test.js",
13-
"tsc:watch": "tsc --outDir dist -w",
12+
"test": "tsc -p tsconfig.json --outDir dist && ava dist/*.test.js",
13+
"tsc:watch": "tsc -p tsconfig.json --outDir dist -w",
1414
"test:watch": "ava dist/*.test.js --watch",
1515
"watch": "run-p tsc:watch test:watch",
1616
"prepublish": "run-s clean build"
1717
},
1818
"devDependencies": {
19-
"@types/node": "^9.6.0",
19+
"@types/node": "^16.7.10",
2020
"ava": "^0.25.0",
21-
"npm-run-all": "^4.1.2",
21+
"benchmark": "^2.1.4",
22+
"npm-run-all": "^4.1.5",
2223
"rimraf": "^2.6.2",
23-
"typescript": "^2.8.0",
24-
"benchmark": "^2.1.4"
24+
"typescript": "^4.4.2"
2525
},
2626
"typings": "./dist/index.d.ts",
2727
"files": [
2828
"dist"
2929
],
3030
"dependencies": {
31-
"tslib": "^1.9.0"
31+
"tslib": "^2.3.1"
3232
}
3333
}

tsconfig.json

+3-9
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,14 @@
11
{
2-
"exclude": [
3-
"node_modules",
4-
"dist"
5-
],
2+
"exclude": ["node_modules", "dist"],
63
"compilerOptions": {
74
/* Basic Options */
85
"target": "es5",
96
"module": "commonjs",
10-
"lib": [
11-
"es2015",
12-
"dom"
13-
],
7+
"lib": ["esnext.array", "es2019"],
148
// "allowJs": true, /* Allow javascript files to be compiled. */
159
// "checkJs": true, /* Report errors in .js files. */
1610
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
17-
"declaration": true, /* Generates corresponding '.d.ts' file. */
11+
"declaration": true /* Generates corresponding '.d.ts' file. */,
1812
// "sourceMap": true, /* Generates corresponding '.map' file. */
1913
// "outFile": "./", /* Concatenate and emit output to single file. */
2014
// "outDir": "./", /* Redirect output structure to the directory. */

yarn.lock

+59-72
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,10 @@
5353
pretty-ms "^0.2.1"
5454
text-table "^0.2.0"
5555

56-
"@types/node@^9.6.0":
57-
version "9.6.0"
58-
resolved "https://registry.yarnpkg.com/@types/node/-/node-9.6.0.tgz#d3480ee666df9784b1001a1872a2f6ccefb6c2d7"
56+
"@types/node@^16.7.10":
57+
version "16.7.10"
58+
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.7.10.tgz#7aa732cc47341c12a16b7d562f519c2383b6d4fc"
59+
integrity sha512-S63Dlv4zIPb8x6MMTgDq5WWRJQe56iBEY0O3SOFA9JrRienkOVDXSXBjjJw6HTNQYSE2JI6GMCR6LVbIMHJVvA==
5960

6061
abbrev@1:
6162
version "1.1.1"
@@ -90,7 +91,7 @@ ansi-styles@^2.2.1:
9091
version "2.2.1"
9192
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
9293

93-
ansi-styles@^3.1.0, ansi-styles@^3.2.0, ansi-styles@^3.2.1:
94+
ansi-styles@^3.1.0, ansi-styles@^3.2.1:
9495
version "3.2.1"
9596
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
9697
dependencies:
@@ -734,14 +735,23 @@ chalk@^1.1.3:
734735
strip-ansi "^3.0.0"
735736
supports-color "^2.0.0"
736737

737-
chalk@^2.0.1, chalk@^2.1.0:
738+
chalk@^2.0.1:
738739
version "2.3.2"
739740
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65"
740741
dependencies:
741742
ansi-styles "^3.2.1"
742743
escape-string-regexp "^1.0.5"
743744
supports-color "^5.3.0"
744745

746+
chalk@^2.4.1:
747+
version "2.4.2"
748+
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
749+
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
750+
dependencies:
751+
ansi-styles "^3.2.1"
752+
escape-string-regexp "^1.0.5"
753+
supports-color "^5.3.0"
754+
745755
chokidar@^1.4.2:
746756
version "1.7.0"
747757
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468"
@@ -898,14 +908,25 @@ create-error-class@^3.0.0:
898908
dependencies:
899909
capture-stack-trace "^1.0.0"
900910

901-
cross-spawn@^5.0.1, cross-spawn@^5.1.0:
911+
cross-spawn@^5.0.1:
902912
version "5.1.0"
903913
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
904914
dependencies:
905915
lru-cache "^4.0.1"
906916
shebang-command "^1.2.0"
907917
which "^1.2.9"
908918

919+
cross-spawn@^6.0.5:
920+
version "6.0.5"
921+
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
922+
integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
923+
dependencies:
924+
nice-try "^1.0.4"
925+
path-key "^2.0.1"
926+
semver "^5.5.0"
927+
shebang-command "^1.2.0"
928+
which "^1.2.9"
929+
909930
910931
version "2.0.5"
911932
resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8"
@@ -1001,10 +1022,6 @@ duplexer3@^0.1.4:
10011022
version "0.1.4"
10021023
resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
10031024

1004-
duplexer@~0.1.1:
1005-
version "0.1.1"
1006-
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1"
1007-
10081025
ecc-jsbn@~0.1.1:
10091026
version "0.1.1"
10101027
resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505"
@@ -1081,18 +1098,6 @@ esutils@^2.0.2:
10811098
version "2.0.2"
10821099
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
10831100

1084-
event-stream@~3.3.0:
1085-
version "3.3.4"
1086-
resolved "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571"
1087-
dependencies:
1088-
duplexer "~0.1.1"
1089-
from "~0"
1090-
map-stream "~0.1.0"
1091-
pause-stream "0.0.11"
1092-
split "0.3"
1093-
stream-combiner "~0.0.4"
1094-
through "~2.3.1"
1095-
10961101
execa@^0.7.0:
10971102
version "0.7.0"
10981103
resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777"
@@ -1210,10 +1215,6 @@ form-data@~2.1.1:
12101215
combined-stream "^1.0.5"
12111216
mime-types "^2.1.12"
12121217

1213-
from@~0:
1214-
version "0.1.7"
1215-
resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe"
1216-
12171218
fs.realpath@^1.0.0:
12181219
version "1.0.0"
12191220
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
@@ -1894,10 +1895,6 @@ map-obj@^1.0.0, map-obj@^1.0.1:
18941895
version "1.0.1"
18951896
resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
18961897

1897-
map-stream@~0.1.0:
1898-
version "0.1.0"
1899-
resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194"
1900-
19011898
matcher@^1.0.0:
19021899
version "1.1.0"
19031900
resolved "https://registry.yarnpkg.com/matcher/-/matcher-1.1.0.tgz#4ad3a9cb6585186dc95cb8a08c7de936caed17ee"
@@ -2012,6 +2009,11 @@ nan@^2.3.0:
20122009
version "2.10.0"
20132010
resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f"
20142011

2012+
nice-try@^1.0.4:
2013+
version "1.0.5"
2014+
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
2015+
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
2016+
20152017
node-pre-gyp@^0.6.39:
20162018
version "0.6.39"
20172019
resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz#c00e96860b23c0e1420ac7befc5044e1d78d8649"
@@ -2050,16 +2052,17 @@ normalize-path@^2.0.0, normalize-path@^2.0.1:
20502052
dependencies:
20512053
remove-trailing-separator "^1.0.1"
20522054

2053-
npm-run-all@^4.1.2:
2054-
version "4.1.2"
2055-
resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.2.tgz#90d62d078792d20669139e718621186656cea056"
2055+
npm-run-all@^4.1.5:
2056+
version "4.1.5"
2057+
resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.5.tgz#04476202a15ee0e2e214080861bff12a51d98fba"
2058+
integrity sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==
20562059
dependencies:
2057-
ansi-styles "^3.2.0"
2058-
chalk "^2.1.0"
2059-
cross-spawn "^5.1.0"
2060+
ansi-styles "^3.2.1"
2061+
chalk "^2.4.1"
2062+
cross-spawn "^6.0.5"
20602063
memorystream "^0.3.1"
20612064
minimatch "^3.0.4"
2062-
ps-tree "^1.1.0"
2065+
pidtree "^0.3.0"
20632066
read-pkg "^3.0.0"
20642067
shell-quote "^1.6.1"
20652068
string.prototype.padend "^3.0.0"
@@ -2232,7 +2235,7 @@ path-is-inside@^1.0.1:
22322235
version "1.0.2"
22332236
resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
22342237

2235-
path-key@^2.0.0:
2238+
path-key@^2.0.0, path-key@^2.0.1:
22362239
version "2.0.1"
22372240
resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
22382241

@@ -2256,16 +2259,15 @@ path-type@^3.0.0:
22562259
dependencies:
22572260
pify "^3.0.0"
22582261

2259-
2260-
version "0.0.11"
2261-
resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445"
2262-
dependencies:
2263-
through "~2.3"
2264-
22652262
performance-now@^0.2.0:
22662263
version "0.2.0"
22672264
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5"
22682265

2266+
pidtree@^0.3.0:
2267+
version "0.3.1"
2268+
resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.3.1.tgz#ef09ac2cc0533df1f3250ccf2c4d366b0d12114a"
2269+
integrity sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==
2270+
22692271
pify@^2.0.0:
22702272
version "2.3.0"
22712273
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
@@ -2346,12 +2348,6 @@ process-nextick-args@~2.0.0:
23462348
version "2.0.0"
23472349
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa"
23482350

2349-
ps-tree@^1.1.0:
2350-
version "1.1.0"
2351-
resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.1.0.tgz#b421b24140d6203f1ed3c76996b4427b08e8c014"
2352-
dependencies:
2353-
event-stream "~3.3.0"
2354-
23552351
pseudomap@^1.0.2:
23562352
version "1.0.2"
23572353
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
@@ -2589,6 +2585,11 @@ semver-diff@^2.0.0:
25892585
version "5.5.0"
25902586
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
25912587

2588+
semver@^5.5.0:
2589+
version "5.7.1"
2590+
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
2591+
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
2592+
25922593
serialize-error@^2.1.0:
25932594
version "2.1.0"
25942595
resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-2.1.0.tgz#50b679d5635cdf84667bdc8e59af4e5b81d5f60a"
@@ -2692,12 +2693,6 @@ spdx-license-ids@^3.0.0:
26922693
version "3.0.0"
26932694
resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz#7a7cd28470cc6d3a1cfe6d66886f6bc430d3ac87"
26942695

2695-
2696-
version "0.3.3"
2697-
resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f"
2698-
dependencies:
2699-
through "2"
2700-
27012696
sprintf-js@~1.0.2:
27022697
version "1.0.3"
27032698
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
@@ -2720,12 +2715,6 @@ stack-utils@^1.0.1:
27202715
version "1.0.1"
27212716
resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.1.tgz#d4f33ab54e8e38778b0ca5cfd3b3afb12db68620"
27222717

2723-
stream-combiner@~0.0.4:
2724-
version "0.0.4"
2725-
resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14"
2726-
dependencies:
2727-
duplexer "~0.1.1"
2728-
27292718
string-width@^1.0.1, string-width@^1.0.2:
27302719
version "1.0.2"
27312720
resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
@@ -2871,10 +2860,6 @@ through2@^2.0.0:
28712860
readable-stream "^2.1.5"
28722861
xtend "~4.0.1"
28732862

2874-
through@2, through@~2.3, through@~2.3.1:
2875-
version "2.3.8"
2876-
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
2877-
28782863
time-zone@^1.0.0:
28792864
version "1.0.0"
28802865
resolved "https://registry.yarnpkg.com/time-zone/-/time-zone-1.0.0.tgz#99c5bf55958966af6d06d83bdf3800dc82faec5d"
@@ -2905,9 +2890,10 @@ trim-right@^1.0.1:
29052890
version "1.0.1"
29062891
resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
29072892

2908-
tslib@^1.9.0:
2909-
version "1.9.0"
2910-
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8"
2893+
tslib@^2.3.1:
2894+
version "2.3.1"
2895+
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01"
2896+
integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==
29112897

29122898
tunnel-agent@^0.6.0:
29132899
version "0.6.0"
@@ -2919,9 +2905,10 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0:
29192905
version "0.14.5"
29202906
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
29212907

2922-
typescript@^2.8.0:
2923-
version "2.8.1"
2924-
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.8.1.tgz#6160e4f8f195d5ba81d4876f9c0cc1fbc0820624"
2908+
typescript@^4.4.2:
2909+
version "4.4.2"
2910+
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.2.tgz#6d618640d430e3569a1dfb44f7d7e600ced3ee86"
2911+
integrity sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ==
29252912

29262913
uid-number@^0.0.6:
29272914
version "0.0.6"

0 commit comments

Comments
 (0)