• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

krakjoe / ort / 16400708798

20 Jul 2025 02:04PM UTC coverage: 93.107% (-0.1%) from 93.25%
16400708798

push

github

krakjoe
endings

5808 of 6238 relevant lines covered (93.11%)

115945.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.06
/src/generators/random.c
1
/*
2
  +----------------------------------------------------------------------+
3
  | ort                                                                  |
4
  +----------------------------------------------------------------------+
5
  | Copyright (c) Joe Watkins 2025                                       |
6
  +----------------------------------------------------------------------+
7
  | This source file is subject to version 3.01 of the PHP license,      |
8
  | that is bundled with this package in the file LICENSE, and is        |
9
  | available through the world-wide-web at the following url:           |
10
  | http://www.php.net/license/3_01.txt                                  |
11
  | If you did not receive a copy of the PHP license and are unable to   |
12
  | obtain it through the world-wide-web, please send a note to          |
13
  | license@php.net so we can mail you a copy immediately.               |
14
  +----------------------------------------------------------------------+
15
  | Author: krakjoe                                                      |
16
  +----------------------------------------------------------------------+
17
 */
18

19

20
 /** 
21
{{{
22
    @file generators/random.c
23
    @brief This API provides random generators for Tensor constructors.
24
    
25
    The constructor is overloaded:
26

27
    We shall determine the min and max derived from type:
28
    Tensor\Generator Tensor\Generator\Random(int $type)
29

30
    We shall determine the max derived from type, verifying the minimum is within range:
31
    Tensor\Generator Tensor\Generator\Random(int $type, mixed $min)
32

33
    We shall verify the min and max are within range:
34
    Tensor\Generator Tensor\Generator\Random(int $type, mixed $min, mixed $max)
35

36
    For example:
37
        $tensor = new Tensor\Transient([24, 24],
38
            new Tensor\Generator\Random(Tensor::FLOAT));
39
        Will generate a 24x24 tensor with float values in the range 0-1 (never inclusive of 1.0)
40

41
        $tensor = new Tensor\Transient([24, 24],
42
            new Tensor\Generator\Random(Tensor::UINT8, 0, 255));
43
        Will generate a 24x24 tensor with UINT8 values in the range 0-255
44

45
        $tensor = new Tensor\Transient([24, 24],
46
            new Tensor\Generator\Random(Tensor::INT8));
47
        Will generate a 24x24 tensor with INT8 values in the range INT8_MIN to INT8_MAX
48

49
        An exception will be thrown if min exceeds max, of if any parameter is out of range.
50
}}} */
51
#include "status.h"
52
#include "generators.h"
53
#include "generators/random.h"
54

55
#if PHP_VERSION_ID >= 80200
56
#include <ext/random/php_random.h>
57
#else
58
#include <ext/standard/php_mt_rand.h>
59
#endif
60

61
#if PHP_VERSION_ID < 80300
62
const char* zend_zval_value_name(const zval* arg) {
63
    if (Z_ISUNDEF_P(arg)) {
64
        return "null";
65
    }
66

67
    if (Z_TYPE_P(arg) == IS_OBJECT) {
68
        return ZSTR_VAL(Z_OBJCE_P(arg)->name);
69
    } else if (Z_TYPE_P(arg) == IS_FALSE) {
70
        return "false";
71
    } else if  (Z_TYPE_P(arg) == IS_TRUE) {
72
        return "true";
73
    }
74

75
    return zend_get_type_by_const(Z_TYPE_P(arg));
76
}
77
#endif
78

79
zend_class_entry* php_ort_generator_random_ce;
80

81
typedef struct _php_ort_generator_random_context_t{
82
    zend_long type;
83
    zval min;
84
    zval max;
85
} php_ort_generator_random_context_t;
86

