|
| 1 | +/** |
| 2 | +* @license Apache-2.0 |
| 3 | +* |
| 4 | +* Copyright (c) 2021 The Stdlib Authors. |
| 5 | +* |
| 6 | +* Licensed under the Apache License, Version 2.0 (the "License"); |
| 7 | +* you may not use this file except in compliance with the License. |
| 8 | +* You may obtain a copy of the License at |
| 9 | +* |
| 10 | +* http://www.apache.org/licenses/LICENSE-2.0 |
| 11 | +* |
| 12 | +* Unless required by applicable law or agreed to in writing, software |
| 13 | +* distributed under the License is distributed on an "AS IS" BASIS, |
| 14 | +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 15 | +* See the License for the specific language governing permissions and |
| 16 | +* limitations under the License. |
| 17 | +*/ |
| 18 | + |
| 19 | +'use strict'; |
| 20 | + |
| 21 | +// MODULES // |
| 22 | + |
| 23 | +var join = require( 'path' ).join; |
| 24 | +var writeFileSync = require( '@stdlib/fs/write-file' ).sync; |
| 25 | +var dtypes = require( '@stdlib/ndarray/dtypes' ); |
| 26 | +var currentYear = require( '@stdlib/time/current-year' ); |
| 27 | + |
| 28 | + |
| 29 | +// VARIABLES // |
| 30 | + |
| 31 | +var FUNCTION_NAME = 'abs'; |
| 32 | +var KERNEL_MAP = { |
| 33 | + 'float64': 'stdlib_base_abs', |
| 34 | + 'float32': 'stdlib_base_absf', |
| 35 | + 'complex128': 'stdlib_base_cabs', |
| 36 | + 'complex64': 'stdlib_base_cabsf', |
| 37 | + 'int32': 'stdlib_base_labs', |
| 38 | + 'int16': 'stdlib_base_labs', |
| 39 | + 'int8': 'stdlib_base_labs', |
| 40 | + 'uint32': 'stdlib_base_abs', |
| 41 | + 'uint16': 'stdlib_base_abs', |
| 42 | + 'uint8': 'stdlib_base_abs', |
| 43 | + 'uint8c': 'stdlib_base_abs', |
| 44 | + 'generic': 'stdlib_base_abs' |
| 45 | +}; |
| 46 | +var INCLUDE_MAP = { |
| 47 | + 'abs': 'abs.h', |
| 48 | + 'absf': 'absf.h', |
| 49 | + 'cabs': 'cabs.h', |
| 50 | + 'cabsf': 'cabsf.h', |
| 51 | + 'labs': 'labs.h' |
| 52 | +}; |
| 53 | + |
| 54 | +/** |
| 55 | +* Default output dtype rule for abs function. |
| 56 | +* |
| 57 | +* @private |
| 58 | +* @param {string} input - input dtype |
| 59 | +* @returns {Array<string>} array of valid output dtypes |
| 60 | +*/ |
| 61 | +function outputDtypeRule( input ) { |
| 62 | + var rules = { |
| 63 | + 'float64': [ 'float64', 'generic' ], |
| 64 | + 'float32': [ 'float32', 'float64', 'generic' ], |
| 65 | + 'complex128': [ 'float64', 'generic' ], |
| 66 | + 'complex64': [ 'float32', 'float64', 'generic' ], |
| 67 | + 'int32': [ 'int32', 'uint32', 'float64', 'generic' ], |
| 68 | + 'int16': [ 'int16', 'int32', 'uint16', 'uint32', 'float32', 'float64', 'generic' ], |
| 69 | + 'int8': [ 'int8', 'int16', 'int32', 'uint8', 'uint8c', 'uint16', 'uint32', 'float32', 'float64', 'generic' ], |
| 70 | + 'uint32': [ 'uint32', 'float64', 'generic' ], |
| 71 | + 'uint16': [ 'int32', 'uint16', 'uint32', 'float32', 'float64', 'generic' ], |
| 72 | + 'uint8': [ 'int16', 'int32', 'uint8', 'uint8c', 'uint16', 'uint32', 'float32', 'float64', 'generic' ], |
| 73 | + 'uint8c': [ 'int16', 'int32', 'uint8', 'uint8c', 'uint16', 'uint32', 'float32', 'float64', 'generic' ], |
| 74 | + 'generic': [ 'generic' ] |
| 75 | + }; |
| 76 | + return rules[ input ] || []; |
| 77 | +} |
| 78 | + |
| 79 | +/** |
| 80 | +* Generates the ndarray function name for given input and output dtypes. |
| 81 | +* |
| 82 | +* @private |
| 83 | +* @param {string} input - input dtype |
| 84 | +* @param {string} output - output dtype |
| 85 | +* @returns {string} ndarray function name |
| 86 | +*/ |
| 87 | +function getNdarrayFcnName( input, output ) { |
| 88 | + var map = { |
| 89 | + 'float64': 'd', |
| 90 | + 'float32': 'f', |
| 91 | + 'generic': 'g', |
| 92 | + 'int32': 'i', |
| 93 | + 'int16': 'k', |
| 94 | + 'int8': 's', |
| 95 | + 'uint32': 'u', |
| 96 | + 'uint16': 't', |
| 97 | + 'uint8': 'b', |
| 98 | + 'uint8c': 'b' |
| 99 | + }; |
| 100 | + return 'stdlib_ndarray_' + map[ input ] + '_' + map[ output ]; |
| 101 | +} |
| 102 | + |
| 103 | +/** |
| 104 | +* Counts the number of functions in a group. |
| 105 | +* |
| 106 | +* @private |
| 107 | +* @param {string} dt - dtype |
| 108 | +* @param {Object} grouped - grouped functions |
| 109 | +* @returns {number} count |
| 110 | +*/ |
| 111 | +function countGroup( dt, grouped ) { |
| 112 | + return grouped[ dt ].length; |
| 113 | +} |
| 114 | + |
| 115 | +/** |
| 116 | +* Generates function-specific includes. |
| 117 | +* |
| 118 | +* @private |
| 119 | +* @returns {Array<string>} array of include statements |
| 120 | +*/ |
| 121 | +function generateFunctionIncludes() { |
| 122 | + var includeStatement; |
| 123 | + var functionIncludes; |
| 124 | + var kernelNames; |
| 125 | + var includeKey; |
| 126 | + var kernel; |
| 127 | + var i; |
| 128 | + |
| 129 | + functionIncludes = []; |
| 130 | + kernelNames = Object.keys( KERNEL_MAP ); |
| 131 | + for ( i = 0; i < kernelNames.length; i++ ) { |
| 132 | + kernel = KERNEL_MAP[ kernelNames[ i ] ]; |
| 133 | + includeKey = kernel.replace( 'stdlib_base_', '' ); |
| 134 | + if ( INCLUDE_MAP[ includeKey ] ) { |
| 135 | + includeStatement = '#include "stdlib/math/base/special/' + INCLUDE_MAP[ includeKey ] + '"'; |
| 136 | + if ( functionIncludes.indexOf( includeStatement ) === -1 ) { |
| 137 | + functionIncludes.push( includeStatement ); |
| 138 | + } |
| 139 | + } |
| 140 | + } |
| 141 | + return functionIncludes; |
| 142 | +} |
| 143 | + |
| 144 | +/** |
| 145 | +* Generates type pairs and kernels. |
| 146 | +* |
| 147 | +* @private |
| 148 | +* @returns {Object} object containing types and kernels arrays |
| 149 | +*/ |
| 150 | +function generateTypesAndKernels() { |
| 151 | + var outputDtypes; |
| 152 | + var allDtypes; |
| 153 | + var kernels; |
| 154 | + var output; |
| 155 | + var input; |
| 156 | + var types; |
| 157 | + var i; |
| 158 | + var j; |
| 159 | + |
| 160 | + allDtypes = dtypes( 'all' ); |
| 161 | + types = []; |
| 162 | + kernels = []; |
| 163 | + |
| 164 | + for ( i = 0; i < allDtypes.length; i++ ) { |
| 165 | + input = allDtypes[ i ]; |
| 166 | + outputDtypes = outputDtypeRule( input ); |
| 167 | + for ( j = 0; j < outputDtypes.length; j++ ) { |
| 168 | + output = outputDtypes[ j ]; |
| 169 | + types.push( [ input, output ] ); |
| 170 | + kernels.push( KERNEL_MAP[ input ] || 'stdlib_base_' + FUNCTION_NAME ); |
| 171 | + } |
| 172 | + } |
| 173 | + |
| 174 | + return { |
| 175 | + 'types': types, |
| 176 | + 'kernels': kernels |
| 177 | + }; |
| 178 | +} |
| 179 | + |
| 180 | +/** |
| 181 | +* Main function to generate addon arrays. |
| 182 | +* |
| 183 | +* @private |
| 184 | +*/ |
| 185 | +function main() { |
| 186 | + var functionIncludes; |
| 187 | + var licenseHeader; |
| 188 | + var baseIncludes; |
| 189 | + var dtypeOrder; |
| 190 | + var groupItems; |
| 191 | + var cHeader; |
| 192 | + var kernels; |
| 193 | + var grouped; |
| 194 | + var result; |
| 195 | + var types; |
| 196 | + var jsOut; |
| 197 | + var pair; |
| 198 | + var cOut; |
| 199 | + var obj; |
| 200 | + var dt; |
| 201 | + var i; |
| 202 | + var j; |
| 203 | + |
| 204 | + result = generateTypesAndKernels(); |
| 205 | + types = result.types; |
| 206 | + kernels = result.kernels; |
| 207 | + |
| 208 | + dtypeOrder = [ |
| 209 | + 'float64', 'float32', 'generic', 'int32', 'int16', 'int8', 'uint32', 'uint16', 'uint8', 'uint8c' |
| 210 | + ]; |
| 211 | + grouped = {}; |
| 212 | + |
| 213 | + for ( i = 0; i < dtypeOrder.length; i++ ) { |
| 214 | + grouped[ dtypeOrder[ i ] ] = []; |
| 215 | + } |
| 216 | + |
| 217 | + for ( i = 0; i < types.length; i++ ) { |
| 218 | + pair = types[ i ]; |
| 219 | + if ( grouped[ pair[ 0 ] ] ) { |
| 220 | + grouped[ pair[ 0 ] ].push({ |
| 221 | + 'pair': pair, |
| 222 | + 'kernel': kernels[ i ] |
| 223 | + }); |
| 224 | + } |
| 225 | + } |
| 226 | + |
| 227 | + // Write generated_types.js: |
| 228 | + licenseHeader = '/**\n* @license Apache-2.0\n*\n* Copyright (c) ' + currentYear() + ' The Stdlib Authors.\n*\n* Licensed under the Apache License, Version 2.0 (the "License");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n* http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an "AS IS" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n/* eslint-disable array-element-newline */\n\n\'use strict\';\n\n// MODULES //\n\nvar dtypes = require( \'@stdlib/ndarray/dtypes\' );\n\n\n// MAIN //\n\nvar types = [\n'; |
| 229 | + jsOut = licenseHeader; |
| 230 | + |
| 231 | + for ( i = 0; i < dtypeOrder.length; i++ ) { |
| 232 | + dt = dtypeOrder[ i ]; |
| 233 | + groupItems = grouped[ dt ]; |
| 234 | + for ( j = 0; j < groupItems.length; j++ ) { |
| 235 | + obj = groupItems[ j ]; |
| 236 | + jsOut += ' dtypes.' + obj.pair[ 0 ] + ', dtypes.' + obj.pair[ 1 ] + ',\n'; |
| 237 | + } |
| 238 | + } |
| 239 | + jsOut += '];\n\n\n// EXPORTS //\n\nmodule.exports = types;\n'; |
| 240 | + writeFileSync( join( __dirname, '../lib/generated_types.js' ), jsOut, { |
| 241 | + 'encoding': 'utf8' |
| 242 | + }); |
| 243 | + |
| 244 | + // Write generated_addon_arrays.c: |
| 245 | + cHeader = '/**\n* @license Apache-2.0\n*\n* Copyright (c) ' + currentYear() + ' The Stdlib Authors.\n*\n* Licensed under the Apache License, Version 2.0 (the "License");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n* http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an "AS IS" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n'; |
| 246 | + |
| 247 | + // Add base includes (always required for all math functions): |
| 248 | + baseIncludes = [ |
| 249 | + '#include "stdlib/ndarray/base/function_object.h"', |
| 250 | + '#include "stdlib/ndarray/base/napi/unary.h"', |
| 251 | + '#include "stdlib/ndarray/base/unary.h"', |
| 252 | + '#include "stdlib/ndarray/dtypes.h"', |
| 253 | + '#include <stdint.h>' |
| 254 | + ]; |
| 255 | + cHeader += baseIncludes.join('\n') + '\n'; |
| 256 | + |
| 257 | + // Add function-specific includes: |
| 258 | + functionIncludes = generateFunctionIncludes(); |
| 259 | + if ( functionIncludes.length > 0 ) { |
| 260 | + cHeader += functionIncludes.join('\n') + '\n'; |
| 261 | + } |
| 262 | + |
| 263 | + cOut = cHeader; |
| 264 | + cOut += '\n// Define a list of ndarray functions:\n'; |
| 265 | + cOut += 'static ndarrayFcn functions[] = {\n'; |
| 266 | + for ( i = 0; i < dtypeOrder.length; i++ ) { |
| 267 | + dt = dtypeOrder[ i ]; |
| 268 | + if ( grouped[ dt ].length > 0 ) { |
| 269 | + cOut += ' // ' + dt + ' (' + countGroup( dt, grouped ) + ')\n'; |
| 270 | + groupItems = grouped[ dt ]; |
| 271 | + for ( j = 0; j < groupItems.length; j++ ) { |
| 272 | + obj = groupItems[ j ]; |
| 273 | + cOut += ' ' + getNdarrayFcnName( obj.pair[ 0 ], obj.pair[ 1 ] ) + ',\n'; |
| 274 | + } |
| 275 | + } |
| 276 | + } |
| 277 | + cOut += '};\n\n'; |
| 278 | + cOut += '// Define the **ndarray** argument types for each ndarray function:\n'; |
| 279 | + cOut += 'static int32_t types[] = {\n'; |
| 280 | + for ( i = 0; i < dtypeOrder.length; i++ ) { |
| 281 | + dt = dtypeOrder[ i ]; |
| 282 | + groupItems = grouped[ dt ]; |
| 283 | + for ( j = 0; j < groupItems.length; j++ ) { |
| 284 | + obj = groupItems[ j ]; |
| 285 | + cOut += ' STDLIB_NDARRAY_' + obj.pair[ 0 ].toUpperCase() + ', STDLIB_NDARRAY_' + obj.pair[ 1 ].toUpperCase() + ',\n'; |
| 286 | + } |
| 287 | + } |
| 288 | + cOut += '};\n\n'; |
| 289 | + cOut += '// Define a list of ndarray function "data" (in this case, callbacks):\n'; |
| 290 | + cOut += 'static void *data[] = {\n'; |
| 291 | + for ( i = 0; i < dtypeOrder.length; i++ ) { |
| 292 | + dt = dtypeOrder[ i ]; |
| 293 | + if ( grouped[ dt ].length > 0 ) { |
| 294 | + cOut += ' // ' + dt + ' (' + countGroup( dt, grouped ) + ')\n'; |
| 295 | + groupItems = grouped[ dt ]; |
| 296 | + for ( j = 0; j < groupItems.length; j++ ) { |
| 297 | + obj = groupItems[ j ]; |
| 298 | + cOut += ' (void *)' + obj.kernel + ',\n'; |
| 299 | + } |
| 300 | + } |
| 301 | + } |
| 302 | + cOut += '};\n\n'; |
| 303 | + cOut += '// Create an ndarray function object:\n'; |
| 304 | + cOut += 'static const struct ndarrayFunctionObject obj = {\n'; |
| 305 | + cOut += ' // ndarray function name:\n name,\n\n'; |
| 306 | + cOut += ' // Number of input ndarrays:\n 1,\n\n'; |
| 307 | + cOut += ' // Number of output ndarrays:\n 1,\n\n'; |
| 308 | + cOut += ' // Total number of ndarray arguments (nin + nout):\n 2,\n\n'; |
| 309 | + cOut += ' // Array containing ndarray functions:\n functions,\n\n'; |
| 310 | + cOut += ' // Number of ndarray functions:\n ' + types.length + ',\n\n'; |
| 311 | + cOut += ' // Array of type "numbers" (as enumerated elsewhere), where the total number of types equals `narrays * nfunctions` and where each set of `narrays` consecutive types (non-overlapping) corresponds to the set of ndarray argument types for a corresponding ndarray function:\n types,\n\n'; |
| 312 | + cOut += ' // Array of void pointers corresponding to the "data" (e.g., callbacks) which should be passed to a respective ndarray function (note: the number of pointers should match the number of ndarray functions):\n data\n};\n\n'; |
| 313 | + cOut += 'STDLIB_NDARRAY_NAPI_MODULE_UNARY( obj )\n'; |
| 314 | + writeFileSync( join( __dirname, '../src/generated_addon_arrays.c' ), cOut, { |
| 315 | + 'encoding': 'utf8' |
| 316 | + }); |
| 317 | +} |
| 318 | + |
| 319 | +main(); |
0 commit comments