3
* I hereby release this code into the PUBLIC DOMAIN AS IS. There is no
4
* support, warranty, or guarantee. I will gladly accept comments, bug
5
* reports, and patches, however.
15
void F_FUNC(dodrc,DODRC)(void (*fcn)(int *n, int *m, int *np, int *nq, int *ldn, int *ldm,
16
int *ldnp, double *beta, double *xplusd, int *ifixb, int *ifixx,
17
int *ldifx, int *ideval, double *f, double *fjacb, double *fjacd,
19
int *n, int *m, int *np, int *nq, double *beta, double *y, int *ldy,
20
double *x, int *ldx, double *we, int *ldwe, int *ld2we, double *wd,
21
int *ldwd, int *ld2wd, int *ifixb, int *ifixx, int *ldifx, int *job,
22
int *ndigit, double *taufac, double *sstol, double *partol,
23
int *maxit, int *iprint, int *lunerr, int *lunrpt, double *stpb,
24
double *stpd, int *ldstpd, double *sclb, double *scld, int *ldscld,
25
double *work, int *lwork, int *iwork, int *liwork, int *info);
26
void F_FUNC(dwinf,DWINF)(int *n, int *m, int *np, int *nq, int *ldwe, int *ld2we, int *isodr,
27
int *delta, int *eps, int *xplus, int *fn, int *sd, int *vcv, int *rvar,
28
int *wss, int *wssde, int *wssep, int *rcond, int *eta, int *olmav,
29
int *tau, int *alpha, int *actrs, int *pnorm, int *rnors, int *prers,
30
int *partl, int *sstol, int *taufc, int *apsma, int *betao, int *betac,
31
int *betas, int *betan, int *s, int *ss, int *ssf, int *qraux, int *u,
32
int *fs, int *fjacb, int *we1, int *diff, int *delts, int *deltn,
33
int *t, int *tt, int *omega, int *fjacd, int *wrk1, int *wrk2,
34
int *wrk3, int *wrk4, int *wrk5, int *wrk6, int *wrk7, int *lwkmn);
35
void F_FUNC(dluno,DLUNO)(int *lun, char *fn, int fnlen);
36
void F_FUNC(dlunc,DLUNC)(int *lun);
40
/* callback to pass to DODRC; calls the Python function in the global structure |odr_global| */
41
void fcn_callback(int *n, int *m, int *np, int *nq, int *ldn, int *ldm,
42
int *ldnp, double *beta, double *xplusd, int *ifixb,
43
int *ifixx, int *ldfix, int *ideval, double *f,
44
double *fjacb, double *fjacd, int *istop)
46
PyObject *arg01, *arglist;
48
PyArrayObject *result_array = NULL;
49
PyArrayObject *pyXplusD;
51
arg01 = PyTuple_New(2);
58
pyXplusD = (PyArrayObject *) PyArray_FromDims(2, dim2, PyArray_DOUBLE);
59
memcpy(pyXplusD->data, (void *)xplusd, (*m) * (*n) * sizeof(double));
65
pyXplusD = (PyArrayObject *) PyArray_FromDims(1, dim1, PyArray_DOUBLE);
66
memcpy(pyXplusD->data, (void *)xplusd, (*n) * sizeof(double));
69
PyTuple_SetItem(arg01, 0, odr_global.pyBeta);
70
Py_INCREF(odr_global.pyBeta);
71
PyTuple_SetItem(arg01, 1, (PyObject *) pyXplusD);
72
Py_INCREF((PyObject *) pyXplusD);
74
if (odr_global.extra_args != NULL)
76
arglist = PySequence_Concat(arg01, odr_global.extra_args);
80
arglist = PySequence_Tuple(arg01); /* make a copy */
86
memcpy(((PyArrayObject *) (odr_global.pyBeta))->data, (void *)beta,
87
(*np) * sizeof(double));
89
if ((*ideval % 10) >= 1)
91
/* compute f with odr_global.fcn */
93
if (odr_global.fcn == NULL)
95
/* we don't have a function to call */
96
PYERR2(odr_error, "Function has not been initialized");
99
if ((result = PyEval_CallObject(odr_global.fcn, arglist)) == NULL)
101
PyObject *tmpobj, *str1;
103
if (PyErr_ExceptionMatches(odr_stop))
105
/* stop, don't fail */
113
tmpobj = PyObject_GetAttrString(odr_global.fcn, "func_name");
119
("Error occured while calling the Python function named ");
125
PyString_ConcatAndDel(&str1, tmpobj);
126
PyErr_SetString(odr_error, PyString_AsString(str1));
132
(PyArrayObject *) PyArray_ContiguousFromObject(result,
137
"Result from function call is not a proper array of floats.");
140
memcpy((void *)f, result_array->data, (*n) * (*nq) * sizeof(double));
141
Py_DECREF(result_array);
144
if (((*ideval) / 10) % 10 >= 1)
146
/* compute fjacb with odr_global.fjacb */
148
if (odr_global.fjacb == NULL)
150
/* we don't have a function to call */
151
PYERR2(odr_error, "Function has not been initialized");
154
if ((result = PyEval_CallObject(odr_global.fjacb, arglist)) == NULL)
156
PyObject *tmpobj, *str1;
158
if (PyErr_ExceptionMatches(odr_stop))
160
/* stop, don't fail */
168
tmpobj = PyObject_GetAttrString(odr_global.fjacb, "func_name");
174
("Error occured while calling the Python function named ");
180
PyString_ConcatAndDel(&str1, tmpobj);
181
PyErr_SetString(odr_error, PyString_AsString(str1));
187
(PyArrayObject *) PyArray_ContiguousFromObject(result,
192
"Result from function call is not a proper array of floats.");
195
if (*nq != 1 && *np != 1)
197
/* result_array should be rank-3 */
199
if (result_array->nd != 3)
201
Py_DECREF(result_array);
202
PYERR2(odr_error, "Beta Jacobian is not rank-3");
207
/* result_array should be rank-2 */
209
if (result_array->nd != 2)
211
Py_DECREF(result_array);
212
PYERR2(odr_error, "Beta Jacobian is not rank-2");
216
memcpy((void *)fjacb, result_array->data,
217
(*n) * (*nq) * (*np) * sizeof(double));
218
Py_DECREF(result_array);
222
if (((*ideval) / 100) % 10 >= 1)
224
/* compute fjacd with odr_global.fjacd */
226
if (odr_global.fjacd == NULL)
228
/* we don't have a function to call */
229
PYERR2(odr_error, "fjcad has not been initialized");
232
if ((result = PyEval_CallObject(odr_global.fjacd, arglist)) == NULL)
234
PyObject *tmpobj, *str1;
236
if (PyErr_ExceptionMatches(odr_stop))
238
/* stop, don't fail */
246
tmpobj = PyObject_GetAttrString(odr_global.fjacd, "func_name");
252
("Error occured while calling the Python function named ");
258
PyString_ConcatAndDel(&str1, tmpobj);
259
PyErr_SetString(odr_error, PyString_AsString(str1));
265
(PyArrayObject *) PyArray_ContiguousFromObject(result,
270
"Result from function call is not a proper array of floats.");
273
if (*nq != 1 && *m != 1)
275
/* result_array should be rank-3 */
277
if (result_array->nd != 3)
279
Py_DECREF(result_array);
280
PYERR2(odr_error, "xplusd Jacobian is not rank-3");
283
else if (*nq == 1 && *m != 1)
285
/* result_array should be rank-2 */
287
if (result_array->nd != 2)
289
Py_DECREF(result_array);
290
PYERR2(odr_error, "xplusd Jacobian is not rank-2");
293
else if (*nq == 1 && *m == 1)
295
/* result_array should be rank-1 */
297
if (result_array->nd != 1)
299
Py_DECREF(result_array);
300
PYERR2(odr_error, "xplusd Jacobian is not rank-1");
304
memcpy((void *)fjacd, result_array->data,
305
(*n) * (*nq) * (*m) * sizeof(double));
306
Py_DECREF(result_array);
318
Py_XDECREF(pyXplusD);
324
/* generates Python output from the raw output from DODRC */
325
PyObject *gen_output(int n, int m, int np, int nq, int ldwe, int ld2we,
326
PyArrayObject * beta, PyArrayObject * work,
327
PyArrayObject * iwork, int isodr, int info,
330
PyArrayObject *sd_beta, *cov_beta;
332
int delta, eps, xplus, fn, sd, vcv, rvar, wss, wssde, wssep, rcond;
333
int eta, olmav, tau, alpha, actrs, pnorm, rnors, prers, partl, sstol;
334
int taufc, apsma, betao, betac, betas, betan, s, ss, ssf, qraux, u;
335
int fs, fjacb, we1, diff, delts, deltn, t, tt, omega, fjacd;
336
int wrk1, wrk2, wrk3, wrk4, wrk5, wrk6, wrk7, lwkmn;
340
int dim1[1], dim2[2];
343
/* fatal error in fcn call; return NULL to propogate the exception */
348
lwkmn = work->dimensions[0];
350
F_FUNC(dwinf,DWINF)(&n, &m, &np, &nq, &ldwe, &ld2we, &isodr,
351
&delta, &eps, &xplus, &fn, &sd, &vcv, &rvar, &wss, &wssde,
352
&wssep, &rcond, &eta, &olmav, &tau, &alpha, &actrs, &pnorm,
353
&rnors, &prers, &partl, &sstol, &taufc, &apsma, &betao, &betac,
354
&betas, &betan, &s, &ss, &ssf, &qraux, &u, &fs, &fjacb, &we1,
355
&diff, &delts, &deltn, &t, &tt, &omega, &fjacd, &wrk1, &wrk2,
356
&wrk3, &wrk4, &wrk5, &wrk6, &wrk7, &lwkmn);
358
/* convert FORTRAN indices to C indices */
409
dim1[0] = beta->dimensions[0];
410
sd_beta = (PyArrayObject *) PyArray_FromDims(1, dim1, PyArray_DOUBLE);
411
dim2[0] = beta->dimensions[0];
412
dim2[1] = beta->dimensions[0];
413
cov_beta = (PyArrayObject *) PyArray_FromDims(2, dim2, PyArray_DOUBLE);
415
memcpy(sd_beta->data, (void *)((double *)(work->data) + sd),
416
np * sizeof(double));
417
memcpy(cov_beta->data, (void *)((double *)(work->data) + vcv),
418
np * np * sizeof(double));
422
retobj = Py_BuildValue("OOO", PyArray_Return(beta),
423
PyArray_Return(sd_beta),
424
PyArray_Return(cov_beta));
425
Py_DECREF((PyObject *) sd_beta);
426
Py_DECREF((PyObject *) cov_beta);
432
PyArrayObject *deltaA, *epsA, *xplusA, *fnA;
433
double res_var, sum_square, sum_square_delta, sum_square_eps;
434
double inv_condnum, rel_error;
439
("{s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l,s:l}",
440
"delta", delta, "eps", eps, "xplus", xplus, "fn", fn, "sd", sd, "sd",
441
vcv, "rvar", rvar, "wss", wss, "wssde", wssde, "wssep", wssep,
442
"rcond", rcond, "eta", eta, "olmav", olmav, "tau", tau, "alpha",
443
alpha, "actrs", actrs, "pnorm", pnorm, "rnors", rnors, "prers",
444
prers, "partl", partl, "sstol", sstol, "taufc", taufc, "apsma",
445
apsma, "betao", betao, "betac", betac, "betas", betas, "betan",
446
betan, "s", s, "ss", ss, "ssf", ssf, "qraux", qraux, "u", u, "fs",
447
fs, "fjacb", fjacb, "we1", we1, "diff", diff, "delts", delts,
448
"deltn", deltn, "t", t, "tt", tt, "omega", omega, "fjacd", fjacd,
449
"wrk1", wrk1, "wrk2", wrk2, "wrk3", wrk3, "wrk4", wrk4, "wrk5", wrk5,
450
"wrk6", wrk6, "wrk7", wrk7);
456
(PyArrayObject *) PyArray_FromDims(1, dim1, PyArray_DOUBLE);
458
(PyArrayObject *) PyArray_FromDims(1, dim1, PyArray_DOUBLE);
465
(PyArrayObject *) PyArray_FromDims(2, dim2, PyArray_DOUBLE);
467
(PyArrayObject *) PyArray_FromDims(2, dim2, PyArray_DOUBLE);
473
epsA = (PyArrayObject *) PyArray_FromDims(1, dim1, PyArray_DOUBLE);
474
fnA = (PyArrayObject *) PyArray_FromDims(1, dim1, PyArray_DOUBLE);
480
epsA = (PyArrayObject *) PyArray_FromDims(2, dim2, PyArray_DOUBLE);
481
fnA = (PyArrayObject *) PyArray_FromDims(2, dim2, PyArray_DOUBLE);
484
memcpy(deltaA->data, (void *)((double *)(work->data) + delta),
485
m * n * sizeof(double));
486
memcpy(epsA->data, (void *)((double *)(work->data) + eps),
487
nq * n * sizeof(double));
488
memcpy(xplusA->data, (void *)((double *)(work->data) + xplus),
489
m * n * sizeof(double));
490
memcpy(fnA->data, (void *)((double *)(work->data) + fn),
491
nq * n * sizeof(double));
493
res_var = *((double *)(work->data) + rvar);
494
sum_square = *((double *)(work->data) + wss);
495
sum_square_delta = *((double *)(work->data) + wssde);
496
sum_square_eps = *((double *)(work->data) + wssep);
497
inv_condnum = *((double *)(work->data) + rcond);
498
rel_error = *((double *)(work->data) + eta);
502
("OOO{s:O,s:O,s:O,s:O,s:d,s:d,s:d,s:d,s:d,s:d,s:O,s:O,s:O,s:l}",
503
PyArray_Return(beta), PyArray_Return(sd_beta),
504
PyArray_Return(cov_beta), "delta", PyArray_Return(deltaA), "eps",
505
PyArray_Return(epsA), "xplus", PyArray_Return(xplusA), "y",
506
PyArray_Return(fnA), "res_var", res_var, "sum_square", sum_square,
507
"sum_square_delta", sum_square_delta, "sum_square_eps",
508
sum_square_eps, "inv_condnum", inv_condnum, "rel_error", rel_error,
509
"work", PyArray_Return(work), "work_ind", work_ind, "iwork",
510
PyArray_Return(iwork), "info", info);
511
Py_DECREF((PyObject *) sd_beta);
512
Py_DECREF((PyObject *) cov_beta);
513
Py_DECREF((PyObject *) deltaA);
514
Py_DECREF((PyObject *) epsA);
515
Py_DECREF((PyObject *) xplusA);
516
Py_DECREF((PyObject *) fnA);
517
Py_DECREF((PyObject *) work_ind);
523
PyObject *odr(PyObject * self, PyObject * args, PyObject * kwds)
525
PyObject *fcn, *initbeta, *py, *px, *pwe = NULL, *pwd = NULL, *fjacb = NULL;
526
PyObject *fjacd = NULL, *pifixb = NULL, *pifixx = NULL;
527
PyObject *pstpb = NULL, *pstpd = NULL, *psclb = NULL, *pscld = NULL;
528
PyObject *pwork = NULL, *piwork = NULL, *extra_args = NULL;
529
int job = 0, ndigit = 0, maxit = -1, iprint = 0;
531
double taufac = 0.0, sstol = -1.0, partol = -1.0;
532
char *errfile = NULL, *rptfile = NULL;
533
int lerrfile = 0, lrptfile = 0;
534
PyArrayObject *beta = NULL, *y = NULL, *x = NULL, *we = NULL, *wd = NULL;
535
PyArrayObject *ifixb = NULL, *ifixx = NULL;
536
PyArrayObject *stpb = NULL, *stpd = NULL, *sclb = NULL, *scld = NULL;
537
PyArrayObject *work = NULL, *iwork = NULL;
538
int n, m, np, nq, ldy, ldx, ldwe, ld2we, ldwd, ld2wd, ldifx;
539
int lunerr = -1, lunrpt = -1, ldstpd, ldscld, lwork, liwork, info = 0;
540
static char *kw_list[] = { "fcn", "initbeta", "y", "x", "we", "wd", "fjacb",
541
"fjacd", "extra_args", "ifixb", "ifixx", "job", "iprint", "errfile",
542
"rptfile", "ndigit", "taufac", "sstol", "partol",
543
"maxit", "stpb", "stpd", "sclb", "scld", "work",
544
"iwork", "full_output", NULL
548
int dim1[1], dim2[2], dim3[3];
549
int implicit; /* flag for implicit model */
554
if (!PyArg_ParseTuple(args, "OOOO|OOOOOOOllz#z#ldddlOOOOOOi:odr",
555
&fcn, &initbeta, &py, &px, &pwe, &pwd,
556
&fjacb, &fjacd, &extra_args, &pifixb, &pifixx,
557
&job, &iprint, &errfile, &lerrfile, &rptfile,
558
&lrptfile, &ndigit, &taufac, &sstol, &partol,
559
&maxit, &pstpb, &pstpd, &psclb, &pscld, &pwork,
560
&piwork, &full_output))
567
if (!PyArg_ParseTupleAndKeywords(args, kwds,
568
"OOOO|OOOOOOOllz#z#ldddlOOOOOOi:odr",
569
kw_list, &fcn, &initbeta, &py, &px,
570
&pwe, &pwd, &fjacb, &fjacd,
571
&extra_args, &pifixb, &pifixx, &job,
572
&iprint, &errfile, &lerrfile, &rptfile,
573
&lrptfile, &ndigit, &taufac, &sstol,
574
&partol, &maxit, &pstpb, &pstpd,
575
&psclb, &pscld, &pwork, &piwork,
582
/* Check the validity of all arguments */
584
if (!PyCallable_Check(fcn))
586
PYERR(PyExc_TypeError, "fcn must be callable");
588
if (!PySequence_Check(initbeta))
590
PYERR(PyExc_TypeError, "initbeta must be a sequence");
592
if (!PySequence_Check(py) && !PyInt_Check(py))
594
PYERR(PyExc_TypeError,
595
"y must be a sequence or integer (if model is implicit)");
597
if (!PySequence_Check(px))
599
PYERR(PyExc_TypeError, "x must be a sequence");
601
if (pwe != NULL && !PySequence_Check(pwe) && !PyNumber_Check(pwe))
603
PYERR(PyExc_TypeError, "we must be a sequence or a number");
605
if (pwd != NULL && !PySequence_Check(pwd) && !PyNumber_Check(pwd))
607
PYERR(PyExc_TypeError, "wd must be a sequence or a number");
609
if (fjacb != NULL && !PyCallable_Check(fjacb))
611
PYERR(PyExc_TypeError, "fjacb must be callable");
613
if (fjacd != NULL && !PyCallable_Check(fjacd))
615
PYERR(PyExc_TypeError, "fjacd must be callable");
617
if (extra_args != NULL && !PySequence_Check(extra_args))
619
PYERR(PyExc_TypeError, "extra_args must be a sequence");
621
if (pifixx != NULL && !PySequence_Check(pifixx))
623
PYERR(PyExc_TypeError, "ifixx must be a sequence");
625
if (pifixb != NULL && !PySequence_Check(pifixb))
627
PYERR(PyExc_TypeError, "ifixb must be a sequence");
629
if (pstpb != NULL && !PySequence_Check(pstpb))
631
PYERR(PyExc_TypeError, "stpb must be a sequence");
633
if (pstpd != NULL && !PySequence_Check(pstpd))
635
PYERR(PyExc_TypeError, "stpd must be a sequence");
637
if (psclb != NULL && !PySequence_Check(psclb))
639
PYERR(PyExc_TypeError, "sclb must be a sequence");
641
if (pscld != NULL && !PySequence_Check(pscld))
643
PYERR(PyExc_TypeError, "scld must be a sequence");
645
if (pwork != NULL && !PyArray_Check(pwork))
647
PYERR(PyExc_TypeError, "work must be an array");
649
if (piwork != NULL && !PyArray_Check(piwork))
651
PYERR(PyExc_TypeError, "iwork must be an array");
654
/* start processing the arguments and check for errors on the way */
656
/* check for implicit model */
658
implicit = (job % 10 == 1);
663
(PyArrayObject *) PyArray_CopyFromObject(py, PyArray_DOUBLE, 1,
666
PYERR(PyExc_ValueError,
667
"y could not be made into a suitable array");
669
n = y->dimensions[y->nd - 1]; /* pick the last dimension */
671
(PyArrayObject *) PyArray_CopyFromObject(px, PyArray_DOUBLE, 1,
674
PYERR(PyExc_ValueError,
675
"x could not be made into a suitable array");
677
if (n != x->dimensions[x->nd - 1])
679
PYERR(PyExc_ValueError,
680
"x and y don't have matching numbers of observations");
688
nq = y->dimensions[0];
694
{ /* we *do* have an implicit model */
696
nq = (int)PyInt_AsLong(py);
699
/* initialize y to a dummy array; never referenced */
700
y = (PyArrayObject *) PyArray_FromDims(1, dim1, PyArray_DOUBLE);
703
(PyArrayObject *) PyArray_CopyFromObject(px, PyArray_DOUBLE, 1,
706
PYERR(PyExc_ValueError,
707
"x could not be made into a suitable array");
710
n = x->dimensions[x->nd - 1];
720
m = x->dimensions[0];
724
(PyArrayObject *) PyArray_CopyFromObject(initbeta, PyArray_DOUBLE, 1,
727
PYERR(PyExc_ValueError,
728
"initbeta could not be made into a suitable array");
730
np = beta->dimensions[0];
736
we = (PyArrayObject *) PyArray_FromDims(1, dim1, PyArray_DOUBLE);
737
((double *)(we->data))[0] = -1.0;
739
else if (PyNumber_Check(pwe) && !PyArray_Check(pwe))
741
/* we is a single weight, set the first value of we to -pwe */
745
tmp = PyNumber_Float(pwe);
747
PYERR(PyExc_ValueError, "could not convert we to a suitable array");
748
val = PyFloat_AsDouble(tmp);
754
we = (PyArrayObject *) PyArray_FromDims(3, dim3, PyArray_DOUBLE);
757
((double *)(we->data))[0] = val;
761
((double *)(we->data))[0] = -val;
765
else if (PySequence_Check(pwe))
767
/* we needs to be turned into an array */
770
(PyArrayObject *) PyArray_CopyFromObject(pwe, PyArray_DOUBLE, 1,
773
PYERR(PyExc_ValueError, "could not convert we to a suitable array");
776
if (we->nd == 1 && nq == 1)
782
else if (we->nd == 1 && we->dimensions[0] == nq)
784
/* we is a rank-1 array with diagonal weightings to be broadcast
785
* to all observations */
789
else if (we->nd == 3 && we->dimensions[0] == nq
790
&& we->dimensions[1] == nq && we->dimensions[2] == 1)
792
/* we is a rank-3 array with the covariant weightings
793
to be broadcast to all observations */
797
else if (we->nd == 2 && we->dimensions[0] == nq
798
&& we->dimensions[1] == nq)
800
/* we is a rank-2 array with the full covariant weightings
801
to be broadcast to all observations */
806
else if (we->nd == 2 && we->dimensions[0] == nq
807
&& we->dimensions[1] == n)
809
/* we is a rank-2 array with the diagonal elements of the
810
covariant weightings for each observation */
814
else if (we->nd == 3 && we->dimensions[0] == nq
815
&& we->dimensions[1] == nq && we->dimensions[2] == n)
817
/* we is the full specification of the covariant weights
818
for each observation */
824
PYERR(PyExc_ValueError, "could not convert we to a suitable array");
833
wd = (PyArrayObject *) PyArray_FromDims(1, dim1, PyArray_DOUBLE);
834
((double *)(wd->data))[0] = -1.0;
836
else if (PyNumber_Check(pwd) && !PyArray_Check(pwd))
838
/* wd is a single weight, set the first value of wd to -pwd */
842
tmp = PyNumber_Float(pwd);
844
PYERR(PyExc_ValueError, "could not convert wd to a suitable array");
845
val = PyFloat_AsDouble(tmp);
851
wd = (PyArrayObject *) PyArray_FromDims(3, dim3, PyArray_DOUBLE);
852
((double *)(wd->data))[0] = -val;
855
else if (PySequence_Check(pwd))
857
/* wd needs to be turned into an array */
860
(PyArrayObject *) PyArray_CopyFromObject(pwd, PyArray_DOUBLE, 1,
863
PYERR(PyExc_ValueError, "could not convert wd to a suitable array");
866
if (wd->nd == 1 && m == 1)
871
else if (wd->nd == 1 && wd->dimensions[0] == m)
873
/* wd is a rank-1 array with diagonal weightings to be broadcast
874
* to all observations */
879
else if (wd->nd == 3 && wd->dimensions[0] == m
880
&& wd->dimensions[1] == m && wd->dimensions[2] == 1)
882
/* wd is a rank-3 array with the covariant wdightings
883
to be broadcast to all observations */
887
else if (wd->nd == 2 && wd->dimensions[0] == m
888
&& wd->dimensions[1] == m)
890
/* wd is a rank-2 array with the full covariant weightings
891
to be broadcast to all observations */
896
else if (wd->nd == 2 && wd->dimensions[0] == m
897
&& wd->dimensions[1] == n)
899
/* wd is a rank-2 array with the diagonal elements of the
900
covariant weightings for each observation */
904
else if (wd->nd == 3 && wd->dimensions[0] == m
905
&& wd->dimensions[1] == m && wd->dimensions[2] == n)
907
/* wd is the full specification of the covariant weights
908
for each observation */
914
PYERR(PyExc_ValueError, "could not convert wd to a suitable array");
923
ifixb = (PyArrayObject *) PyArray_FromDims(1, dim1, PyArray_LONG);
924
*(int *)(ifixb->data) = -1; /* set first element negative */
928
/* pifixb is a sequence as checked before */
931
(PyArrayObject *) PyArray_CopyFromObject(pifixb, PyArray_LONG, 1,
934
PYERR(PyExc_ValueError,
935
"could not convert ifixb to a suitable array");
938
if (ifixb->dimensions[0] != np)
940
PYERR(PyExc_ValueError,
941
"could not convert ifixb to a suitable array");
949
ifixx = (PyArrayObject *) PyArray_FromDims(2, dim2, PyArray_LONG);
950
*(int *)(ifixx->data) = -1; /* set first element negative */
955
/* pifixx is a sequence as checked before */
958
(PyArrayObject *) PyArray_CopyFromObject(pifixx, PyArray_LONG, 1,
961
PYERR(PyExc_ValueError,
962
"could not convert ifixx to a suitable array");
965
if (ifixx->nd == 1 && ifixx->dimensions[0] == m)
969
else if (ifixx->nd == 1 && ifixx->dimensions[0] == n && m == 1)
973
else if (ifixx->nd == 2 && ifixx->dimensions[0] == m
974
&& ifixx->dimensions[1] == n)
980
PYERR(PyExc_ValueError,
981
"could not convert ifixx to a suitable array");
987
/* call FORTRAN's OPEN to open the file with a logical unit of 18 */
989
F_FUNC(dluno,DLUNO)(&lunerr, errfile, lerrfile);
994
/* call FORTRAN's OPEN to open the file with a logical unit of 19 */
996
F_FUNC(dluno,DLUNO)(&lunrpt, rptfile, lrptfile);
1002
stpb = (PyArrayObject *) PyArray_FromDims(1, dim1, PyArray_DOUBLE);
1003
*(double *)(stpb->data) = 0.0;
1005
else /* pstpb is a sequence */
1008
(PyArrayObject *) PyArray_CopyFromObject(pstpb, PyArray_DOUBLE, 1,
1010
|| stpb->dimensions[0] != np)
1012
PYERR(PyExc_ValueError,
1013
"could not convert stpb to a suitable array");
1021
stpd = (PyArrayObject *) PyArray_FromDims(2, dim2, PyArray_DOUBLE);
1022
*(double *)(stpd->data) = 0.0;
1028
(PyArrayObject *) PyArray_CopyFromObject(pstpd, PyArray_DOUBLE, 1,
1031
PYERR(PyExc_ValueError,
1032
"could not convert stpb to a suitable array");
1035
if (stpd->nd == 1 && stpd->dimensions[0] == m)
1039
else if (stpd->nd == 1 && stpd->dimensions[0] == n && m == 1)
1043
else if (stpd->nd == 2 && stpd->dimensions[0] == n &&
1044
stpd->dimensions[1] == m)
1053
sclb = (PyArrayObject *) PyArray_FromDims(1, dim1, PyArray_DOUBLE);
1054
*(double *)(sclb->data) = 0.0;
1056
else /* psclb is a sequence */
1059
(PyArrayObject *) PyArray_CopyFromObject(psclb, PyArray_DOUBLE, 1,
1061
|| sclb->dimensions[0] != np)
1063
PYERR(PyExc_ValueError,
1064
"could not convert sclb to a suitable array");
1072
scld = (PyArrayObject *) PyArray_FromDims(2, dim2, PyArray_DOUBLE);
1073
*(double *)(scld->data) = 0.0;
1079
(PyArrayObject *) PyArray_CopyFromObject(pscld, PyArray_DOUBLE, 1,
1082
PYERR(PyExc_ValueError,
1083
"could not convert stpb to a suitable array");
1086
if (scld->nd == 1 && scld->dimensions[0] == m)
1090
else if (scld->nd == 1 && scld->dimensions[0] == n && m == 1)
1094
else if (scld->nd == 2 && scld->dimensions[0] == n &&
1095
scld->dimensions[1] == m)
1106
18 + 11 * np + np * np + m + m * m + 4 * n * nq + 6 * n * m +
1107
2 * n * nq * np + 2 * n * nq * m + nq * nq + 5 * nq + nq * (np + m) +
1117
18 + 11 * np + np * np + m + m * m + 4 * n * nq + 2 * n * m +
1118
2 * n * nq * np + 5 * nq + nq * (np + m) + ldwe * ld2we * nq;
1123
liwork = 20 + np + nq * (np + m);
1125
if ((job / 10000) % 10 >= 1)
1127
/* fit is a restart, make sure work and iwork are input */
1129
if (pwork == NULL || piwork == NULL)
1131
PYERR(PyExc_ValueError,
1132
"need to input work and iwork arrays to restart");
1136
if ((job / 1000) % 10 >= 1)
1138
/* delta should be supplied, make sure the user does */
1142
PYERR(PyExc_ValueError,
1143
"need to input work array for delta initialization");
1150
(PyArrayObject *) PyArray_CopyFromObject(pwork, PyArray_DOUBLE, 1,
1153
PYERR(PyExc_ValueError,
1154
"could not convert work to a suitable array");
1156
if (work->dimensions[0] < lwork)
1158
printf("%d %d\n", work->dimensions[0], lwork);
1159
PYERR(PyExc_ValueError, "work is too small");
1164
/* initialize our own work array */
1166
work = (PyArrayObject *) PyArray_FromDims(1, dim1, PyArray_DOUBLE);
1172
(PyArrayObject *) PyArray_CopyFromObject(piwork, PyArray_LONG, 1,
1175
PYERR(PyExc_ValueError,
1176
"could not convert iwork to a suitable array");
1179
if (iwork->dimensions[0] < liwork)
1181
PYERR(PyExc_ValueError, "iwork is too small");
1186
/* initialize our own iwork array */
1188
iwork = (PyArrayObject *) PyArray_FromDims(1, dim1, PyArray_LONG);
1191
/* check if what JOB requests can be done with what the user has
1192
input into the function */
1194
if ((job / 10) % 10 >= 2)
1196
/* derivatives are supposed to be supplied */
1198
if (fjacb == NULL || fjacd == NULL)
1200
PYERR(PyExc_ValueError,
1201
"need fjacb and fjacd to calculate derivatives");
1205
/* setup the global data for the callback */
1206
odr_global.fcn = fcn;
1208
odr_global.fjacb = fjacb;
1210
odr_global.fjacd = fjacd;
1212
odr_global.pyBeta = (PyObject *) beta;
1214
odr_global.extra_args = extra_args;
1215
Py_XINCREF(extra_args);
1217
/* now call DODRC */
1218
F_FUNC(dodrc,DODRC)(fcn_callback, &n, &m, &np, &nq, (double *)(beta->data),
1219
(double *)(y->data), &ldy, (double *)(x->data), &ldx,
1220
(double *)(we->data), &ldwe, &ld2we,
1221
(double *)(wd->data), &ldwd, &ld2wd,
1222
(int *)(ifixb->data), (int *)(ifixx->data), &ldifx,
1223
&job, &ndigit, &taufac, &sstol, &partol, &maxit,
1224
&iprint, &lunerr, &lunrpt,
1225
(double *)(stpb->data), (double *)(stpd->data), &ldstpd,
1226
(double *)(sclb->data), (double *)(scld->data), &ldscld,
1227
(double *)(work->data), &lwork, (int *)(iwork->data), &liwork,
1230
result = gen_output(n, m, np, nq, ldwe, ld2we,
1231
beta, work, iwork, isodr, info, full_output);
1234
PYERR(PyExc_RuntimeError, "could not generate output");
1238
F_FUNC(dlunc,DLUNC)(&lunerr);
1242
F_FUNC(dlunc,DLUNC)(&lunrpt);
1245
Py_DECREF(odr_global.fcn);
1246
Py_XDECREF(odr_global.fjacb);
1247
Py_XDECREF(odr_global.fjacd);
1248
Py_DECREF(odr_global.pyBeta);
1249
Py_XDECREF(odr_global.extra_args);
1251
odr_global.fcn = odr_global.fjacb = odr_global.fjacd = odr_global.pyBeta =
1252
odr_global.extra_args = NULL;
1275
F_FUNC(dlunc,DLUNC)(&lunerr);
1279
F_FUNC(dlunc,DLUNC)(&lunrpt);
1299
static void check_args(int n, int m, int np, int nq,
1300
PyArrayObject * beta,
1301
PyArrayObject * y, int ldy,
1302
PyArrayObject * x, int ldx,
1303
PyArrayObject * we, int ldwe, int ld2we,
1304
PyArrayObject * wd, int ldwd, int ld2wd,
1305
PyArrayObject * ifixb, PyArrayObject * ifixx,
1306
int ldifx, int job, int ndigit, double taufac,
1307
double sstol, double partol, int maxit,
1308
PyArrayObject * stpb, PyArrayObject * stpd,
1309
int ldstpd, PyArrayObject * sclb,
1310
PyArrayObject * scld, int ldscld,
1311
PyArrayObject * work, int lwork,
1312
PyArrayObject * iwork, int liwork, int info)
1314
PyObject *printdict;
1318
("{s:l,s:l,s:l,s:l,s:O,s:O,s:l,s:O,s:l,s:O,s:l,s:l,s:O,s:l,s:l,s:O,s:O,s:l,s:l,s:l,s:d,s:d,s:d,s:l,s:O,s:O,s:l,s:O,s:O,s:l,s:O,s:l,s:O,s:l,s:l}",
1319
"n", n, "m", m, "np", np, "nq", nq, "beta", (PyObject *) beta, "y",
1320
(PyObject *) y, "ldy", ldy, "x", (PyObject *) x, "ldx", ldx, "we",
1321
(PyObject *) we, "ldwe", ldwe, "ld2we", ld2we, "wd", (PyObject *) wd,
1322
"ldwd", ldwd, "ld2wd", ld2wd, "ifixb", (PyObject *) ifixb, "ifixx",
1323
(PyObject *) ifixx, "ldifx", ldifx, "job", job, "ndigit", ndigit,
1324
"taufac", taufac, "sstol", sstol, "partol", partol, "maxit", maxit,
1325
"stpb", (PyObject *) stpb, "stpd", (PyObject *) stpd, "ldstpd", ldstpd,
1326
"sclb", (PyObject *) sclb, "scld", (PyObject *) scld, "ldscld", ldscld,
1327
"work", (PyObject *) work, "lwork", lwork, "iwork", (PyObject *) iwork,
1328
"liwork", liwork, "info", info);
1329
if (printdict == NULL)
1335
PyObject_Print(printdict, stdout, Py_PRINT_RAW);
1337
Py_XDECREF(printdict);
1340
static char odr__doc__[] =
1341
"odr(fcn, beta0, y, x,\nwe=None, wd=None, fjacb=None, fjacd=None,\nextra_args=None, ifixx=None, ifixb=None, job=0, iprint=0,\nerrfile=None, rptfile=None, ndigit=0,\ntaufac=0.0, sstol=-1.0, partol=-1.0,\nmaxit=-1, stpb=None, stpd=None,\nsclb=None, scld=None, work=None, iwork=None,\nfull_output=0)";
1343
static PyMethodDef methods[] = {
1344
{"odr", (PyCFunction) odr, METH_VARARGS | METH_KEYWORDS, odr__doc__},
1348
PyMODINIT_FUNC init__odrpack(void)
1354
m = Py_InitModule("__odrpack", methods);
1355
d = PyModule_GetDict(m);
1356
odr_error = PyErr_NewException("odr.odrpack.odr_error", NULL, NULL);
1357
odr_stop = PyErr_NewException("odr.odrpack.odr_stop", NULL, NULL);
1358
PyDict_SetItemString(d, "odr_error", odr_error);
1359
PyDict_SetItemString(d, "odr_stop", odr_stop);