87
static zend_always_inline void
88
    php_ort_generator_random_invoke(
15,552✔
89
        php_ort_generator_t* generator, zval* zv) {
90
    php_ort_generator_random_context_t* context =
15,552✔
91
        (php_ort_generator_random_context_t*) generator->context;
92

93
    switch (context->type) {
15,552✔
94
        case ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT:
3,456✔
95
        case ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE: {
96
            double min = Z_DVAL(context->min);
3,456✔
97
            double max = Z_DVAL(context->max);
3,456✔
98
            double scale =
6,912✔
99
                (double) php_mt_rand() /
3,456✔
100
                    ((double) PHP_MT_RAND_MAX + 1.0);
101

102
            if (scale > 0.999999) {
3,456✔
103
                scale = 0.999999;
104
            }
105

106
            if (scale < 0.0) {
1,719✔
107
                scale = 0;
×
108
            }
109

110
            ZVAL_DOUBLE(zv, min + scale * (max - min));
3,456✔
111
            break;
3,456✔
112
        }
113
        
114
        default: {
12,096✔
115
            ZVAL_LONG(zv, php_mt_rand_range(
12,096✔
116
                Z_LVAL(context->min), Z_LVAL(context->max)));
117
            break;
12,096✔
118
        }
119
    }
120
}
15,552✔
121

122
static zend_object* php_ort_generator_random_create(
432✔
123
    zend_class_entry* ce) {
124
    php_ort_generator_t* generator =
432✔
125
        zend_object_alloc(
432✔
126
            sizeof(php_ort_generator_t), ce);
127

128
    zend_object_std_init(&generator->std, ce);
432✔
129
    object_properties_init(&generator->std, ce);
432✔
130

131
    generator->std.handlers =
432✔
132
        &php_ort_generator_handlers;
133

134
    generator->invoke = php_ort_generator_random_invoke;
432✔
135
    generator->context =
864✔
136
        ecalloc(1, sizeof(php_ort_generator_random_context_t));
432✔
137

138
    return &generator->std;
432✔
139
}
140

141
ZEND_BEGIN_ARG_INFO_EX(
142
    php_ort_generator_random__construct_arginfo, 0, 0, 1)
143
    ZEND_ARG_TYPE_INFO(0, type, IS_LONG, 0)
144
    ZEND_ARG_TYPE_INFO(0, min, IS_LONG, 0)
145
    ZEND_ARG_TYPE_INFO(0, max, IS_LONG, 0)
146
ZEND_END_ARG_INFO()
147

148
#define ORT_GENERATOR_RANDOM_CHECK_TYPE(type, var, name) \
149
do {                                                     \
150
    if (Z_TYPE_P(var) != IS_##type) {                    \
151
        zend_throw_exception_ex(                         \
152
            php_ort_status_error_ce, 0,                  \
153
            "Expected "#type" for "#name", got %s",      \
154
            zend_zval_value_name(var));                  \
155
        return;                                          \
156
    }                                                    \
157
} while(0)
158

159
#define ORT_GENERATOR_RANDOM_CHECK_SIGNED_RANGE(var, name, min, max)\
160
do {                                                                  \
161
    if (Z_LVAL_P(var) < min || Z_LVAL_P(var) > max) {                 \
162
        zend_throw_exception_ex(                                      \
163
            php_ort_status_error_ce, 0,                               \
164
            "Value for "#name" must be between "                      \
165
                ZEND_LONG_FMT" and "                                  \
166
                ZEND_LONG_FMT", got "ZEND_LONG_FMT"",                 \
167
            (zend_long) min,                                          \
168
            (zend_long) max,                                          \
169
            Z_LVAL_P(var));                                           \
170
        return;                                                       \
171
    }                                                                 \
172
} while(0)
173

174
#define ORT_GENERATOR_RANDOM_CHECK_UNSIGNED_RANGE(var, name, max)     \
175
do {                                                                  \
176
    if (Z_LVAL_P(var) < 0 || Z_LVAL_P(var) > max) {                   \
177
        zend_throw_exception_ex(                                      \
178
            php_ort_status_error_ce, 0,                               \
179
            "Value for "#name" must be between 0 and "                \
180
            "%d, got "ZEND_LONG_FMT"",                                \
181
            max,                                                      \
182
            Z_LVAL_P(var));                                           \
183
        return;                                                       \
184
    }                                                                 \
185
} while(0)
186

