Skip to content

Commit 58c4aaa

Browse files
committed
Initial commit
1 parent 55fcbb2 commit 58c4aaa

17 files changed

Lines changed: 750 additions & 257 deletions
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
namespace Tensor\Benchmarks\Factories;
4+
5+
use Tensor\Vector;
6+
use Generator;
7+
8+
/**
9+
* @Groups({"Factories"})
10+
*/
11+
class VectorLinspaceBench
12+
{
13+
/**
14+
* @return list<array{size: int}>
15+
*/
16+
public function sizes() : Generator
17+
{
18+
yield 'small' => ['size' => 1024 * 1024];
19+
yield 'medium' => ['size' => 4096 * 4096];
20+
}
21+
22+
/**
23+
* @Subject
24+
* @Iterations(5)
25+
* @ParamProviders({"sizes"})
26+
* @OutputTimeUnit("milliseconds", precision=3)
27+
* @param array $params
28+
*/
29+
public function linspace(array $params) : void
30+
{
31+
Vector::linspace(0.0, 1000.0, $params['size']);
32+
}
33+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
namespace Tensor\Benchmarks\Factories;
4+
5+
use Tensor\Vector;
6+
use Generator;
7+
8+
/**
9+
* @Groups({"Factories"})
10+
*/
11+
class VectorRangeBench
12+
{
13+
/**
14+
* @return list<array{size: int}>
15+
*/
16+
public function sizes() : Generator
17+
{
18+
yield 'small' => ['size' => 1024 * 1024];
19+
yield 'medium' => ['size' => 4096 * 4096];
20+
}
21+
22+
/**
23+
* @Subject
24+
* @Iterations(5)
25+
* @ParamProviders({"sizes"})
26+
* @OutputTimeUnit("milliseconds", precision=3)
27+
* @param array $params
28+
*/
29+
public function range(array $params) : void
30+
{
31+
Vector::range(0.0, (float) $params['size'], 1.0);
32+
}
33+
}

‎ext/include/factories.c‎

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,3 +178,96 @@ void tensor_random_gaussian(zval * return_value, zval * n)
178178

179179
zval_ptr_dtor(&c);
180180
}
181+
182+
/**
183+
* Create a tensor with `n` evenly spaced values between `min` and `max`,
184+
* inclusive of both endpoints. Values are accumulated from `min` toward
185+
* `max`, with the final element forced to `max` to guarantee exact endpoint.
186+
* The caller is responsible for rejecting n < 2 or min > max.
187+
*/
188+
void tensor_linspace(zval * return_value, zval * min, zval * max, zval * n)
189+
{
190+
zend_long length = zephir_get_intval(n);
191+
double lo = zephir_get_doubleval(min);
192+
double hi = zephir_get_doubleval(max);
193+
zval c;
194+
195+
if (UNEXPECTED(tensor_tensorbuffer_create(return_value, length, &c) == FAILURE)) {
196+
return;
197+
}
198+
199+
double * vc = zephir_buffer_doubles(&c);
200+
201+
double step = fabs(hi - lo) / (double) (length - 1);
202+
203+
zend_long i;
204+
205+
vc[0] = lo;
206+
207+
for (i = 1; i < length - 1; ++i) {
208+
vc[i] = vc[i - 1] + step;
209+
}
210+
211+
vc[length - 1] = hi;
212+
213+
zval_ptr_dtor(&c);
214+
}
215+
216+
/**
217+
* Create a tensor mirroring PHP's `range($start, $end, $step)` semantics:
218+
* values are `start + i*step` (or `start - i*|step|` for decreasing range),
219+
* generated until the value crosses `end`. The caller must reject a zero step,
220+
* a step with the wrong sign for the direction of traversal, and a step
221+
* whose magnitude exceeds the span. Equal start/end yields a single-element
222+
* tensor holding that value.
223+
*/
224+
void tensor_range(zval * return_value, zval * start, zval * end, zval * interval)
225+
{
226+
double s = zephir_get_doubleval(start);
227+
double e = zephir_get_doubleval(end);
228+
double st = fabs(zephir_get_doubleval(interval));
229+
230+
zval c;
231+
232+
if (s == e) {
233+
if (UNEXPECTED(tensor_tensorbuffer_create(return_value, 1, &c) == FAILURE)) {
234+
return;
235+
}
236+
237+
double * vc = zephir_buffer_doubles(&c);
238+
239+
vc[0] = s;
240+
241+
zval_ptr_dtor(&c);
242+
243+
return;
244+
}
245+
246+
int increasing = e > s;
247+
double sign = increasing ? 1.0 : -1.0;
248+
249+
zend_long count = 0;
250+
zend_long i;
251+
252+
for (i = 0; ; ++i) {
253+
double el = s + ((double) i) * st * sign;
254+
255+
if ((increasing && el > e) || (!increasing && el < e)) {
256+
break;
257+
}
258+
259+
++count;
260+
}
261+
262+
if (UNEXPECTED(tensor_tensorbuffer_create(return_value, count, &c) == FAILURE)) {
263+
return;
264+
}
265+
266+
double * vc = zephir_buffer_doubles(&c);
267+
268+
for (i = 0; i < count; ++i) {
269+
vc[i] = s + ((double) i) * st * sign;
270+
}
271+
272+
zval_ptr_dtor(&c);
273+
}

‎ext/include/factories.h‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,22 @@ void tensor_random_uniform_pm1(zval * return_value, zval * n);
4242
*/
4343
void tensor_random_gaussian(zval * return_value, zval * n);
4444

45+
/**
46+
* Allocate a fresh `Tensor\TensorBuffer` of `n` elements holding the evenly
47+
* spaced values between `min` and `max` (inclusive of both endpoints). Values
48+
* are accumulated from `min` toward `max`, with the final element forced to
49+
* `max`. The caller must reject `n < 2` and `min > max`.
50+
*/
51+
void tensor_linspace(zval * return_value, zval * min, zval * max, zval * n);
52+
53+
/**
54+
* Allocate a fresh `Tensor\TensorBuffer` mirroring PHP's
55+
* `range($start, $end, $interval)`: values are `start ± i*|interval|`,
56+
* generated until the value crosses `end`. Equal start/end yields a
57+
* single-element buffer. The caller must reject a zero interval, an interval
58+
* whose sign disagrees with the traversal direction (for increasing ranges),
59+
* and an interval whose magnitude exceeds the span.
60+
*/
61+
void tensor_range(zval * return_value, zval * start, zval * end, zval * interval);
62+
4563
#endif

‎ext/tensor/decompositions/cholesky.zep.c‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎ext/tensor/decompositions/eigen.zep.c‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎ext/tensor/decompositions/lu.zep.c‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎ext/tensor/decompositions/svd.zep.c‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)