mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
never mind; we really do *not* have any use for these funcs;
things will be handled very differently. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@8121 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
18cc347bae
commit
7c5f5fcaf3
@ -1,385 +0,0 @@
|
|||||||
/* XXXXXXXXXXXXXXXXXXXXXXXXXXX
|
|
||||||
Caution
|
|
||||||
|
|
||||||
As of March 2003, this file is under construction,
|
|
||||||
it is in the process of being modernized
|
|
||||||
in order to allow the implementation of Lots to proceed forward.
|
|
||||||
This is needed, in turn, to complete the implementation of books.
|
|
||||||
|
|
||||||
this file does not currently compile
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************\
|
|
||||||
* This program is free software; you can redistribute it and/or *
|
|
||||||
* modify it under the terms of the GNU General Public License as *
|
|
||||||
* published by the Free Software Foundation; either version 2 of *
|
|
||||||
* the License, or (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
* This program is distributed in the hope that it will be useful, *
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
||||||
* GNU General Public License for more details. *
|
|
||||||
* *
|
|
||||||
* You should have received a copy of the GNU General Public License*
|
|
||||||
* along with this program; if not, contact: *
|
|
||||||
* *
|
|
||||||
* Free Software Foundation Voice: +1-617-542-5942 *
|
|
||||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
|
||||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
|
||||||
\********************************************************************/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* FILE:
|
|
||||||
* Queue.c
|
|
||||||
*
|
|
||||||
* DESCRIPTION:
|
|
||||||
* Provide simple FIFO/LIFO cost-basis accounting support.
|
|
||||||
*
|
|
||||||
* RESTRICTIONS:
|
|
||||||
* -- Does not support use with mixed currencies.
|
|
||||||
* -- Does not check for or warn mixed currency use.
|
|
||||||
* -- Does not allow pushhead after a pophead has occured.
|
|
||||||
*
|
|
||||||
* HISTORY:
|
|
||||||
* Created by Linas Vepstas January 1999
|
|
||||||
* Copyright (c) 1999, 2000, 2003 Linas Vepstas <linas@linas.org>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <limits.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <strings.h>
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include "gnc-commodity.h"
|
|
||||||
#include "gnc-engine.h"
|
|
||||||
#include "GNCQueue.h"
|
|
||||||
#include "Transaction.h"
|
|
||||||
#include "TransactionP.h"
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
/* This static indicates the debugging module that this .o belongs to. */
|
|
||||||
static short module = MOD_ENGINE;
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
struct queue_s
|
|
||||||
{
|
|
||||||
GUID guid; /* globally unique id */
|
|
||||||
GNCBook *book;
|
|
||||||
|
|
||||||
/* List of Lots ?? */
|
|
||||||
|
|
||||||
/* XXX commodity ??? */
|
|
||||||
Split **split_list;
|
|
||||||
|
|
||||||
int head_split;
|
|
||||||
int tail_split;
|
|
||||||
int list_len;
|
|
||||||
|
|
||||||
gnc_numeric head_amount;
|
|
||||||
gnc_numeric head_value;
|
|
||||||
Timespec head_date;
|
|
||||||
|
|
||||||
gnc_numeric tail_amount;
|
|
||||||
gnc_numeric tail_value;
|
|
||||||
Timespec tail_date;
|
|
||||||
|
|
||||||
/* kvp_data is a key-value pair database for storing simple
|
|
||||||
* "extra" information in splits, transactions, and accounts.
|
|
||||||
* it's NULL until accessed. */
|
|
||||||
kvp_frame * kvp_data;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
GNCQueue *
|
|
||||||
xaccMallocQueue (GNCBook *book)
|
|
||||||
{
|
|
||||||
GNCQueue * ret;
|
|
||||||
ret = (GNCQueue *) g_new (GNCQueue, 1);
|
|
||||||
xaccInitGNCQueue (ret, book);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
#define INITIAL_LENGTH 100
|
|
||||||
|
|
||||||
void
|
|
||||||
xaccInitQueue (GNCQueue *q, GNCBook *book)
|
|
||||||
{
|
|
||||||
if (!q) return;
|
|
||||||
|
|
||||||
q->split_list = (Split **) malloc (INITIAL_LENGTH * sizeof (Split *));
|
|
||||||
q->list_len = INITIAL_LENGTH;
|
|
||||||
q->head_split = -1;
|
|
||||||
q->tail_split = 0;
|
|
||||||
q->head_amount = gnc_numeric_zero();
|
|
||||||
q->tail_amount = gnc_numeric_zero();
|
|
||||||
q->head_price = gnc_numeric_zero();
|
|
||||||
q->tail_price = gnc_numeric_zero();
|
|
||||||
|
|
||||||
q->head_date.tv_sec = 0;
|
|
||||||
q->head_date.tv_nsec = 0;
|
|
||||||
q->tail_date.tv_sec = 0;
|
|
||||||
q->tail_date.tv_nsec = 0;
|
|
||||||
|
|
||||||
q->kvp_data = kvp_frame_new();
|
|
||||||
q->book = book;
|
|
||||||
xaccGUIDNew (&q->guid, book);
|
|
||||||
xaccStoreEntity(book->entity_table, q, &q->guid, GNC_ID_QUEUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
void
|
|
||||||
xaccFreeQueue (GNCQueue *q)
|
|
||||||
{
|
|
||||||
if (!q) return;
|
|
||||||
|
|
||||||
xaccRemoveEntity (q->book->entity_table, &q->guid);
|
|
||||||
|
|
||||||
if (q->split_list) _free (q->split_list);
|
|
||||||
q->split_list = 0x0;
|
|
||||||
q->list_len = -1;
|
|
||||||
q->head_split = -1;
|
|
||||||
q->tail_split = 0;
|
|
||||||
q->head_amount = gnc_numeric_zero();
|
|
||||||
q->tail_amount = gnc_numeric_zero();
|
|
||||||
q->head_price = gnc_numeric_zero();
|
|
||||||
q->tail_price = gnc_numeric_zero();
|
|
||||||
|
|
||||||
g_free (q);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
void
|
|
||||||
xaccQueuePushHead (GNCQueue *q, Split *s)
|
|
||||||
{
|
|
||||||
if (!q || !s) return;
|
|
||||||
|
|
||||||
/* I'm too lazy to code up a more complex feature that no one will use ... */
|
|
||||||
/* If you are reading this, you are invited to do so yourself :-) */
|
|
||||||
if ( !DEQ (q->head_amount, 0.0)) {
|
|
||||||
PERR ("The current implementation does not\n"
|
|
||||||
"\tsupport pushing onto a queue that has been popped \n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* don't queue a split that has no value */
|
|
||||||
if (DEQ (s->damount, 0.0)) return;
|
|
||||||
|
|
||||||
q->head_split ++;
|
|
||||||
q->split_list [ q->head_split ] = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
double
|
|
||||||
xaccQueuePopTailShares (GNCQueue *q, double shrs)
|
|
||||||
{
|
|
||||||
int tp, hp;
|
|
||||||
Split **list;
|
|
||||||
double rshrs = 0.0;
|
|
||||||
|
|
||||||
if (!q) return 0.0;
|
|
||||||
if (0.0 >= shrs) return 0.0;
|
|
||||||
|
|
||||||
/* the tail holds enough to do it in one go. */
|
|
||||||
if (q->tail_amount > shrs) {
|
|
||||||
q->tail_amount -= shrs;
|
|
||||||
return shrs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* use up the tail shares first ... */
|
|
||||||
shrs -= q->tail_amount;
|
|
||||||
rshrs += q->tail_amount;
|
|
||||||
q->tail_amount = 0.0;
|
|
||||||
q->tail_price = 0.0;
|
|
||||||
q->tail_date.tv_sec = 0;
|
|
||||||
q->tail_date.tv_nsec = 0;
|
|
||||||
|
|
||||||
/* start poping */
|
|
||||||
tp = q->tail_split;
|
|
||||||
hp = q->head_split;
|
|
||||||
list = q->split_list;
|
|
||||||
while (tp <= hp)
|
|
||||||
{
|
|
||||||
/* the tail holds enough to do it in one go. */
|
|
||||||
if ((list[tp]->damount) > shrs) {
|
|
||||||
q->tail_amount = list[tp]->damount - shrs;
|
|
||||||
q->tail_price = list[tp]->share_price;
|
|
||||||
assert (list[tp]->parent);
|
|
||||||
q->tail_date = list[tp]->parent->date_posted;
|
|
||||||
rshrs += shrs;
|
|
||||||
tp++;
|
|
||||||
q->tail_split = tp;
|
|
||||||
return rshrs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* well, well need use up this entire split ... */
|
|
||||||
shrs -= (list[tp]->damount);
|
|
||||||
rshrs += (list[tp]->damount);
|
|
||||||
tp++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* oops, if we got to here, we've used up all of the splits.
|
|
||||||
* give em whatever we've got on the head, and then we're outta here.
|
|
||||||
*/
|
|
||||||
q->tail_split = 0;
|
|
||||||
q->head_split = -1;
|
|
||||||
|
|
||||||
/* the head holds enough to do it in one go. */
|
|
||||||
if (q->head_amount > shrs) {
|
|
||||||
q->head_amount -= shrs;
|
|
||||||
rshrs += shrs;
|
|
||||||
return shrs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* use up whats left of the head shares */
|
|
||||||
shrs -= q->head_amount;
|
|
||||||
rshrs += q->head_amount;
|
|
||||||
q->head_amount = 0.0;
|
|
||||||
q->head_price = 0.0;
|
|
||||||
q->head_date.tv_sec = 0;
|
|
||||||
q->head_date.tv_nsec = 0;
|
|
||||||
|
|
||||||
return rshrs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
double
|
|
||||||
xaccQueuePopTailValue (GNCQueue *q, double val)
|
|
||||||
{
|
|
||||||
int tp, hp;
|
|
||||||
Split **list;
|
|
||||||
double rval = 0.0;
|
|
||||||
|
|
||||||
if (!q) return 0.0;
|
|
||||||
if (0.0 >= val) return 0.0;
|
|
||||||
|
|
||||||
/* the tail holds enough to do it in one go. */
|
|
||||||
if (q->tail_amount * q->tail_price > val) {
|
|
||||||
q->tail_amount -= val / q->tail_price;
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* use up the tail shares first ... */
|
|
||||||
val -= q->tail_amount * q->tail_price;
|
|
||||||
rval += q->tail_amount * q->tail_price;
|
|
||||||
q->tail_amount = 0.0;
|
|
||||||
q->tail_price = 0.0;
|
|
||||||
q->tail_date.tv_sec = 0;
|
|
||||||
q->tail_date.tv_nsec = 0;
|
|
||||||
|
|
||||||
/* start poping */
|
|
||||||
tp = q->tail_split;
|
|
||||||
hp = q->head_split;
|
|
||||||
list = q->split_list;
|
|
||||||
while (tp <= hp)
|
|
||||||
{
|
|
||||||
/* the tail holds enough to do it in one go. */
|
|
||||||
if ((list[tp]->damount)*(list[tp]->share_price) > val) {
|
|
||||||
q->tail_amount = list[tp]->damount - (val/(list[tp]->share_price));
|
|
||||||
q->tail_price = list[tp]->share_price;
|
|
||||||
assert (list[tp]->parent);
|
|
||||||
q->tail_date = list[tp]->parent->date_posted;
|
|
||||||
rval += val;
|
|
||||||
tp++;
|
|
||||||
q->tail_split = tp;
|
|
||||||
return rval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* well, well need use up this entire split ... */
|
|
||||||
val -= (list[tp]->damount) * (list[tp]->share_price);
|
|
||||||
rval += (list[tp]->damount) * (list[tp]->share_price);
|
|
||||||
tp++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* oops, if we got to here, we've used up all of the splits.
|
|
||||||
* give em whatever we've got on the head, and then we're outta here.
|
|
||||||
*/
|
|
||||||
q->tail_split = 0;
|
|
||||||
q->head_split = -1;
|
|
||||||
|
|
||||||
/* the head holds enough to do it in one go. */
|
|
||||||
if (q->head_amount * q->head_price > val) {
|
|
||||||
q->head_amount -= val / (q->head_price);
|
|
||||||
rval += val;
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* use up whats left of the head shares */
|
|
||||||
val -= q->head_amount * q->head_price;
|
|
||||||
rval += q->head_amount * q->head_price;
|
|
||||||
q->head_amount = 0.0;
|
|
||||||
q->head_price = 0.0;
|
|
||||||
q->head_date.tv_sec = 0;
|
|
||||||
q->head_date.tv_nsec = 0;
|
|
||||||
|
|
||||||
return rval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
/* these routines are same as above, but everything is reversed... */
|
|
||||||
|
|
||||||
double
|
|
||||||
xaccQueuePopHeadValue (GNCQueue *q, double val)
|
|
||||||
{
|
|
||||||
PERR("not implemented\n");
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
double
|
|
||||||
xaccQueuePopHeadShares (GNCQueue *q, double val)
|
|
||||||
{
|
|
||||||
PERR("not implemented\n");
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================================================== */
|
|
||||||
|
|
||||||
double
|
|
||||||
xaccQueueGetShares (GNCQueue *q)
|
|
||||||
{
|
|
||||||
Split **list;
|
|
||||||
double shrs = 0.0;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!q) return 0.0;
|
|
||||||
|
|
||||||
shrs += q->head_amount;
|
|
||||||
shrs += q->tail_amount;
|
|
||||||
|
|
||||||
list = q->split_list;
|
|
||||||
|
|
||||||
for (i = q->tail_split; i <= q->head_split; i++)
|
|
||||||
shrs += list[i]->damount;
|
|
||||||
|
|
||||||
return shrs;
|
|
||||||
}
|
|
||||||
|
|
||||||
double
|
|
||||||
xaccQueueGetValue (GNCQueue *q)
|
|
||||||
{
|
|
||||||
Split **list;
|
|
||||||
double val = 0.0;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!q) return 0.0;
|
|
||||||
|
|
||||||
val += q->head_amount * q->head_price;
|
|
||||||
val += q->tail_amount * q->tail_price;
|
|
||||||
|
|
||||||
list = q->split_list;
|
|
||||||
|
|
||||||
for (i = q->tail_split; i <= q->head_split; i++)
|
|
||||||
val += list[i]->damount * list[i]->share_price;
|
|
||||||
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================ END OF FILE ==================== */
|
|
@ -1,120 +0,0 @@
|
|||||||
/* XXXXXXXXXXXXXXXXXXXXXXXXXXX
|
|
||||||
Caution
|
|
||||||
|
|
||||||
As of March 2003, this file is under construction,
|
|
||||||
it is in the process of being modernized
|
|
||||||
in order to allow the implementation of Lots to proceed forward.
|
|
||||||
This is needed, in turn, to complete the implementation of books.
|
|
||||||
|
|
||||||
this file does not currently compile
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* FILE:
|
|
||||||
* Queue.h
|
|
||||||
*
|
|
||||||
* DESCRIPTION:
|
|
||||||
* Provides simple FIFO/LIFO cost-basis accounting support.
|
|
||||||
*
|
|
||||||
* The routines in this class implement a simple FIFO that
|
|
||||||
* holds a series of splits. Splits can be pushed onto the head
|
|
||||||
* of the fifo. The number of shares contained in the fifo is
|
|
||||||
* then simply the sum of all of the shares in the splits.
|
|
||||||
* The "value" of the fifo is the cost-basis value of all of
|
|
||||||
* the splits, i.e. the total of number of shares times prices.
|
|
||||||
*
|
|
||||||
* When shares are sold, they are dequed from the queue. If the
|
|
||||||
* oldest shares are sold first, they are dequed or "popped" from
|
|
||||||
* the tail, and the queue acts as a FIFO. If the newest shares
|
|
||||||
* are sold first, then the queue acts as a LIFO, and shares are
|
|
||||||
* poped off the head.
|
|
||||||
*
|
|
||||||
* Either shares or a monetary value can be dequeued. The amount
|
|
||||||
* dequeued does not have to exactly equal the amount/value of
|
|
||||||
* any given split; fractional amounts can be dequeued. This queue
|
|
||||||
* automatically tracks fractional amounts on both the head (LIFO)
|
|
||||||
* and tail (FIFO). Indeed, there are *no* routines to explicitly
|
|
||||||
* dequeue a split; *only* amounts and values can be dequed.
|
|
||||||
* Conversely, *only* splits can be pushed on, as this queue does
|
|
||||||
* not provide any internal or hidden elements.
|
|
||||||
*
|
|
||||||
* In addition to the queue value, and the number of shares queued,
|
|
||||||
* the average age of the shares can also be computed, as well as
|
|
||||||
* other statistics involving a date and price. The queue automatically
|
|
||||||
* tracks the posted date of fractional splits at the head and tail.
|
|
||||||
*
|
|
||||||
* RESTRICTIONS:
|
|
||||||
* -- Does not support use with mixed currencies.
|
|
||||||
* -- Does not check for or warn mixed currency use.
|
|
||||||
* -- Does not allow push-head after a pop-head has occured.
|
|
||||||
* -- Push-tail not implemented
|
|
||||||
*
|
|
||||||
* HISTORY:
|
|
||||||
* created by Linas Vepstas January 1999
|
|
||||||
* Copyright (c) 1999, 2000 Linas Vepstas
|
|
||||||
*/
|
|
||||||
/********************************************************************\
|
|
||||||
* This program is free software; you can redistribute it and/or *
|
|
||||||
* modify it under the terms of the GNU General Public License as *
|
|
||||||
* published by the Free Software Foundation; either version 2 of *
|
|
||||||
* the License, or (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
* This program is distributed in the hope that it will be useful, *
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
||||||
* GNU General Public License for more details. *
|
|
||||||
* *
|
|
||||||
* You should have received a copy of the GNU General Public License*
|
|
||||||
* along with this program; if not, contact: *
|
|
||||||
* *
|
|
||||||
* Free Software Foundation Voice: +1-617-542-5942 *
|
|
||||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
|
||||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
|
||||||
\********************************************************************/
|
|
||||||
|
|
||||||
#ifndef XACC_QUEUE_H
|
|
||||||
#define XACC_QUEUE_H
|
|
||||||
|
|
||||||
#include "Transaction.h"
|
|
||||||
|
|
||||||
typedef struct _Queue Queue;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The xaccQueuePushHead() routine pushes a split onto the head
|
|
||||||
* of the queue.
|
|
||||||
*
|
|
||||||
* The xaccQueuePopTailShares() routine removes the indicated
|
|
||||||
* number of shares from the bottom of the queue. If the queue
|
|
||||||
* does not contain that many shares, it dequeues all of the
|
|
||||||
* shares. This routine returns the actual number of shares dequeued.
|
|
||||||
* Use this routine for FIFO accounting.
|
|
||||||
*
|
|
||||||
* The xaccQueuePopTailValue() routine removes the indicated
|
|
||||||
* value from the bottom of the queue. If the value of the queue is less
|
|
||||||
* than this amount, the value of the queue is set to zero, and the
|
|
||||||
* actual value poped is returned.
|
|
||||||
* Use this routine for FIFO accounting.
|
|
||||||
*
|
|
||||||
* The xaccQueuePopHeadShares() and xaccQueuePopHeadValue() routines
|
|
||||||
* behave in the same way as the *Tail* versions, except that they act
|
|
||||||
* on the head of the queue. Use these routines for LIFO accounting.
|
|
||||||
*
|
|
||||||
* The xaccQueueGetValue() routine returns the value of the queue.
|
|
||||||
* The xaccQueueGetShares() routine returns the number of shares in the queue.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Queue * xaccMallocQueue (void);
|
|
||||||
void xaccInitQueue (Queue *q);
|
|
||||||
void xaccFreeQueue (Queue *q);
|
|
||||||
|
|
||||||
void xaccQueuePushHead (Queue *q, Split *s);
|
|
||||||
|
|
||||||
double xaccQueuePopHeadShares (Queue *, double);
|
|
||||||
double xaccQueuePopHeadValue (Queue *, double);
|
|
||||||
double xaccQueuePopTailShares (Queue *, double);
|
|
||||||
double xaccQueuePopTailValue (Queue *, double);
|
|
||||||
|
|
||||||
double xaccQueueGetValue (Queue *);
|
|
||||||
double xaccQueueGetShares (Queue *);
|
|
||||||
|
|
||||||
#endif /* XACC_QUEUE_H */
|
|
Loading…
Reference in New Issue
Block a user