int main(int argc, char **argv) {
  wbArg_t args;
  int inputLength;
  float *hostInput1;
  float *hostInput2;
  float *hostOutput;
  //float *deviceInput1;
  //float *deviceInput2;
  //float *deviceOutput;

  args = wbArg_read(argc, argv);

  wbTime_start(Generic, "Importing data and creating memory on host");
  hostInput1 = (float *)wbImport(wbArg_getInputFile(args, 0), &inputLength);
  hostInput2 = (float *)wbImport(wbArg_getInputFile(args, 1), &inputLength);
  hostOutput = (float *)malloc(inputLength * sizeof(float));
  wbTime_stop(Generic, "Importing data and creating memory on host");

  wbLog(TRACE, "The input length is ", inputLength);
	vecadd(hostInput1, hostInput2, hostOutput, inputLength);
  wbSolution(args, hostOutput, inputLength);

  free(hostInput1);
  free(hostInput2);
  free(hostOutput);

  return 0;
}
Exemple #2
0
static struct uniform *get_uniform(struct brush *b, const char *n)
{
    struct uniform *u = NULL;

    /* Ensure that the uniform vector exists. */

    if (b->uniform == NULL)
        b->uniform = vecnew(4, sizeof (struct uniform));

    if (b->uniform)
    {
        int i;

        /* Search for an existing uniform of the given name. */

        for (i = 0; i < vecnum(b->uniform); ++i)
            if (!strcmp(((struct uniform *) vecget(b->uniform, i))->name, n))
                return   (struct uniform *) vecget(b->uniform, i);

        /* This uniform does not exist.  Create it. */

        if ((u = (struct uniform *) vecget(b->uniform, vecadd(b->uniform))))
        {
            u->name = memdup(n, 1, strlen(n) + 1);
            u->rows = 0;
            u->cols = 0;
            u->indx = 0;
            u->vals = NULL;
        }
    }
    return u;
}
Exemple #3
0
//
// Evaluate a point on the circle given the swivel angle 
//
void SRS::evaluate_circle(float angle, float p[3])
{
#if 1
    evalcircle(c, u, v, radius, angle, p);
#else
    // p = o + r*cos(f)*u + r*sin(f)*v

    float temp[3];

    cpvector(p, c);
    vecscalarmult(temp, u, radius*cos(angle));
    vecadd(p, p, temp);
    vecscalarmult(temp, v, radius*sin(angle));
    vecadd(p, p, temp);
#endif
}
Exemple #4
0
static void patrol(Enemy *e, Player *p, Zone *z){
	double wx = e->ai.mv.x;
	double bw = e->body.bbox.b.x - e->body.bbox.a.x;
	double s = wx < 0 ? -1 : 1;

	Rect nextlow = {
		vecadd(e->body.bbox.a, (Point){s*bw,32}),
		vecadd(e->body.bbox.b, (Point){s*bw,32})
	};
	if(!(lvlmajorblk(z->lvl, nextlow).flags & Tcollide) || e->body.bbox.a.x == e->ai.lastp.x)
		e->ai.mv.x = -wx;

	e->ai.lastp = e->body.bbox.a;

	e->body.vel.x = e->ai.mv.x;
}
Exemple #5
0
void recv_create_object(void)
{
    /* Unpack the object header. */

    int i = new_object();
    int n = recv_index();

    int j, k;

    struct object      *o = get_object(i);
    struct object_mesh *m = NULL;

    o->count = 1;

    /* Unpack the vertices and meshes. */

    o->vv = recv_vector();
    o->mv = vecnew(n, sizeof (struct object_mesh));

    for (j = 0; j < n; ++j)
        if ((k = vecadd(o->mv)) >= 0)
        {
            m = (struct object_mesh *) vecget(o->mv, k);

            m->brush = recv_index();
            m->fv    = recv_vector();
            m->ev    = recv_vector();
        }

    /* Encapsulate this object in an entity. */

    recv_create_entity();
}
Exemple #6
0
inline void evalcircle(const float c[3],
		       const float u[3],
		       const float v[3],
		       float radius,
		       float angle,
		       float p[3])
{
    // p = o + r*cos(f)*u + r*sin(f)*v

    float temp[3];

    cpvector(p, c);
    vecscalarmult(temp, (float*)u, radius*_cos(angle));
    vecadd(p, p, temp);
    vecscalarmult(temp, (float*)v, radius*_sin(angle));
    vecadd(p, p, temp);
}
Exemple #7
0
static inline void addImpulseAtOffset(vec3* vel, vec3* angVel, float invMass, float invInertia, const vec3* offset, const vec3* impulse)
{
    vec3 tmp;
	vecaddscale(vel, vel, impulse, invMass);
    veccross(&tmp, offset, impulse);
	vecscale(&tmp, &tmp, invInertia);
	vecadd(angVel, angVel, &tmp);
}
Exemple #8
0
static vec3 getPointVel(Chassis* c, const vec3* offset)
{
	// offset is in world space

	vec3 v;
	veccross(&v, &c->angVel, offset);
	vecadd(&v, &v, &c->vel);
	return v;
}
Exemple #9
0
static int new_object(void)
{
    int i, n = vecnum(object);

    for (i = 0; i < n; ++i)
        if (get_object(i)->count == 0)
            return i;

    return vecadd(object);
}
Exemple #10
0
static void read_v(const char *line)
{
    int i;

    if ((i = vecadd(_vv)) >= 0)
    {
        struct vec3 *vp = (struct vec3 *) vecget(_vv, i);
        sscanf(line, "%f %f %f", &vp->x, &vp->y, &vp->z);
    }
}
Exemple #11
0
static int new_sprite(void)
{
    int i, n = vecnum(sprite);

    for (i = 0; i < n; ++i)
        if (get_sprite(i)->count == 0)
            return i;

    return vecadd(sprite);
}
Exemple #12
0
static int new_camera(void)
{
    int i, n = vecnum(camera);

    for (i = 0; i < n; ++i)
        if (get_camera(i)->count == 0)
            return i;

    return vecadd(camera);
}
Exemple #13
0
static int new_brush(void)
{
    int i, n = vecnum(brush);

    for (i = 0; i < n; ++i)
        if (get_brush(i)->count == 0)
            return i;

    return vecadd(brush);
}
Exemple #14
0
static void read_vt(const char *line)
{
    int i;

    if ((i = vecadd(_uv)) >= 0)
    {
        struct vec2 *up = (struct vec2 *) vecget(_uv, i);
        sscanf(line, "%f %f", &up->u, &up->v);
    }
}
Exemple #15
0
static int new_galaxy(void)
{
    int i, n = vecnum(galaxy);

    for (i = 0; i < n; ++i)
        if (get_galaxy(i)->count == 0)
            return i;

    return vecadd(galaxy);
}
Exemple #16
0
static int create_mesh(int i)
{
    int j;

    if ((j = vecadd(get_object(i)->mv)) >= 0)
    {
        struct object_mesh *m = get_object_mesh(i, j);

        m->fv = vecnew(0, sizeof (struct object_face));
        m->ev = vecnew(0, sizeof (struct object_edge));
    }
    return j;
}
Exemple #17
0
static void read_face_vertices(vector_t vv, const char *line)
{
    const char *c = line;
    int dc;
    int vj, vc = vecnum(_vv);
    int uj, uc = vecnum(_uv);
    int nj, nc = vecnum(_nv);
    int i;

    /* Scan down the face string recording index set specifications. */

    while ((dc = read_face_indices(c, &vj, &uj, &nj)))
        if ((i = vecadd(vv)) >= 0)
        {
            struct object_vert *v = (struct object_vert *) vecget(vv, i);

            /* Convert a face index to a vector index. */

            int ui = (uj > 0) ? uj - 1 : uj + uc;
            int ni = (nj > 0) ? nj - 1 : nj + nc;
            int vi = (vj > 0) ? vj - 1 : vj + vc;

            /* Locate the indexed values in the vector caches. */

            struct vec2 *up = (0 <= ui && ui < uc) ? vecget(_uv, ui) : NULL;
            struct vec3 *np = (0 <= ni && ni < nc) ? vecget(_nv, ni) : NULL;
            struct vec3 *vp = (0 <= vi && vi < vc) ? vecget(_vv, vi) : NULL;

            /* Initialize the new vertex, defaulting on bad input. */

            v->u[0] = up ? up->u : 0.0f;
            v->u[1] = up ? up->v : 0.0f;

            v->n[0] = np ? np->x : 0.0f;
            v->n[1] = np ? np->y : 0.0f;
            v->n[2] = np ? np->z : 1.0f;

            v->v[0] = vp ? vp->x : 0.0f;
            v->v[1] = vp ? vp->y : 0.0f;
            v->v[2] = vp ? vp->z : 0.0f;

            /* Note bad indices. */

            if (uj && !up) uerr++;
            if (nj && !np) nerr++;
            if (vj && !vp) verr++;

            c += dc;
        }
}
Exemple #18
0
static int create_vert(int i)
{
    int j;

    if ((j = vecadd(get_object(i)->vv)) >= 0)
    {
        struct object_vert *p = get_object_vert(i, j);

        p->n[0] = 0.0;
        p->n[0] = 0.0;
        p->n[1] = 1.0;

        get_object(i)->aabb_state = 0;
    }
    return j;
}
Exemple #19
0
static void generateQuarterCurve(vec3* out, const vec3* p, const vec3* x, const vec3* y, int N, float gamma=1.f)
{
	if (N>1)
	{
		const float dAlpha = PI * 0.5f / float(N-1);
		float alpha = 0.f;
		vec3* v = out;
		vecadd(v, p, x);
		for (int i=1; i<N; i++)
		{
			v++;
			alpha += dAlpha;
			vecaddscale(v, p, x, powf(cosf(alpha),gamma));
			vecaddscale(v, v, y, powf(sinf(alpha),gamma));
		}
	}
}
Exemple #20
0
static void read_edge_vertices(vector_t vv, const char *line)
{
    const char *c = line;
    int dc;
    int vj, vc = vecnum(_vv);
    int tj, tc = vecnum(_uv);
    int i;

    /* Scan down the face string recording index set specifications. */

    while ((dc = read_edge_indices(c, &vj, &tj)))
        if ((i = vecadd(vv)) >= 0)
        {
            struct object_vert *v = (struct object_vert *) vecget(vv, i);

            /* Convert an edge index to a vector index. */

            int ui = (tj > 0) ? tj - 1 : tj + tc;
            int vi = (vj > 0) ? vj - 1 : vj + vc;

            /* Locate the indexed values in the vector caches. */

            struct vec2 *up = (0 <= ui && ui < tc) ? vecget(_uv, ui) : NULL;
            struct vec3 *vp = (0 <= vi && vi < vc) ? vecget(_vv, vi) : NULL;

            /* Initialize the new vertex, defaulting on bad input. */

            v->u[0] = up ? up->u : 0.0f;
            v->u[1] = up ? up->v : 0.0f;

            v->n[0] = 0.0f;
            v->n[1] = 0.0f;
            v->n[2] = 1.0f;

            v->v[0] = vp ? vp->x : 0.0f;
            v->v[1] = vp ? vp->y : 0.0f;
            v->v[2] = vp ? vp->z : 0.0f;

            /* Note bad indices. */

            if (tj && !up) uerr++;
            if (vj && !vp) verr++;

            c += dc;
        }
}
Exemple #21
0
void SRS::SetAimGoal(const float goal[3],
		     const float ax[3],
		     float flex_angle)
{
    float s[3];

    cpvector(ee, goal);
    cpvector(axis, ax);
    get_translation(T, p_r1);
    get_translation(S, s);

    get_aim_circle_equation(goal, 
	    axis, p_r1, s, proj_axis, flex_angle, c, u, v, radius);

    rotation_principal_axis_to_matrix('y', flex_angle, Ry);
    vecmult(ee_r1, (float*)s, Ry); 
    vecadd(ee_r1, ee_r1, (float*)p_r1);
}
Exemple #22
0
static void doCorrection3(Chassis* c, const vec3* worldOffset, const vec3* axis, float requiredVelocityChange, float linearRatio)
{
	const float u = 1.f - linearRatio;
	// Add half to the linear
    vec3 tmp;
	vecaddscale(&c->vel, &c->vel, axis, requiredVelocityChange*linearRatio);

	// Add the other half to the angular
	vec3 cross;
	veccross(&cross, worldOffset, axis);
	veccross(&cross, &cross, worldOffset);
	float angularResponse = vecdot(axis, &cross);
	float angVelChange = requiredVelocityChange / angularResponse;

	vec3 impulse;
	vecscale(&impulse, axis, angVelChange*u);
	veccross(&tmp, worldOffset, &impulse);
	vecadd(&c->angVel, &c->angVel, &tmp);
}
Exemple #23
0
static struct object_mesh *read_usemtl(vector_t mv, const char *line,
                                                    const char *file)
{
    int i;

    if ((i = vecadd(mv)) >= 0)
    {
        struct object_mesh *m = (struct object_mesh *) vecget(mv, i);

        if (line)
            m->brush = send_create_brush(file, parse_name(line));
        else
            m->brush = 0;

        m->fv = vecnew(0, sizeof (struct object_face));
        m->ev = vecnew(0, sizeof (struct object_edge));

        return m;
    }
    return NULL;
}
Exemple #24
0
static void read_l(vector_t vv, vector_t ev, const char *line)
{
    int i, i0, i1, j;

    /* Scan down the edge string recording index set specifications. */

    i0 = vecnum(vv);
    read_edge_vertices(vv, line);
    i1 = vecnum(vv);

    /* Convert our N new vertices into N-1 new edges. */

    for (i = i0; i < i1 - 1; ++i)
        if ((j = vecadd(ev)) >= 0)
        {
            struct object_edge *e = (struct object_edge *) vecget(ev, j);
                
            e->vi[0] = i;
            e->vi[1] = i + 1;
        }
}
Exemple #25
0
static void read_f(vector_t vv, vector_t fv, const char *line)
{
    int i, i0, i1, j;

    /* Scan down the face string recording index set specifications. */

    i0 = vecnum(vv);
    read_face_vertices(vv, line);
    i1 = vecnum(vv);

    /* Convert our N new vertices into N-2 new triangles. */

    for (i = i0; i < i1 - 2; ++i)
        if ((j = vecadd(fv)) >= 0)
        {
            struct object_face *f = (struct object_face *) vecget(fv, j);
         
            f->vi[0] = i0;
            f->vi[1] = i + 1;
            f->vi[2] = i + 2;
        }
}
Exemple #26
0
static void draw(Scrn *s, Gfx *g){
	extern char *statname[];

	Statup *sup = s->data;

	gfxclear(g, (Color){ 127, 200, 255 });

	enum { Bufsz = 256 };
	char buf[Bufsz];

	int mh = TxtSzMedium/2;
	int Pad = 4;
	Point sloc = { Pad, Pad };
	for(int i = StatHp; i < StatMax; i++){
		Meter meter = {
			.base = sup->p->stats[i],
			.extra = sup->p->eqp[i],
			.max = statmax[i],
			.xscale = 2,
			.h = mh,
			.cbg = {0x65, 0x65, 0x65},
			.cbase = {0x1E, 0x94, 0x22},
			.cextra = {0x1B, 0xAF, 0xE0},
			.cborder = {}
		};

		Point mloc = { sloc.x + mh*2, sloc.y };
		Rect ma = meterarea(&meter, mloc);

		if(rectcontains(ma, sup->mouse))
			meter.cbg = (Color){ 255, 219, 0 };

		txtdraw(g, sup->txt, sloc, statname[i]);
		meterdraw(g, &meter, mloc);

		if(rectcontains(ma, sup->mouse) && sup->inc && sup->p->stats[i] < statmax[i]){
			if(i == StatHp){
				sup->p->stats[i] += 5;
				sup->p->curhp += 5;
			}else
				sup->p->stats[i]++;

			sup->norbs--;
			sup->uorbs++;
			sup->inc = 0;
		}

		sloc = vecadd(sloc, (Point){0, mh + Pad});
	}

	snprintf(buf, Bufsz, "Orbs: %d", sup->norbs);
	Point o = txtdims(sup->txt, buf);
	txtdraw(g, sup->txt, (Point){ Scrnw - o.x, 1 }, buf);

	gfxflip(g);
}