187
PHP_METHOD(Generator_RandomInt, __construct) {
432✔
188
    php_ort_generator_t* generator =
432✔
189
        php_ort_generator_fetch(
432✔
190
            Z_OBJ_P(getThis()));
432✔
191
    php_ort_generator_random_context_t* context =
432✔
192
        (php_ort_generator_random_context_t*)
193
            generator->context;
194

195
    memset(context, 0, sizeof(
432✔
196
        php_ort_generator_random_context_t));
197

198
    zval* min = NULL;
432✔
199
    zval* max = NULL;
432✔
200

201
    ZEND_PARSE_PARAMETERS_START(1, 3)
432✔
202
        Z_PARAM_LONG(context->type)
864✔
203
        Z_PARAM_OPTIONAL
432✔
204
        Z_PARAM_ZVAL(min)
432✔
205
        Z_PARAM_ZVAL(max)
288✔
206
    ZEND_PARSE_PARAMETERS_END();
432✔
207

208
    if (ZEND_NUM_ARGS() == 1) {
432✔
209
        /* only a type provided, we set range */
210
        switch (context->type) {
144✔
211
            case ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT:
32✔
212
            case ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE:
213
                ZVAL_DOUBLE(&context->min, 0.0);
32✔
214
                ZVAL_DOUBLE(&context->max, 1.0);
32✔
215
                break;
32✔
216

217
            case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8:
16✔
218
                ZVAL_LONG(&context->min, INT8_MIN);
16✔
219
                ZVAL_LONG(&context->max, INT8_MAX);
16✔
220
                break;
16✔
221

222
            case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT16:
16✔
223
                ZVAL_LONG(&context->min, INT16_MIN);
16✔
224
                ZVAL_LONG(&context->max, INT16_MAX);
16✔
225
                break;
16✔
226

227
            case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32:
16✔
228
                ZVAL_LONG(&context->min, INT32_MIN);
16✔
229
                ZVAL_LONG(&context->max, INT32_MAX);
16✔
230
                break;
16✔
231

232
            case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64:
16✔
233
                ZVAL_LONG(&context->min, INT64_MIN);
16✔
234
                ZVAL_LONG(&context->max, INT64_MAX);
16✔
235
                break;
16✔
236

237
            case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8:
16✔
238
                ZVAL_LONG(&context->min, 0);
16✔
239
                ZVAL_LONG(&context->max, UINT8_MAX);
16✔
240
                break;
16✔
241

242
            case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT16:
16✔
243
                ZVAL_LONG(&context->min, 0);
16✔
244
                ZVAL_LONG(&context->max, UINT16_MAX);
16✔
245
                break;
16✔
246

247
            case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT32:
16✔
248
                ZVAL_LONG(&context->min, 0);
16✔
249
                ZVAL_LONG(&context->max, UINT32_MAX);
16✔
250
                break;
16✔
251

252
            default:
×
253
                zend_throw_exception_ex(
×
254
                    php_ort_status_error_ce, 0,
255
                    "Unsupported type for Random generator: %s",
256
                    php_ort_type_name(context->type));
257
                return;
×
258
        }
259
    } else if (ZEND_NUM_ARGS() == 2) {
288✔
260
        /* type and min provided */
261

262
#define ORT_GENERATOR_RANDOM_CHECK_SIGNED_CASE(          \
263
    type, minimum, maximum) do {                         \
264
    ORT_GENERATOR_RANDOM_CHECK_TYPE(type, min, "min");   \
265
    ORT_GENERATOR_RANDOM_CHECK_SIGNED_RANGE(             \
266
        min, "min", minimum, maximum);                   \
267
    ZVAL_COPY(&context->min, min);                       \
268
    ZVAL_LONG(&context->max, maximum);                   \
269
} while(0)
270

271
#define ORT_GENERATOR_RANDOM_CHECK_UNSIGNED_CASE(        \
272
    type, maximum) do {                                  \
273
    ORT_GENERATOR_RANDOM_CHECK_TYPE(type, min, "min");   \
274
    ORT_GENERATOR_RANDOM_CHECK_UNSIGNED_RANGE(           \
275
        min, "min", maximum);                            \
276
    ZVAL_COPY(&context->min, min);                       \
277
    ZVAL_LONG(&context->max, maximum);                   \
278
} while(0)
279

