Skip to content

Commit 56dab20

Browse files
committed
chore: initial script
1 parent 90c26b3 commit 56dab20

File tree

2 files changed

+518
-0
lines changed

2 files changed

+518
-0
lines changed
Lines changed: 387 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,387 @@
1+
/* eslint-disable */
2+
3+
var resolve = require( 'path' ).resolve;
4+
var writeFile = require( '@stdlib/fs/write-file' ).sync;
5+
var readFile = require( '@stdlib/fs/read-file' ).sync;
6+
var replace = require( '@stdlib/string/replace' );
7+
var dtypeChar = require( '@stdlib/ndarray/base/dtype-char' );
8+
var dtypeEnum2Str = require( '@stdlib/ndarray/base/dtype-enum2str' );
9+
var uppercase = require( '@stdlib/string/uppercase' );
10+
var currentYear = require( '@stdlib/time/current-year' );
11+
var supportedTypes = require( './../lib/types.js' );
12+
13+
// VARIABLES //
14+
15+
var OPTS = {
16+
'encoding': 'utf8'
17+
};
18+
19+
// Define paths
20+
var SRC_PATH = resolve( __dirname, '..', 'src', 'addon.c.txt' );
21+
var OUT_PATH = resolve( __dirname, '..', 'src', 'addon.c' );
22+
23+
// Define constants for the abs function
24+
var FCN_BASENAME = 'abs';
25+
var FCN_DESCRIPTION = 'Computes the absolute value.';
26+
var INTERFACE_NAME = 'stdlib_ndarray_abs';
27+
28+
// Define a note
29+
var NOTE = 'NOTE: Do not edit this file directly. This file is auto-generated.';
30+
var YEAR = currentYear();
31+
var COPYRIGHT = 'The Stdlib Authors';
32+
33+
// FUNCTIONS //
34+
35+
/**
36+
* Generates function mappings based on the existing types.js file.
37+
*
38+
* @private
39+
* @returns {Object} object containing functions, types, and data arrays
40+
*/
41+
function generateFunctionMappings() {
42+
var functions = [];
43+
var typeEnums = [];
44+
var data = [];
45+
var i, inputDtype, outputDtype, inputChar, outputChar;
46+
var functionName, typePair, dataFunction;
47+
48+
// Process the supportedTypes array (which contains pairs: input, output, input, output, ...)
49+
for ( i = 0; i < supportedTypes.length; i += 2 ) {
50+
// Convert numeric dtype constants to string names
51+
inputDtype = dtypeEnum2Str( supportedTypes[ i ] );
52+
outputDtype = dtypeEnum2Str( supportedTypes[ i + 1 ] );
53+
54+
// Handle generic types specially
55+
if ( inputDtype === 'generic' || outputDtype === 'generic' ) {
56+
// For generic types, we use a special function name pattern
57+
if ( inputDtype === 'generic' && outputDtype === 'generic' ) {
58+
functionName = 'stdlib_ndarray_v_v';
59+
} else if ( outputDtype === 'generic' ) {
60+
inputChar = dtypeChar( inputDtype );
61+
functionName = 'stdlib_ndarray_' + inputChar + '_v';
62+
} else {
63+
// This case shouldn't occur in the current types.js
64+
continue;
65+
}
66+
} else {
67+
// Get dtype characters for non-generic types
68+
inputChar = dtypeChar( inputDtype );
69+
outputChar = dtypeChar( outputDtype );
70+
71+
if ( inputChar === 'a' ) {
72+
inputChar = 'b';
73+
}
74+
if ( outputChar === 'a' ) {
75+
outputChar = 'b';
76+
}
77+
78+
// Generate function name
79+
functionName = generateFunctionName( inputChar, outputChar );
80+
}
81+
82+
functions.push( functionName );
83+
84+
// Generate type pair
85+
typePair = generateTypePair( inputDtype, outputDtype );
86+
typeEnums.push( typePair );
87+
88+
// Generate data function (generic types also use abs)
89+
dataFunction = generateDataFunction( inputDtype );
90+
data.push( dataFunction );
91+
}
92+
93+
return {
94+
'functions': functions,
95+
'types': typeEnums,
96+
'data': data
97+
};
98+
}
99+
100+
/**
101+
* Generates the ndarray function name for given input and output dtype characters.
102+
*
103+
* @private
104+
* @param {string} inputChar - input dtype character
105+
* @param {string} outputChar - output dtype character
106+
* @returns {string} function name
107+
*/
108+
function generateFunctionName( inputChar, outputChar ) {
109+
// Use simple naming convention without casting suffix (matches original)
110+
var functionName = 'stdlib_ndarray_' + inputChar + '_' + outputChar;
111+
return functionName;
112+
}
113+
114+
/**
115+
* Generates the type pair string for given input and output dtypes.
116+
*
117+
* @private
118+
* @param {string} inputDtype - input data type
119+
* @param {string} outputDtype - output data type
120+
* @returns {string} type pair string
121+
*/
122+
function generateTypePair( inputDtype, outputDtype ) {
123+
var inputEnum, outputEnum;
124+
125+
// Handle generic type specially
126+
if ( inputDtype === 'generic' ) {
127+
inputEnum = 'STDLIB_NDARRAY_GENERIC';
128+
} else {
129+
inputEnum = 'STDLIB_NDARRAY_' + uppercase( inputDtype );
130+
}
131+
132+
if ( outputDtype === 'generic' ) {
133+
outputEnum = 'STDLIB_NDARRAY_GENERIC';
134+
} else {
135+
outputEnum = 'STDLIB_NDARRAY_' + uppercase( outputDtype );
136+
}
137+
138+
return inputEnum + ', ' + outputEnum;
139+
}
140+
141+
/**
142+
* Generates the data function pointer for given input dtype.
143+
*
144+
* @private
145+
* @param {string} inputDtype - input data type
146+
* @returns {string} data function pointer
147+
*/
148+
function generateDataFunction( inputDtype ) {
149+
var functionPtr;
150+
151+
// Map dtypes to appropriate C functions
152+
if ( inputDtype === 'float64' ) {
153+
functionPtr = '(void *)stdlib_base_abs';
154+
} else if ( inputDtype === 'float32' ) {
155+
functionPtr = '(void *)stdlib_base_absf';
156+
} else if ( inputDtype === 'int32' ) {
157+
functionPtr = '(void *)stdlib_base_labs';
158+
} else if ( inputDtype === 'int16' ) {
159+
functionPtr = '(void *)abs_k'; // Custom int16 abs function
160+
} else if ( inputDtype === 'int8' ) {
161+
functionPtr = '(void *)abs_s'; // Custom int8 abs function
162+
} else if ( inputDtype === 'uint32' ) {
163+
functionPtr = '(void *)identity_u'; // Identity for unsigned types
164+
} else if ( inputDtype === 'uint16' ) {
165+
functionPtr = '(void *)identity_t';
166+
} else if ( inputDtype === 'uint8' || inputDtype === 'uint8c' ) {
167+
functionPtr = '(void *)identity_b';
168+
} else if ( inputDtype === 'generic' ) {
169+
functionPtr = '(void *)stdlib_base_abs'; // Generic uses regular abs
170+
} else {
171+
// Default fallback
172+
functionPtr = '(void *)stdlib_base_abs';
173+
}
174+
175+
return functionPtr;
176+
}
177+
178+
/**
179+
* Creates a basic addon.c template if it doesn't exist.
180+
*
181+
* @private
182+
*/
183+
function createTemplate() {
184+
var template = `/**
185+
* @license Apache-2.0
186+
*
187+
* Copyright (c) {{YEAR}} {{COPYRIGHT}}.
188+
*
189+
* Licensed under the Apache License, Version 2.0 (the "License");
190+
* you may not use this file except in compliance with the License.
191+
* You may obtain a copy of the License at
192+
*
193+
* http://www.apache.org/licenses/LICENSE-2.0
194+
*
195+
* Unless required by applicable law or agreed to in writing, software
196+
* distributed under the License is distributed on an "AS IS" BASIS,
197+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
198+
* See the License for the specific language governing permissions and
199+
* limitations under the License.
200+
*/
201+
202+
/* {{NOTE}} */
203+
204+
#include "stdlib/math/base/special/abs.h"
205+
#include "stdlib/math/base/special/absf.h"
206+
#include "stdlib/math/base/special/labs.h"
207+
#include "stdlib/ndarray/base/function_object.h"
208+
#include "stdlib/ndarray/base/napi/unary.h"
209+
#include "stdlib/ndarray/base/unary.h"
210+
#include "stdlib/ndarray/dtypes.h"
211+
#include <stdint.h>
212+
213+
/**
214+
* Evaluates the identity function for an unsigned 32-bit integer.
215+
*
216+
* @param x input value
217+
* @return input value
218+
*/
219+
static uint32_t identity_u( const uint32_t x ) {
220+
return x;
221+
}
222+
223+
/**
224+
* Evaluates the identity function for an unsigned 16-bit integer.
225+
*
226+
* @param x input value
227+
* @return input value
228+
*/
229+
static uint16_t identity_t( const uint16_t x ) {
230+
return x;
231+
}
232+
233+
/**
234+
* Evaluates the identity function for an unsigned 8-bit integer.
235+
*
236+
* @param x input value
237+
* @return input value
238+
*/
239+
static uint8_t identity_b( const uint8_t x ) {
240+
return x;
241+
}
242+
243+
/**
244+
* Computes the absolute value of a signed 16-bit integer.
245+
*
246+
* @param x input value
247+
* @return absolute value
248+
*/
249+
static int16_t abs_k( const int16_t x ) {
250+
if ( x < 0 ) {
251+
return -x;
252+
}
253+
return x;
254+
}
255+
256+
/**
257+
* Computes the absolute value of a signed 8-bit integer.
258+
*
259+
* @param x input value
260+
* @return absolute value
261+
*/
262+
static int8_t abs_s( const int8_t x ) {
263+
if ( x < 0 ) {
264+
return -x;
265+
}
266+
return x;
267+
}
268+
269+
// Define an interface name:
270+
static const char name[] = "{{INTERFACE_NAME}}";
271+
272+
// Define a list of ndarray functions:
273+
static ndarrayFcn functions[] = {
274+
{{FUNCTIONS}}
275+
};
276+
277+
// Define the **ndarray** argument types for each ndarray function:
278+
static int32_t types[] = {
279+
{{TYPES}}
280+
};
281+
282+
// Define a list of ndarray function "data" (in this case, callbacks):
283+
static void *data[] = {
284+
{{DATA}}
285+
};
286+
287+
// Create an ndarray function object:
288+
static const struct ndarrayFunctionObject obj = {
289+
// ndarray function name:
290+
name,
291+
292+
// Number of input ndarrays:
293+
1,
294+
295+
// Number of output ndarrays:
296+
1,
297+
298+
// Total number of ndarray arguments (nin + nout):
299+
2,
300+
301+
// Array containing ndarray functions:
302+
functions,
303+
304+
// Number of ndarray functions:
305+
{{NUM_FUNCTIONS}},
306+
307+
// 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:
308+
types,
309+
310+
// 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):
311+
data
312+
};
313+
314+
STDLIB_NDARRAY_NAPI_MODULE_UNARY( obj )
315+
`;
316+
317+
var err = writeFile( SRC_PATH, template, OPTS );
318+
if ( err ) {
319+
throw err;
320+
}
321+
console.log( 'Created template file: ' + SRC_PATH );
322+
}
323+
324+
/**
325+
* Generates the addon.c file for the abs function.
326+
*
327+
* @private
328+
* @throws {Error} unexpected error
329+
*/
330+
function generateAddonC() {
331+
var template;
332+
var functions;
333+
var types;
334+
var data;
335+
var err;
336+
337+
// Read the template file
338+
template = readFile( SRC_PATH, OPTS );
339+
if ( template instanceof Error ) {
340+
throw template;
341+
}
342+
343+
// Generate function signatures, types, and data arrays
344+
var result = generateFunctionMappings();
345+
functions = result.functions;
346+
types = result.types;
347+
data = result.data;
348+
349+
// Replace template placeholders
350+
template = replace( template, '{{YEAR}}', YEAR.toString() );
351+
template = replace( template, '{{COPYRIGHT}}', COPYRIGHT );
352+
template = replace( template, '{{NOTE}}', NOTE );
353+
template = replace( template, '{{FCN_BASENAME}}', FCN_BASENAME );
354+
template = replace( template, '{{FCN_DESCRIPTION}}', FCN_DESCRIPTION );
355+
template = replace( template, '{{INTERFACE_NAME}}', INTERFACE_NAME );
356+
template = replace( template, '{{FUNCTIONS}}', functions.join( ',\n\t' ) );
357+
template = replace( template, '{{TYPES}}', types.join( ',\n\t' ) );
358+
template = replace( template, '{{DATA}}', data.join( ',\n\t' ) );
359+
template = replace( template, '{{NUM_FUNCTIONS}}', functions.length.toString() );
360+
361+
// Write the generated file
362+
err = writeFile( OUT_PATH, template, OPTS );
363+
if ( err ) {
364+
throw err;
365+
}
366+
367+
console.log( 'Generated addon.c with ' + functions.length + ' function mappings.' );
368+
}
369+
370+
371+
372+
// MAIN //
373+
374+
console.log( 'Generating addon.c for stdlib abs function...' );
375+
376+
// Create template if it doesn't exist, then generate the addon.c file
377+
try {
378+
generateAddonC();
379+
} catch ( error ) {
380+
if ( error.code === 'ENOENT' ) {
381+
console.log( 'Template file not found. Creating template...' );
382+
createTemplate();
383+
generateAddonC();
384+
} else {
385+
throw error;
386+
}
387+
}

0 commit comments

Comments
 (0)