static void handle(Scrn *s, Scrnstk *stk, Event *e){
	Statup *sup = s->data;

	if(e->type == Mousemv){
		sup->mouse = projpt((Point){ e->x, e->y });
		sup->inc = 0;
		return;
	}

	if(e->type == Mousebt && sup->uorbs == 0){
		if(sup->norbs == 0)
			return;
		sup->mouse = projpt((Point){ e->x, e->y });
		sup->inc = 1;
		return;
	}

	if(e->type != Keychng || e->repeat)
		return;

	if(e->down && e->key == kmap[Mvinv]){
		Player *p = sup->p;
		int u = 0;
		for(Invit *i = p->inv; i != p->inv + Maxinv && u < sup->uorbs; i++){
			if(i->id == ItemStatup){
				i->id = 0;
				sup->norbs--;
				u++;
			}
		}
		gamesave(sup->g);
		scrnstkpop(stk);
		return;
	}
}
Exemple #27
0
 int line_search_morethuente(
    int n,
    T *x,
    T *f,
    T *g,
    T *s,
    T *stp,
    const T* xp,
    const T* gp,
    T *wa,
    callback_data_t<T> *cd,
    const lbfgs_parameter_t *param
    )
{
    int count = 0;
    int brackt, stage1, uinfo = 0;
    T dg;
    T stx, fx, dgx;
    T sty, fy, dgy;
    T fxm, dgxm, fym, dgym, fm, dgm;
    T finit, ftest1, dginit, dgtest;
    T width, prev_width;
    T stmin, stmax;

    /* Check the input parameters for errors. */
    if (*stp <= 0.) {
        return LBFGSERR_INVALIDPARAMETERS;
    }

    /* Compute the initial gradient in the search direction. */
    vecdot(&dginit, g, s, n);

    /* Make sure that s points to a descent direction. */
    if (0 < dginit) {
        return LBFGSERR_INCREASEGRADIENT;
    }

    /* Initialize local variables. */
    brackt = 0;
    stage1 = 1;
    finit = *f;
    dgtest = param->ftol * dginit;
    width = param->max_step - param->min_step;
    prev_width = 2.0 * width;

    /*
        The variables stx, fx, dgx contain the values of the step,
        function, and directional derivative at the best step.
        The variables sty, fy, dgy contain the value of the step,
        function, and derivative at the other endpoint of
        the interval of uncertainty.
        The variables stp, f, dg contain the values of the step,
        function, and derivative at the current step.
    */
    stx = sty = 0.;
    fx = fy = finit;
    dgx = dgy = dginit;

    for (;;) {
        /*
            Set the minimum and maximum steps to correspond to the
            present interval of uncertainty.
         */
        if (brackt) {
            stmin = min2(stx, sty);
            stmax = max2(stx, sty);
        } else {
            stmin = stx;
            stmax = *stp + 4.0 * (*stp - stx);
        }

        /* Clip the step in the range of [stpmin, stpmax]. */
        if (*stp < param->min_step) *stp = param->min_step;
        if (param->max_step < *stp) *stp = param->max_step;

        /*
            If an unusual termination is to occur then let
            stp be the lowest point obtained so far.
         */
        if ((brackt && ((*stp <= stmin || stmax <= *stp) || param->max_linesearch <= count + 1 || uinfo != 0)) || (brackt && (stmax - stmin <= param->xtol * stmax))) {
            *stp = stx;
        }

        /*
            Compute the current value of x:
                x <- x + (*stp) * s.
         */
        veccpy(x, xp, n);
        vecadd(x, s, *stp, n);

        /* Evaluate the function and gradient values. */
        *f = cd->proc_evaluate(cd->instance, x, g, cd->n, *stp);
        vecdot(&dg, g, s, n);

        ftest1 = finit + *stp * dgtest;
        ++count;

        /* Test for errors and convergence. */
        if (brackt && ((*stp <= stmin || stmax <= *stp) || uinfo != 0)) {
            /* Rounding errors prevent further progress. */
            return LBFGSERR_ROUNDING_ERROR;
        }
        if (*stp == param->max_step && *f <= ftest1 && dg <= dgtest) {
            /* The step is the maximum value. */
            return LBFGSERR_MAXIMUMSTEP;
        }
        if (*stp == param->min_step && (ftest1 < *f || dgtest <= dg)) {
            /* The step is the minimum value. */
            return LBFGSERR_MINIMUMSTEP;
        }
        if (brackt && (stmax - stmin) <= param->xtol * stmax) {
            /* Relative width of the interval of uncertainty is at most xtol. */
            return LBFGSERR_WIDTHTOOSMALL;
        }
        if (param->max_linesearch <= count) {
            /* Maximum number of iteration. */
            return LBFGSERR_MAXIMUMLINESEARCH;
        }
        if (*f <= ftest1 && fabs(dg) <= param->gtol * (-dginit)) {
            /* The sufficient decrease condition and the directional derivative condition hold. */
            return count;
        }

        /*
            In the first stage we seek a step for which the modified
            function has a nonpositive value and nonnegative derivative.
         */
        if (stage1 && *f <= ftest1 && min2(param->ftol, param->gtol) * dginit <= dg) {
            stage1 = 0;
        }

        /*
            A modified function is used to predict the step only if
            we have not obtained a step for which the modified
            function has a nonpositive function value and nonnegative
            derivative, and if a lower function value has been
            obtained but the decrease is not sufficient.
         */
        if (stage1 && ftest1 < *f && *f <= fx) {
            /* Define the modified function and derivative values. */
            fm = *f - *stp * dgtest;
            fxm = fx - stx * dgtest;
            fym = fy - sty * dgtest;
            dgm = dg - dgtest;
            dgxm = dgx - dgtest;
            dgym = dgy - dgtest;

            /*
                Call update_trial_interval() to update the interval of
                uncertainty and to compute the new step.
             */
            uinfo = update_trial_interval(
                &stx, &fxm, &dgxm,
                &sty, &fym, &dgym,
                stp, &fm, &dgm,
                stmin, stmax, &brackt
                );

            /* Reset the function and gradient values for f. */
            fx = fxm + stx * dgtest;
            fy = fym + sty * dgtest;
            dgx = dgxm + dgtest;
            dgy = dgym + dgtest;
        } else {
            /*
                Call update_trial_interval() to update the interval of
                uncertainty and to compute the new step.
             */
            uinfo = update_trial_interval(
                &stx, &fx, &dgx,
                &sty, &fy, &dgy,
                stp, f, &dg,
                stmin, stmax, &brackt
                );
        }

        /*
            Force a sufficient decrease in the interval of uncertainty.
         */
        if (brackt) {
            if (0.66 * prev_width <= fabs(sty - stx)) {
                *stp = stx + 0.5 * (sty - stx);
            }
            prev_width = width;
            width = fabs(sty - stx);
        }
    }

    return LBFGSERR_LOGICERROR;
}
Exemple #28
0
 int line_search_backtracking_owlqn(
    int n,
    T *x,
    T *f,
    T *g,
    T *s,
    T *stp,
    const T* xp,
    const T* gp,
    T *wp,
    callback_data_t<T> *cd,
    const lbfgs_parameter_t *param
    )
{
    int i, count = 0;
    T width = 0.5, norm = 0.;
    T finit = *f, dgtest;

    /* Check the input parameters for errors. */
    if (*stp <= 0.) {
        return LBFGSERR_INVALIDPARAMETERS;
    }

    /* Choose the orthant for the new point. */
    for (i = 0;i < n;++i) {
        wp[i] = (xp[i] == 0.) ? -gp[i] : xp[i];
    }

    for (;;) {
        /* Update the current point. */
        veccpy(x, xp, n);
        vecadd(x, s, *stp, n);

        /* The current point is projected onto the orthant. */
        owlqn_project(x, wp, param->orthantwise_start, param->orthantwise_end);

        /* Evaluate the function and gradient values. */
        *f = cd->proc_evaluate(cd->instance, x, g, cd->n, *stp);

        /* Compute the L1 norm of the variables and add it to the object value. */
        norm = owlqn_x1norm(x, param->orthantwise_start, param->orthantwise_end);
        *f += norm * param->orthantwise_c;

        ++count;

        dgtest = 0.;
        for (i = 0;i < n;++i) {
            dgtest += (x[i] - xp[i]) * gp[i];
        }

        if (*f <= finit + param->ftol * dgtest) {
            /* The sufficient decrease condition. */
            return count;
        }

        if (*stp < param->min_step) {
            /* The step is the minimum value. */
            return LBFGSERR_MINIMUMSTEP;
        }
        if (*stp > param->max_step) {
            /* The step is the maximum value. */
            return LBFGSERR_MAXIMUMSTEP;
        }
        if (param->max_linesearch <= count) {
            /* Maximum number of iteration. */
            return LBFGSERR_MAXIMUMLINESEARCH;
        }

        (*stp) *= width;
    }
}
Exemple #29
0
int line_search_backtracking(
    int n,
    T *x,
    T *f,
    T *g,
    T *s,
    T *stp,
    const T* xp,
    const T* gp,
    T *wp,
    callback_data_t<T>*cd,
    const lbfgs_parameter_t *param
    )
{
    int count = 0;
    T width, dg;
    T finit, dginit = 0., dgtest;
    const T dec = 0.5, inc = 2.1;

    /* Check the input parameters for errors. */
    if (*stp <= 0.) {
        return LBFGSERR_INVALIDPARAMETERS;
    }

    /* Compute the initial gradient in the search direction. */
    vecdot(&dginit, g, s, n);

    /* Make sure that s points to a descent direction. */
    if (0 < dginit) {
        return LBFGSERR_INCREASEGRADIENT;
    }

    /* The initial value of the objective function. */
    finit = *f;
    dgtest = param->ftol * dginit;

    for (;;) {
        veccpy(x, xp, n);
        vecadd(x, s, *stp, n);

        /* Evaluate the function and gradient values. */
        *f = cd->proc_evaluate(cd->instance, x, g, cd->n, *stp);

        ++count;

        if (*f > finit + *stp * dgtest) {
            width = dec;
        } else {
            /* The sufficient decrease condition (Armijo condition). */
            if (param->linesearch == LBFGS_LINESEARCH_BACKTRACKING_ARMIJO) {
                /* Exit with the Armijo condition. */
                return count;
	        }

	        /* Check the Wolfe condition. */
	        vecdot(&dg, g, s, n);
	        if (dg < param->wolfe * dginit) {
    		    width = inc;
	        } else {
		        if(param->linesearch == LBFGS_LINESEARCH_BACKTRACKING_WOLFE) {
		            /* Exit with the regular Wolfe condition. */
		            return count;
		        }

		        /* Check the strong Wolfe condition. */
		        if(dg > -param->wolfe * dginit) {
		            width = dec;
		        } else {
		            /* Exit with the strong Wolfe condition. */
		            return count;
		        }
            }
        }

        if (*stp < param->min_step) {
            /* The step is the minimum value. */
            return LBFGSERR_MINIMUMSTEP;
        }
        if (*stp > param->max_step) {
            /* The step is the maximum value. */
            return LBFGSERR_MAXIMUMSTEP;
        }
        if (param->max_linesearch <= count) {
            /* Maximum number of iteration. */
            return LBFGSERR_MAXIMUMLINESEARCH;
        }

        (*stp) *= width;
    }
}
Exemple #30
0
int lbfgs(
    int n,
    T *x,
    T *ptr_fx,
typename   FuncWrapper<T>::lbfgs_evaluate_t proc_evaluate,
    typename  FuncWrapper<T>::lbfgs_progress_t proc_progress,
    void *instance,
    lbfgs_parameter_t *_param
    )
{
    int ret;
    int i, j, k, ls, end, bound;
    T step;

    /* Constant parameters and their default values. */
    lbfgs_parameter_t param = (_param != NULL) ? (*_param) : _defparam;
    const int m = param.m;

    T *xp = NULL;
    T *g = NULL, *gp = NULL, *pg = NULL;
    T *d = NULL, *w = NULL, *pf = NULL;
    iteration_data_t<T> *lm = NULL;
    iteration_data_t<T>*it = NULL;
    T ys, yy;
    T xnorm, gnorm, beta;
    T fx = 0.;
    T rate = 0.;
typename    LineSearchWrapper<T>::line_search_proc linesearch = line_search_morethuente;

    /* Construct a callback data. */
    callback_data_t<T> cd;
    cd.n = n;
    cd.instance = instance;
    cd.proc_evaluate = proc_evaluate;
    cd.proc_progress = proc_progress;

#if     defined(USE_SSE) && (defined(__SSE__) || defined(__SSE2__))
    /* Round out the number of variables. */
    n = round_out_variables(n);
#endif/*defined(USE_SSE)*/

    /* Check the input parameters for errors. */
    if (n <= 0) {
        return LBFGSERR_INVALID_N;
    }
#if     defined(USE_SSE) && (defined(__SSE__) || defined(__SSE2__))
    if (n % 8 != 0) {
        return LBFGSERR_INVALID_N_SSE;
    }
    if ((uintptr_t)(const void*)x % 16 != 0) {
        return LBFGSERR_INVALID_X_SSE;
    }
#endif/*defined(USE_SSE)*/
    if (param.epsilon < 0.) {
        return LBFGSERR_INVALID_EPSILON;
    }
    if (param.past < 0) {
        return LBFGSERR_INVALID_TESTPERIOD;
    }
    if (param.delta < 0.) {
        return LBFGSERR_INVALID_DELTA;
    }
    if (param.min_step < 0.) {
        return LBFGSERR_INVALID_MINSTEP;
    }
    if (param.max_step < param.min_step) {
        return LBFGSERR_INVALID_MAXSTEP;
    }
    if (param.ftol < 0.) {
        return LBFGSERR_INVALID_FTOL;
    }
    if (param.linesearch == LBFGS_LINESEARCH_BACKTRACKING_WOLFE ||
        param.linesearch == LBFGS_LINESEARCH_BACKTRACKING_STRONG_WOLFE) {
        if (param.wolfe <= param.ftol || 1. <= param.wolfe) {
            return LBFGSERR_INVALID_WOLFE;
        }
    }
    if (param.gtol < 0.) {
        return LBFGSERR_INVALID_GTOL;
    }
    if (param.xtol < 0.) {
        return LBFGSERR_INVALID_XTOL;
    }
    if (param.max_linesearch <= 0) {
        return LBFGSERR_INVALID_MAXLINESEARCH;
    }
    if (param.orthantwise_c < 0.) {
        return LBFGSERR_INVALID_ORTHANTWISE;
    }
    if (param.orthantwise_start < 0 || n < param.orthantwise_start) {
        return LBFGSERR_INVALID_ORTHANTWISE_START;
    }
    if (param.orthantwise_end < 0) {
        param.orthantwise_end = n;
    }
    if (n < param.orthantwise_end) {
        return LBFGSERR_INVALID_ORTHANTWISE_END;
    }
    if (param.orthantwise_c != 0.) {
        switch (param.linesearch) {
        case LBFGS_LINESEARCH_BACKTRACKING:
            linesearch = line_search_backtracking_owlqn;
            break;
        default:
            /* Only the backtracking method is available. */
            return LBFGSERR_INVALID_LINESEARCH;
        }
    } else {
        switch (param.linesearch) {
        case LBFGS_LINESEARCH_MORETHUENTE:
            linesearch = line_search_morethuente;
            break;
        case LBFGS_LINESEARCH_BACKTRACKING_ARMIJO:
        case LBFGS_LINESEARCH_BACKTRACKING_WOLFE:
        case LBFGS_LINESEARCH_BACKTRACKING_STRONG_WOLFE:
            linesearch = line_search_backtracking;
            break;
        default:
            return LBFGSERR_INVALID_LINESEARCH;
        }
    }

    /* Allocate working space. */
    xp = (T*)vecalloc(n * sizeof(T));
    g = (T*)vecalloc(n * sizeof(T));
    gp = (T*)vecalloc(n * sizeof(T));
    d = (T*)vecalloc(n * sizeof(T));
    w = (T*)vecalloc(n * sizeof(T));
    if (xp == NULL || g == NULL || gp == NULL || d == NULL || w == NULL) {
        ret = LBFGSERR_OUTOFMEMORY;
        goto lbfgs_exit;
    }

    if (param.orthantwise_c != 0.) {
        /* Allocate working space for OW-LQN. */
        pg = (T*)vecalloc(n * sizeof(T));
        if (pg == NULL) {
            ret = LBFGSERR_OUTOFMEMORY;
            goto lbfgs_exit;
        }
    }

    /* Allocate limited memory storage. */
    lm = (iteration_data_t<T>*)vecalloc(m * sizeof(iteration_data_t<T>));
    if (lm == NULL) {
        ret = LBFGSERR_OUTOFMEMORY;
        goto lbfgs_exit;
    }

    /* Initialize the limited memory. */
    for (i = 0;i < m;++i) {
        it = &lm[i];
        it->alpha = 0;
        it->ys = 0;
        it->s = (T*)vecalloc(n * sizeof(T));
        it->y = (T*)vecalloc(n * sizeof(T));
        if (it->s == NULL || it->y == NULL) {
            ret = LBFGSERR_OUTOFMEMORY;
            goto lbfgs_exit;
        }
    }

    /* Allocate an array for storing previous values of the objective function. */
    if (0 < param.past) {
        pf = (T*)vecalloc(param.past * sizeof(T));
    }

    /* Evaluate the function value and its gradient. */
    fx = cd.proc_evaluate(cd.instance, x, g, cd.n, 0);
    if (0. != param.orthantwise_c) {
        /* Compute the L1 norm of the variable and add it to the object value. */
        xnorm = owlqn_x1norm(x, param.orthantwise_start, param.orthantwise_end);
        fx += xnorm * param.orthantwise_c;
        owlqn_pseudo_gradient(
            pg, x, g, n,
            T(param.orthantwise_c), param.orthantwise_start, param.orthantwise_end
            );
    }

    /* Store the initial value of the objective function. */
    if (pf != NULL) {
        pf[0] = fx;
    }

    /*
        Compute the direction;
        we assume the initial hessian matrix H_0 as the identity matrix.
     */
    if (param.orthantwise_c == 0.) {
        vecncpy(d, g, n);
    } else {
        vecncpy(d, pg, n);
    }

    /*
       Make sure that the initial variables are not a minimizer.
     */
    vec2norm(&xnorm, x, n);
    if (param.orthantwise_c == 0.) {
        vec2norm(&gnorm, g, n);
    } else {
        vec2norm(&gnorm, pg, n);
    }
    if (xnorm < 1.0) xnorm = 1.0;
    if (gnorm / xnorm <= param.epsilon) {
        ret = LBFGS_ALREADY_MINIMIZED;
        goto lbfgs_exit;
    }

    /* Compute the initial step:
        step = 1.0 / sqrt(vecdot(d, d, n))
     */
    vec2norminv(&step, d, n);

    k = 1;
    end = 0;
    for (;;) {
        /* Store the current position and gradient vectors. */
        veccpy(xp, x, n);
        veccpy(gp, g, n);

        /* Search for an optimal step. */
        if (param.orthantwise_c == 0.) {
            ls = linesearch(n, x, &fx, g, d, &step, xp, gp, w, &cd, &param);
        } else {
            ls = linesearch(n, x, &fx, g, d, &step, xp, pg, w, &cd, &param);
            owlqn_pseudo_gradient(
                pg, x, g, n,
                T(param.orthantwise_c), param.orthantwise_start, param.orthantwise_end
                );
        }
        if (ls < 0) {
            /* Revert to the previous point. */
            veccpy(x, xp, n);
            veccpy(g, gp, n);
            ret = ls;
            goto lbfgs_exit;
        }

        /* Compute x and g norms. */
        vec2norm(&xnorm, x, n);
        if (param.orthantwise_c == 0.) {
            vec2norm(&gnorm, g, n);
        } else {
            vec2norm(&gnorm, pg, n);
        }

        /* Report the progress. */
        if (cd.proc_progress) {
            if ((ret = cd.proc_progress(cd.instance, x, g, fx, xnorm, gnorm, step, cd.n, k, ls))) {
                goto lbfgs_exit;
            }
        }

        /*
            Convergence test.
            The criterion is given by the following formula:
                |g(x)| / \max(1, |x|) < \epsilon
         */
        if (xnorm < 1.0) xnorm = 1.0;
        if (gnorm / xnorm <= param.epsilon) {
            /* Convergence. */
            ret = LBFGS_SUCCESS;
            break;
        }

        /*
            Test for stopping criterion.
            The criterion is given by the following formula:
                (f(past_x) - f(x)) / f(x) < \delta
         */
        if (pf != NULL) {
            /* We don't test the stopping criterion while k < past. */
            if (param.past <= k) {
                /* Compute the relative improvement from the past. */
                rate = (pf[k % param.past] - fx) / fx;

                /* The stopping criterion. */
                if (rate < param.delta) {
                    ret = LBFGS_STOP;
                    break;
                }
            }

            /* Store the current value of the objective function. */
            pf[k % param.past] = fx;
        }

        if (param.max_iterations != 0 && param.max_iterations < k+1) {
            /* Maximum number of iterations. */
            ret = LBFGSERR_MAXIMUMITERATION;
            break;
        }

        /*
            Update vectors s and y:
                s_{k+1} = x_{k+1} - x_{k} = \step * d_{k}.
                y_{k+1} = g_{k+1} - g_{k}.
         */
        it = &lm[end];
        vecdiff(it->s, x, xp, n);
        vecdiff(it->y, g, gp, n);

        /*
            Compute scalars ys and yy:
                ys = y^t \cdot s = 1 / \rho.
                yy = y^t \cdot y.
            Notice that yy is used for scaling the hessian matrix H_0 (Cholesky factor).
         */
        vecdot(&ys, it->y, it->s, n);
        vecdot(&yy, it->y, it->y, n);
        it->ys = ys;

        /*
            Recursive formula to compute dir = -(H \cdot g).
                This is described in page 779 of:
                Jorge Nocedal.
                Updating Quasi-Newton Matrices with Limited Storage.
                Mathematics of Computation, Vol. 35, No. 151,
                pp. 773--782, 1980.
         */
        bound = (m <= k) ? m : k;
        ++k;
        end = (end + 1) % m;

        /* Compute the steepest direction. */
        if (param.orthantwise_c == 0.) {
            /* Compute the negative of gradients. */
            vecncpy(d, g, n);
        } else {
            vecncpy(d, pg, n);
        }

        j = end;
        for (i = 0;i < bound;++i) {
            j = (j + m - 1) % m;    /* if (--j == -1) j = m-1; */
            it = &lm[j];
            /* \alpha_{j} = \rho_{j} s^{t}_{j} \cdot q_{k+1}. */
            vecdot(&it->alpha, it->s, d, n);
            it->alpha /= it->ys;
            /* q_{i} = q_{i+1} - \alpha_{i} y_{i}. */
            vecadd(d, it->y, -it->alpha, n);
        }

        vecscale(d, ys / yy, n);

        for (i = 0;i < bound;++i) {
            it = &lm[j];
            /* \beta_{j} = \rho_{j} y^t_{j} \cdot \gamma_{i}. */
            vecdot(&beta, it->y, d, n);
            beta /= it->ys;
            /* \gamma_{i+1} = \gamma_{i} + (\alpha_{j} - \beta_{j}) s_{j}. */
            vecadd(d, it->s, it->alpha - beta, n);
            j = (j + 1) % m;        /* if (++j == m) j = 0; */
        }

        /*
            Constrain the search direction for orthant-wise updates.
         */
        if (param.orthantwise_c != 0.) {
            for (i = param.orthantwise_start;i < param.orthantwise_end;++i) {
                if (d[i] * pg[i] >= 0) {
                    d[i] = 0;
                }
            }
        }

        /*
            Now the search direction d is ready. We try step = 1 first.
         */
        step = 1.0;
    }

lbfgs_exit:
    /* Return the final value of the objective function. */
    if (ptr_fx != NULL) {
        *ptr_fx = fx;
    }

    vecfree(pf);

    /* Free memory blocks used by this function. */
    if (lm != NULL) {
        for (i = 0;i < m;++i) {
            vecfree(lm[i].s);
            vecfree(lm[i].y);
        }
        vecfree(lm);
    }
    vecfree(pg);
    vecfree(w);
    vecfree(d);
    vecfree(gp);
    vecfree(g);
    vecfree(xp);

    return ret;
}