280
        switch (context->type) {
144✔
281
            case ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT:
32✔
282
            case ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE:
283
                ORT_GENERATOR_RANDOM_CHECK_TYPE(
32✔
284
                    DOUBLE, min, "min");
285
                ZVAL_COPY(&context->min, min);
32✔
286
                ZVAL_DOUBLE(&context->max, 1.0);
32✔
287
                break;
32✔
288

289
            case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8:
16✔
290
                ORT_GENERATOR_RANDOM_CHECK_SIGNED_CASE(LONG, INT8_MIN, INT8_MAX);
16✔
291
                break;
16✔
292

293
            case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT16:
16✔
294
                ORT_GENERATOR_RANDOM_CHECK_SIGNED_CASE(LONG, INT16_MIN, INT16_MAX);
16✔
295
                break;
16✔
296

297
            case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32:
16✔
298
                ORT_GENERATOR_RANDOM_CHECK_SIGNED_CASE(LONG, INT32_MIN, INT32_MAX);
16✔
299
                break;
16✔
300

301
            case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64:
16✔
302
                ORT_GENERATOR_RANDOM_CHECK_SIGNED_CASE(LONG, INT64_MIN, INT64_MAX);
16✔
303
                break;
16✔
304

305
            case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8:
16✔
306
                ORT_GENERATOR_RANDOM_CHECK_UNSIGNED_CASE(LONG, UINT8_MAX);
16✔
307
                break;
16✔
308

309
            case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT16:
16✔
310
                ORT_GENERATOR_RANDOM_CHECK_UNSIGNED_CASE(LONG, UINT16_MAX);
16✔
311
                break;
16✔
312

313
            case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT32:
16✔
314
                ORT_GENERATOR_RANDOM_CHECK_UNSIGNED_CASE(LONG, UINT32_MAX);
16✔
315
                break;
16✔
316

317
            default:
×
318
                zend_throw_exception_ex(
×
319
                    php_ort_status_error_ce, 0,
320
                    "Unsupported type for Random generator: %s",
321
                    php_ort_type_name(context->type));
322
                return;
×
323
        }
324

325
#undef ORT_GENERATOR_RANDOM_CHECK_SIGNED_CASE
326
#undef ORT_GENERATOR_RANDOM_CHECK_UNSIGNED_CASE
327
    } else if (ZEND_NUM_ARGS() == 3) {
144✔
328
        /* type, min and max provided */
329

330
#define ORT_GENERATOR_RANDOM_CHECK_SIGNED_CASE(        \
331
    type, minimum, maximum) do {                       \
332
    ORT_GENERATOR_RANDOM_CHECK_TYPE(                   \
333
        type, min, "min");                             \
334
    ORT_GENERATOR_RANDOM_CHECK_TYPE(                   \
335
        type, max, "max");                             \
336
    ORT_GENERATOR_RANDOM_CHECK_SIGNED_RANGE(           \
337
        min, "min", minimum, maximum);                 \
338
    ORT_GENERATOR_RANDOM_CHECK_SIGNED_RANGE(           \
339
        max, "max", minimum, maximum);                 \
340
    if (Z_LVAL_P(min) > Z_LVAL_P(max)) {               \
341
        zend_throw_exception_ex(                       \
342
            php_ort_status_error_ce, 0,                \
343
            "Min value must be less than or equal to " \
344
            "max value for Random generator");         \
345
        return;                                        \
346
    }                                                  \
347
    ZVAL_COPY(&context->min, min);                     \
348
    ZVAL_COPY(&context->max, max);                     \
349
} while(0)
350

351
#define ORT_GENERATOR_RANDOM_CHECK_UNSIGNED_CASE(      \
352
    type,  maximum) do {                               \
353
    ORT_GENERATOR_RANDOM_CHECK_TYPE(                   \
354
        type, min, "min");                             \
355
    ORT_GENERATOR_RANDOM_CHECK_TYPE(                   \
356
        type, max, "max");                             \
357
    ORT_GENERATOR_RANDOM_CHECK_UNSIGNED_RANGE(         \
358
        min, "min", maximum);                          \
359
    ORT_GENERATOR_RANDOM_CHECK_UNSIGNED_RANGE(         \
360
        max, "max", maximum);                          \
361
    if (Z_LVAL_P(min) > Z_LVAL_P(max)) {               \
362
        zend_throw_exception_ex(                       \
363
            php_ort_status_error_ce, 0,                \
364
            "Min value must be less than or equal to " \
365
            "max value for Random generator");         \
366
        return;                                        \
367
    }                                                  \
368
    ZVAL_COPY(&context->min, min);                     \
369
    ZVAL_COPY(&context->max, max);                     \
370
} while(0)
371

