Added a "bulk" Linear regression operator that returns a tensor of#634
Added a "bulk" Linear regression operator that returns a tensor of#634highperformancecoder merged 4 commits intomasterfrom
Conversation
slope/intercepts, rather than the linear interpolation that the standard linear regression operator does.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughAdds a new OperationType Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
Adds a new bulkLinearRegression operation type intended to return regression parameters (slope/intercept) as a tensor, distinct from the existing linearRegression behavior.
Changes:
- Extends the
OperationTypeenum and wiring/instantiation paths to includebulkLinearRegression. - Implements a new tensor-op specialization for
bulkLinearRegression, plus units and icon rendering support. - Adds/updates a large set of web UI icon PNG assets (including
bulkLinearRegression.png) and adds equation/LaTeX/Matlab renderers for the new op.
Reviewed changes
Copilot reviewed 12 out of 64 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| schema/operationType.h | Adds bulkLinearRegression to the operation type enum. |
| schema/operationType.cc | Defines numArguments for bulkLinearRegression. |
| model/operationRS1.cc | Instantiates/exports the new operation type for the RS layer. |
| model/operation.cc | Adds units handling + icon drawing for bulkLinearRegression. |
| engine/node_matlab.cc | Adds Matlab codegen for bulkLinearRegression. |
| engine/node_latex.cc | Adds LaTeX codegen for bulkLinearRegression. |
| engine/minskyTensorOps.cc | Refactors linear regression implementation and adds bulkLinearRegression tensor op. |
| engine/equationDisplayRender.cc | Adds equation rendering for bulkLinearRegression. |
| engine/derivative.cc | Marks vector derivative as not implemented for bulkLinearRegression. |
| Makefile | Removes debug warnings from the build. |
| gui-js/apps/minsky-web/src/assets/images/icons/bulkLinearRegression.png | Adds web icon asset for the new operation. |
| gui-js/apps/minsky-web/src/assets/images/icons/zero.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/userFunction.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/time.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/tanh.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/tan.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/supremum.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/supIndex.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/sum.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/stdDev.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/slice.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/size.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/sinh.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/sin.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/shape.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/runningSum.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/runningProduct.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/runningAv.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/product.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/pow.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/polygamma.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/pi.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/percent.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/min.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/median.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/max.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/lt.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/log.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/ln.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/le.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/innerProduct.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/infimum.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/infIndex.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/inf.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/index.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/frac.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/floor.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/exp.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/euler.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/eq.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/differentiate.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/differencePlus.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/difference.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/covariance.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/cosh.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/cos.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/correlation.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/atan.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/asin.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/any.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/all.png | Adds/updates web icon asset. |
| gui-js/apps/minsky-web/src/assets/images/icons/acos.png | Adds/updates web icon asset. |
Comments suppressed due to low confidence (1)
engine/minskyTensorOps.cc:1157
- LinearRegression::setArguments() now computes
dimensionby iteratingm_hypercube.xvectorsand usingrank(), butm_hypercubeis no longer initialised fromy->hypercube()in this function. This can leavedimensionincorrect (or dependent on stale state from a previous call), breaking axis selection and the fallback x-from-xvector logic. Computedimensionfromy->hypercube()/y->rank()(or sethypercube(y->hypercube())before this block, then let derived classes override the output hypercube as needed).
{
auto& xv=m_hypercube.xvectors;
dimension=rank()>1? rank(): 0;
for (auto i=xv.begin(); i!=xv.end(); ++i)
if (i->name==args.dimension)
dimension=i-xv.begin();
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| void setArguments(const TensorPtr& y, const TensorPtr& x, | ||
| const ITensor::Args& args) override | ||
| { | ||
| LinearRegression::setArguments(y,x,args); | ||
| if (dimension>=y->rank()) | ||
| throw_error("Need to specify axis"); | ||
| auto hc=y->hypercube(); | ||
| hc.xvectors[dimension]=civita::XVector("Linear Parameters",{},{"Slope","Intercept"}); | ||
| hypercube(hc); | ||
| } |
There was a problem hiding this comment.
GeneralTensorOp::setArguments() assumes y is non-null (y->rank(), y->hypercube()), but LinearRegression::setArguments() explicitly supports !y by returning early. This override should mirror that behaviour (early return when !y) to avoid dereferencing a null tensor when the op is unwired.
engine/node_latex.cc
Outdated
| if (!arguments.empty() && !arguments[0].empty() && arguments[0][0] && | ||
| arguments.size()>1 && !arguments[1].empty() && arguments[1][0]) | ||
| return o<<"{\\mathrm{bLinReg}\\left("<<arguments[0][0]->latex()<< | ||
| ","<<arguments[1][0]<<"\\right)"; |
There was a problem hiding this comment.
In the bulkLinearRegression LaTeX renderer, the second argument is streamed as arguments[1][0] rather than rendered via ->latex(), which will output a pointer/address (and also leaves the \mathrm{...} group unbalanced because the outer { is never closed). Use arguments[1][0]->latex() and ensure the emitted string closes the outer brace (eg ...\right)}) to produce valid LaTeX.
| ","<<arguments[1][0]<<"\\right)"; | |
| ","<<arguments[1][0]->latex()<<"\\right)}"; |
engine/equationDisplayRender.cc
Outdated
| parenthesise(surf, [&](Surface& surf){ | ||
| arguments[0][0]->render(surf); | ||
| print(surf.cairo(),",",Anchor::nw); | ||
| arguments[0][1]->render(surf); |
There was a problem hiding this comment.
In bulkLinearRegression equation rendering, the second operand is rendered using arguments[0][1], but the operand existence check uses arguments[1][0] (and most other binary renderers use arguments[1][0]). This likely renders the wrong node or can go out of bounds. Render the second argument via arguments[1][0] here.
| arguments[0][1]->render(surf); | |
| arguments[1][0]->render(surf); |
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
engine/minskyTensorOps.cc (2)
1143-1148:⚠️ Potential issue | 🔴 CriticalGuard the unwired state before touching
xory.
LinearRegression::setArguments()already treats!yas valid, buttimestamp()and both derivedsetArguments()overloads still dereferencex/yunconditionally. That turns an unwired operator into a null-deref during graph construction/evaluation.🛡️ Suggested fix
@@ if (!y) { + x.reset(); + this->y.reset(); m_index.clear(); hypercube({}); return; } @@ - civita::ITensor::Timestamp timestamp() const override {return std::max(x->timestamp(), y->timestamp());} + civita::ITensor::Timestamp timestamp() const override + { + return std::max(x ? x->timestamp() : Timestamp(), + y ? y->timestamp() : Timestamp()); + } @@ LinearRegression::setArguments(y,x,args); + if (!y) return; hypercube(y->hypercube()); @@ LinearRegression::setArguments(y,x,args); + if (!y) return; if (dimension>=y->rank())Also applies to: 1211-1211, 1219-1224, 1250-1259
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@engine/minskyTensorOps.cc` around lines 1143 - 1148, The code dereferences x/y without guarding for an unwired (null) input; update timestamp(), LinearRegression::setArguments() overloads and the derived setArguments() methods to check the unwired condition (e.g., if (!y) or if (!x || !y) as appropriate) before accessing x or y and return early or skip processing (mirroring the existing LinearRegression::setArguments() behavior); ensure m_index.clear() and hypercube({}) remain where needed for the !y path and do not touch x/y when they are null to avoid null-derefs.
1151-1169:⚠️ Potential issue | 🔴 CriticalResolve the regression axis from
y->hypercube(), not from this op's current hypercube.After the refactor, this block reads
m_hypercubebefore it has been initialized fromy. On a fresh op, every named axis is ignored, so rank>1 regressions silently run on axis 0 andbulkLinearRegressionno longer rejects missing/invalid axis names.🔧 Suggested fix
@@ - { - auto& xv=m_hypercube.xvectors; - dimension=rank()>1? rank(): 0; - for (auto i=xv.begin(); i!=xv.end(); ++i) - if (i->name==args.dimension) - dimension=i-xv.begin(); - } + { + const auto& xv=y->hypercube().xvectors; + dimension=y->rank()>1? y->rank(): 0; + for (auto i=xv.begin(); i!=xv.end(); ++i) + if (i->name==args.dimension) + dimension=i-xv.begin(); + } @@ - if (rank()>1 && dimension>=rank()) return; + if (y->rank()>1 && dimension>=y->rank()) return;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@engine/minskyTensorOps.cc` around lines 1151 - 1169, The code currently resolves named axes using m_hypercube before m_hypercube has been initialized from y, causing named axes to be ignored; change the logic so you initialize or reference y's hypercube (y->hypercube() or equivalent) to determine dimension/name lookup before using m_hypercube: use y->hypercube().xvectors when searching for args.dimension, assign dimension from that hypercube, then proceed to set sumy/setArguments and the rank checks (rank()>1 && dimension>=rank()) so invalid/missing axis names are rejected as before (affecting the block around sumy.setArgument, SpreadY creation, setArguments and the subsequent x construction/bulkLinearRegression path).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@engine/equationDisplayRender.cc`:
- Around line 1053-1064: The render implementation of
OperationDAG<OperationType::bulkLinearRegression>::render is indexing the wrong
input list for the second argument: the guard checks arguments[1][0] but the
code uses arguments[0][1], which can go out of bounds; update the lambda body to
render the second item from the validated second input list (use arguments[1][1]
for the second rendered argument) and keep the existing guards (arguments,
arguments[0][0], arguments[1][0], etc.) to ensure safety.
In `@engine/minskyTensorOps.cc`:
- Around line 1253-1258: LinearRegression::setArguments inherits m_index from
y->index(), but after replacing the regression axis via hc.xvectors[...] and
calling hypercube(hc) the old linear indices are invalid; clear or rebuild
m_index so output indices match the new hypercube. Specifically, after the
hypercube(hc) call reset m_index (e.g. set empty) or recompute it from the
result hypercube/scale.index() instead of y->index(); ensure any downstream
logic uses the rebuilt m_index derived from scale.index() when producing sparse
output.
In `@engine/node_latex.cc`:
- Around line 406-413: The latex emitter for
OperationDAG<OperationType::bulkLinearRegression>::latex incorrectly streams
arguments[1][0] directly and omits the closing brace; update the return
expression to call arguments[1][0]->latex() and append the missing closing
braces so the output is something like o << "{\\mathrm{bLinReg}\\left(" <<
arguments[0][0]->latex() << "," << arguments[1][0]->latex() << "\\right)}";
ensuring parentheses and the outer '{' are properly closed.
In `@model/operation.cc`:
- Around line 518-519: The bulkLinearRegression branch incorrectly returns
m_ports[1]->units(check) for both outputs; change it to compute and return the
correct units for slope and intercept: derive slope units as units(Y)/units(X)
and intercept units as units(Y) using the existing units() accessor on input
ports (e.g., m_ports[index]->units(check)), then populate/return the two output
unit entries (matching the output port order for slope and intercept) instead of
forwarding m_ports[1]->units(check); update the case handling for
bulkLinearRegression in Operation::units (or the function containing that
switch) to construct and return the proper unit vector for both outputs.
---
Outside diff comments:
In `@engine/minskyTensorOps.cc`:
- Around line 1143-1148: The code dereferences x/y without guarding for an
unwired (null) input; update timestamp(), LinearRegression::setArguments()
overloads and the derived setArguments() methods to check the unwired condition
(e.g., if (!y) or if (!x || !y) as appropriate) before accessing x or y and
return early or skip processing (mirroring the existing
LinearRegression::setArguments() behavior); ensure m_index.clear() and
hypercube({}) remain where needed for the !y path and do not touch x/y when they
are null to avoid null-derefs.
- Around line 1151-1169: The code currently resolves named axes using
m_hypercube before m_hypercube has been initialized from y, causing named axes
to be ignored; change the logic so you initialize or reference y's hypercube
(y->hypercube() or equivalent) to determine dimension/name lookup before using
m_hypercube: use y->hypercube().xvectors when searching for args.dimension,
assign dimension from that hypercube, then proceed to set sumy/setArguments and
the rank checks (rank()>1 && dimension>=rank()) so invalid/missing axis names
are rejected as before (affecting the block around sumy.setArgument, SpreadY
creation, setArguments and the subsequent x construction/bulkLinearRegression
path).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 35797ea0-f966-44a9-a040-8d26cd0ef12d
⛔ Files ignored due to path filters (52)
gui-js/apps/minsky-web/src/assets/images/icons/acos.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/all.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/any.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/asin.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/atan.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/bulkLinearRegression.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/correlation.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/cos.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/cosh.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/covariance.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/difference.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/differencePlus.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/differentiate.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/eq.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/euler.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/exp.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/floor.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/frac.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/index.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/inf.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/infIndex.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/infimum.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/innerProduct.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/le.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/ln.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/log.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/lt.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/max.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/median.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/min.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/percent.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/pi.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/polygamma.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/pow.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/product.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/runningAv.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/runningProduct.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/runningSum.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/shape.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/sin.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/sinh.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/size.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/slice.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/stdDev.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/sum.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/supIndex.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/supremum.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/tan.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/tanh.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/time.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/userFunction.pngis excluded by!**/*.pnggui-js/apps/minsky-web/src/assets/images/icons/zero.pngis excluded by!**/*.png
📒 Files selected for processing (12)
MakefileRavelCAPIecolabengine/derivative.ccengine/equationDisplayRender.ccengine/minskyTensorOps.ccengine/node_latex.ccengine/node_matlab.ccmodel/operation.ccmodel/operationRS1.ccschema/operationType.ccschema/operationType.h
💤 Files with no reviewable changes (1)
- Makefile
…d tests Agent-Logs-Url: https://github.com/highperformancecoder/minsky/sessions/6762f0ad-cf41-452b-b6b4-3fc692881ff2 Co-authored-by: highperformancecoder <3075825+highperformancecoder@users.noreply.github.com>
…rmancecoder/minsky into feature-bulk-linear-regression
if (!y) return;guard)if (!y) return;guard)->latex()and closes the outer}arguments[1][0]instead ofarguments[0][1]vectorBulkLinearRegression: verifies output shape (2 elements: Slope/Intercept) and correct values for y=x+1matrixBulkLinearRegression: verifies output shape ({2,2}: Slope/Intercept × columns) and correct values for two regression lines📱 Kick off Copilot coding agent tasks wherever you are with GitHub Mobile, available on iOS and Android.
This change is
Summary by CodeRabbit
New Features
Bug Fixes
Chores