372
        switch (context->type) {
144✔
373
            case ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT:
32✔
374
            case ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE:
375
                ORT_GENERATOR_RANDOM_CHECK_TYPE(
32✔
376
                    DOUBLE, min, "min");
377
                ORT_GENERATOR_RANDOM_CHECK_TYPE(
32✔
378
                    DOUBLE, max, "max");
379
                ZVAL_COPY(&context->min, min);
32✔
380
                ZVAL_COPY(&context->max, max);
32✔
381
            break;
382

383
            case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8:
16✔
384
                ORT_GENERATOR_RANDOM_CHECK_SIGNED_CASE(LONG, INT8_MIN, INT8_MAX);
16✔
385
                break;
386
            
387
            case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT16:
16✔
388
                ORT_GENERATOR_RANDOM_CHECK_SIGNED_CASE(LONG, INT16_MIN, INT16_MAX);
16✔
389
                break;
390

391
            case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32:
16✔
392
                ORT_GENERATOR_RANDOM_CHECK_SIGNED_CASE(LONG, INT32_MIN, INT32_MAX);
16✔
393
                break;
394

395
            case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64:
16✔
396
                ORT_GENERATOR_RANDOM_CHECK_SIGNED_CASE(LONG, INT64_MIN, INT64_MAX);
16✔
397
                break;
398

399
            case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8:
16✔
400
                ORT_GENERATOR_RANDOM_CHECK_UNSIGNED_CASE(LONG, UINT8_MAX);
16✔
401
                break;
402

403
            case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT16:
16✔
404
                ORT_GENERATOR_RANDOM_CHECK_UNSIGNED_CASE(LONG, UINT16_MAX);
16✔
405
                break;
406

407
            case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT32:
16✔
408
                ORT_GENERATOR_RANDOM_CHECK_UNSIGNED_CASE(LONG, UINT32_MAX);
16✔
409
                break;
410

411
            default:
×
412
                zend_throw_exception_ex(
×
413
                    php_ort_status_error_ce, 0,
414
                    "Unsupported type for Random generator: %s",
415
                    php_ort_type_name(context->type));
416
                return;
×
417
        }
418
#undef ORT_GENERATOR_RANDOM_CHECK_SIGNED_CASE
419
#undef ORT_GENERATOR_RANDOM_CHECK_UNSIGNED_CASE
420
    }
421
}
422

423
#undef ORT_GENERATOR_RANDOM_CHECK_TYPE
424

425
zend_function_entry php_ort_generator_random_methods[] = {
426
    PHP_ME(Generator_RandomInt, __construct,
427
        php_ort_generator_random__construct_arginfo, ZEND_ACC_PUBLIC)
428
    PHP_FE_END
429
};
430

431
PHP_MINIT_FUNCTION(ORT_GENERATORS_RANDOM)
3,296✔
432
{
433
    zend_class_entry ce;
3,296✔
434

435
    INIT_NS_CLASS_ENTRY(ce,
3,296✔
436
        "ORT\\Tensor\\Generator",
437
        "Random", php_ort_generator_random_methods);
3,296✔
438
    php_ort_generator_random_ce =
6,592✔
439
        zend_register_internal_class_ex(
3,296✔
440
            &ce, php_ort_generator_internal_ce);
441
    php_ort_generator_random_ce->create_object =
3,296✔
442
        php_ort_generator_random_create;
443
    php_ort_generator_random_ce->ce_flags |= ZEND_ACC_FINAL;
3,296✔
444

445
    return SUCCESS;
3,296✔
446
}
447

448
PHP_MSHUTDOWN_FUNCTION(ORT_GENERATORS_RANDOM) 
3,296✔
449
{
450
    return SUCCESS;
3,296✔
451
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc