Example #1
0
// BigratToInt converts a *big.Rat to a *big.Int (with truncation)
func BigratToBigint(bigrat *big.Rat) *big.Int {
	int_string := bigrat.FloatString(0)
	bigint := new(big.Int)
	// no error scenario could be imagined in testing, so discard err
	fmt.Sscan(int_string, bigint)
	return bigint
}
Example #2
0
// Prints each transaction that matches the given filters.
func PrintRegister(generalLedger []*ledger.Transaction, filterArr []string, columns int) {
	runningBalance := new(big.Rat)
	for _, trans := range generalLedger {
		for _, accChange := range trans.AccountChanges {
			inFilter := len(filterArr) == 0
			for _, filter := range filterArr {
				if strings.Contains(accChange.Name, filter) {
					inFilter = true
				}
			}
			if inFilter {
				runningBalance.Add(runningBalance, accChange.Balance)
				writtenBytes, _ := fmt.Printf("%s %s", trans.Date.Format(ledger.TransactionDateFormat), trans.Payee)
				outBalanceString := accChange.Balance.FloatString(ledger.DisplayPrecision)
				outRunningBalanceString := runningBalance.FloatString(ledger.DisplayPrecision)
				spaceCount := columns - writtenBytes - 2 - len(outBalanceString) - len(outRunningBalanceString)
				if spaceCount < 0 {
					spaceCount = 0
				}
				fmt.Printf("%s%s %s", strings.Repeat(" ", spaceCount), outBalanceString, outRunningBalanceString)
				fmt.Println("")
			}
		}
	}
}
Example #3
0
// FloatString returns a string representation of decimal form with precision digits of precision after the decimal point and the last digit rounded.
func (this Decimal) FloatString(precision int) string {
	this.ensureValid()

	x := new(big.Rat).SetInt(this.integer)
	y := new(big.Rat).Inv(new(big.Rat).SetInt(new(big.Int).Exp(big.NewInt(int64(10)), big.NewInt(int64(this.scale)), nil)))
	z := new(big.Rat).Mul(x, y)
	return z.FloatString(precision)
}
Example #4
0
File: bigrat.go Project: zzn01/ivy
func (r BigRat) floatString(verb byte, prec int) string {
	switch verb {
	case 'f', 'F':
		return r.Rat.FloatString(prec)
	case 'e', 'E':
		// The exponent will alway be >= 0.
		sign := ""
		var x, t big.Rat
		x.Set(r.Rat)
		if x.Sign() < 0 {
			sign = "-"
			x.Neg(&x)
		}
		t.Set(&x)
		exp := ratExponent(&x)
		ratScale(&t, exp)
		str := t.FloatString(prec + 1) // +1 because first digit might be zero.
		// Drop the decimal.
		if str[0] == '0' {
			str = str[2:]
			exp--
		} else if len(str) > 1 && str[1] == '.' {
			str = str[0:1] + str[2:]
		}
		return eFormat(verb, prec, sign, str, exp)
	case 'g', 'G':
		var x big.Rat
		x.Set(r.Rat)
		exp := ratExponent(&x)
		// Exponent could be positive or negative
		if exp < -4 || prec <= exp {
			// Use e format.
			verb -= 2 // g becomes e.
			return trimEZeros(verb, r.floatString(verb, prec-1))
		}
		// Use f format.
		// If it's got zeros right of the decimal, they count as digits in the precision.
		// If it's got digits left of the decimal, they count as digits in the precision.
		// Both are handled by adjusting prec by exp.
		str := r.floatString(verb-1, prec-exp-1) // -1 for the one digit left of the decimal.
		// Trim trailing decimals.
		point := strings.IndexByte(str, '.')
		if point > 0 {
			n := len(str)
			for str[n-1] == '0' {
				n--
			}
			str = str[:n]
			if str[n-1] == '.' {
				str = str[:n-1]
			}
		}
		return str
	default:
		Errorf("can't handle verb %c for rational", verb)
	}
	return ""
}
Example #5
0
func String(v xdr.Int64) string {
	var f, o, r big.Rat

	f.SetInt64(int64(v))
	o.SetInt64(One)
	r.Quo(&f, &o)

	return r.FloatString(7)
}
Example #6
0
func floatString(r *big.Rat) string {
	const prec = 50
	s := r.FloatString(prec)
	if strings.ContainsRune(s, '.') {
		s = strings.TrimRight(s, "0")
		if s[len(s)-1] == '.' {
			s += "0"
		}
	}
	return s
}
Example #7
0
// floatString returns the string representation for a
// numeric value v in normalized floating-point format.
func floatString(v exact.Value) string {
	if exact.Sign(v) == 0 {
		return "0.0"
	}
	// x != 0

	// convert |v| into a big.Rat x
	x := new(big.Rat).SetFrac(absInt(exact.Num(v)), absInt(exact.Denom(v)))

	// normalize x and determine exponent e
	// (This is not very efficient, but also not speed-critical.)
	var e int
	for x.Cmp(ten) >= 0 {
		x.Quo(x, ten)
		e++
	}
	for x.Cmp(one) < 0 {
		x.Mul(x, ten)
		e--
	}

	// TODO(gri) Values such as 1/2 are easier to read in form 0.5
	// rather than 5.0e-1. Similarly, 1.0e1 is easier to read as
	// 10.0. Fine-tune best exponent range for readability.

	s := x.FloatString(100) // good-enough precision

	// trim trailing 0's
	i := len(s)
	for i > 0 && s[i-1] == '0' {
		i--
	}
	s = s[:i]

	// add a 0 if the number ends in decimal point
	if len(s) > 0 && s[len(s)-1] == '.' {
		s += "0"
	}

	// add exponent and sign
	if e != 0 {
		s += fmt.Sprintf("e%+d", e)
	}
	if exact.Sign(v) < 0 {
		s = "-" + s
	}

	// TODO(gri) If v is a "small" fraction (i.e., numerator and denominator
	// are just a small number of decimal digits), add the exact fraction as
	// a comment. For instance: 3.3333...e-1 /* = 1/3 */

	return s
}
// Compute 4*(1 - 1/3 + 1/5 - 1/7 + 1/9 - ...)
func main() {
	sum := big.NewRat(0, 1)
	var sumTimes4 big.Rat

	for i, sign := int64(1), int64(1); i < 10000000; i, sign = i+2, -sign {
		part := big.NewRat(sign, i)
		sum.Add(sum, part)

		if (i+1)%1000 == 0 {
			sumTimes4.Mul(big.NewRat(4, 1), sum)
			fmt.Printf("%v, %v\n", i+1, sumTimes4.FloatString(10))
		}
	}

}
Example #9
0
// getDifficultyRatio returns the proof-of-work difficulty as a multiple of the
// minimum difficulty using the passed bits field from the header of a block.
func getDifficultyRatio(bits uint32) float64 {
	// The minimum difficulty is the max possible proof-of-work limit bits
	// converted back to a number.  Note this is not the same as the the
	// proof of work limit directly because the block difficulty is encoded
	// in a block with the compact form which loses precision.
	max := btcchain.CompactToBig(activeNetParams.powLimitBits)
	target := btcchain.CompactToBig(bits)

	difficulty := new(big.Rat).SetFrac(max, target)
	outString := difficulty.FloatString(2)
	diff, err := strconv.ParseFloat(outString, 64)
	if err != nil {
		rpcsLog.Errorf("Cannot get difficulty: %v", err)
		return 0
	}
	return diff
}
Example #10
0
// hostcmd is the handler for the command `siac host`.
// Prints info about the host.
func hostcmd() {
	hg := new(api.HostGET)
	err := getAPI("/host", &hg)
	if err != nil {
		die("Could not fetch host settings:", err)
	}
	// convert accepting bool
	accept := yesNo(hg.AcceptingContracts)
	// convert price to SC/GB/mo
	price := new(big.Rat).SetInt(hg.Price.Big())
	price.Mul(price, big.NewRat(4320, 1e24/1e9))
	fmt.Printf(`Host info:
	Storage:      %v (%v used)
	Price:        %v SC per GB per month
	Max Duration: %v Blocks

	Contracts:           %v
	Accepting Contracts: %v
	Anticipated Revenue: %v
	Revenue:             %v
	Lost Revenue:        %v
`, filesizeUnits(hg.TotalStorage), filesizeUnits(hg.TotalStorage-hg.StorageRemaining),
		price.FloatString(3), hg.MaxDuration, hg.NumContracts, accept,
		hg.AnticipatedRevenue, hg.Revenue, hg.LostRevenue)

	// display more info if verbose flag is set
	if !hostVerbose {
		return
	}
	fmt.Printf(`
	Net Address: %v
	Unlock Hash: %v
	(NOT a wallet address!)

RPC Stats:
	Error Calls:        %v
	Unrecognized Calls: %v
	Download Calls:     %v
	Renew Calls:        %v
	Revise Calls:       %v
	Settings Calls:     %v
	Upload Calls:       %v
`, hg.NetAddress, hg.UnlockHash, hg.RPCErrorCalls, hg.RPCUnrecognizedCalls, hg.RPCDownloadCalls,
		hg.RPCRenewCalls, hg.RPCReviseCalls, hg.RPCSettingsCalls, hg.RPCUploadCalls)
}
Example #11
0
// Prints out account balances formated to a windows of a width of columns.
// Only shows accounts with names less than or equal to the given depth.
func PrintBalances(accountList []*ledger.Account, printZeroBalances bool, depth, columns int) {
	overallBalance := new(big.Rat)
	for _, account := range accountList {
		accDepth := len(strings.Split(account.Name, ":"))
		if accDepth == 1 {
			overallBalance.Add(overallBalance, account.Balance)
		}
		if (printZeroBalances || account.Balance.Sign() != 0) && (depth < 0 || accDepth <= depth) {
			outBalanceString := account.Balance.FloatString(ledger.DisplayPrecision)
			spaceCount := columns - len(account.Name) - len(outBalanceString)
			fmt.Printf("%s%s%s\n", account.Name, strings.Repeat(" ", spaceCount), outBalanceString)
		}
	}
	fmt.Println(strings.Repeat("-", columns))
	outBalanceString := overallBalance.FloatString(ledger.DisplayPrecision)
	spaceCount := columns - len(outBalanceString)
	fmt.Printf("%s%s\n", strings.Repeat(" ", spaceCount), outBalanceString)
}
Example #12
0
func Parse(v string) (xdr.Int64, error) {
	var f, o, r big.Rat

	_, ok := f.SetString(v)
	if !ok {
		return xdr.Int64(0), fmt.Errorf("cannot parse amount: %s", v)
	}

	o.SetInt64(One)
	r.Mul(&f, &o)

	is := r.FloatString(0)
	i, err := strconv.ParseInt(is, 10, 64)
	if err != nil {
		return xdr.Int64(0), err
	}
	return xdr.Int64(i), nil
}
Example #13
0
//"Pell Equation"
func main() {
	starttime := time.Now()

	total := 0
	for rad := 2; rad <= 100; rad++ {

		if !isSquare(rad) {

			convergentList := make([]int, 1)

			test := frac{a: 0, b: 1, R: rad, d: 1}
			n := 0

			n, test = nextFrac(test)

			convergentList[0] = n

			for i := 0; i < 200; i++ {
				n, test = nextFrac(test)
				convergentList = append(convergentList, n)

			}

			fLength := len(convergentList) - 1

			p, q := ctdFrac(convergentList[:fLength])

			var r big.Rat

			r.SetString(p + "/" + q)

			deciString := r.FloatString(105) //A bit too long in order to avoid rounding

			total += sumDigits(deciString[:101]) //The extra 1 is the decimal point
		}
	}

	fmt.Println(total)

	fmt.Println("Elapsed time:", time.Since(starttime))

}
Example #14
0
func hoststatuscmd() {
	info := new(modules.HostInfo)
	err := getAPI("/host/status", info)
	if err != nil {
		fmt.Println("Could not fetch host settings:", err)
		return
	}
	// convert price to SC/GB/mo
	price := new(big.Rat).SetInt(info.Price.Big())
	price.Mul(price, big.NewRat(4320, 1e24/1e9))
	fmt.Printf(`Host settings:
Storage:      %v (%v used)
Price:        %v SC per GB per month
Collateral:   %v
Max Filesize: %v
Max Duration: %v
Contracts:    %v
`, filesizeUnits(info.TotalStorage), filesizeUnits(info.TotalStorage-info.StorageRemaining),
		price.FloatString(3), info.Collateral, info.MaxFilesize, info.MaxDuration, info.NumContracts)
}
Example #15
0
File: p26.go Project: yzx226/Euler
func f1() {
	max := 1
	ii := 2
	for i := 2; i < 1000; i++ {
		r := new(big.Rat)
		r.SetString("1/" + strconv.Itoa(i))
		s := r.FloatString(10000)[2:9999]
		//s = strings.TrimLeft(s, "0")
		//fmt.Println(s)

		v := dup(&s)
		d := len(v)
		if max < d {
			max = d
			ii = i
			//fmt.Println(i, d, s, v)
		}
	}

	fmt.Println(ii, max)
}
Example #16
0
// Check the transaction to ensure it is balanced
func (t *Transaction) CheckBalance() error {
	if len(t.Accounts) == 0 {
		return errors.New("Transaction does not have any accounts")
	}

	// Check that they balance
	balance := new(big.Rat)
	for _, a := range t.Accounts {
		if a.Debit {
			balance.Add(balance, a.Amount)
		} else {
			balance.Sub(balance, a.Amount)
		}
	}

	b := balance.FloatString(2)
	if b != "0.00" {
		return errors.New(fmt.Sprintf("Transaction does not balance: %s", b))
	}

	return nil
}
Example #17
0
func eDigits(precisionFactor int, stringLength int) string {
	array := make([]int64, precisionFactor)
	for i := 0; i < precisionFactor; i++ {
		var t int64 = int64(i)
		array[i] = t + 1
	}

	var digitsToMultiply []int64
	var e *big.Rat = big.NewRat(1, 1)

	for i := 1; i <= precisionFactor; i++ {
		digitsToMultiply = array[0:i]
		var digitsProduct int64 = 1
		for x := 0; x < len(digitsToMultiply); x++ {
			digitsProduct = digitsProduct * digitsToMultiply[x]
		}
		var finalProduct *big.Rat = big.NewRat(1, digitsProduct)
		e.Add(e, finalProduct)
	}

	return e.FloatString(stringLength)
}
Example #18
0
// PrintRegister prints each transaction that matches the given filters.
func PrintRegister(generalLedger []*ledger.Transaction, filterArr []string, columns int) {
	// Calulate widths for variable-length part of output
	// 3 10-width columns (date, account-change, running-total)
	// 4 spaces
	remainingWidth := columns - (10 * 3) - (4 * 1)
	formatString := fmt.Sprintf("%%-10.10s %%-%[1]d.%[1]ds %%-%[2]d.%[2]ds %%10.10s %%10.10s\n", remainingWidth/3, (remainingWidth/3)*2)

	var otherAccount string
	runningBalance := new(big.Rat)
	for _, trans := range generalLedger {
		for aIdx, accChange := range trans.AccountChanges {
			inFilter := len(filterArr) == 0
			for _, filter := range filterArr {
				if strings.Contains(accChange.Name, filter) {
					inFilter = true

					// Probably not the best way, but we just need to find one other account
					if aIdx > 0 {
						otherAccount = trans.AccountChanges[0].Name
					} else {
						otherAccount = trans.AccountChanges[1].Name
					}
				}
			}
			if inFilter {
				runningBalance.Add(runningBalance, accChange.Balance)
				outBalanceString := accChange.Balance.FloatString(displayPrecision)
				outRunningBalanceString := runningBalance.FloatString(displayPrecision)
				fmt.Printf(formatString,
					trans.Date.Format(transactionDateFormat),
					trans.Payee,
					otherAccount,
					outBalanceString,
					outRunningBalanceString)
			}
		}
	}
}
Example #19
0
func (c Test) NumTest1() revel.Result {
	text := fmt.Sprint(94.85 / 100.0)
	text += "____"
	rat := big.Rat{}
	rat.SetString("94.85/100.0")
	text += rat.FloatString(10)
	text += "____"
	text += fmt.Sprint(c.getFloat("0.1") + c.getFloat("0.7"))
	text += "____"
	text += fmt.Sprint(c.getFloat("0.1") + c.getFloat("0.6"))
	text += "____"
	text += fmt.Sprint(c.getFloat("0.13") + c.getFloat("3.59"))
	text += "_dec_"
	dec1 := c.add("0.1", "0.7")
	text += dec1.String()
	text += "____"
	dec1 = c.add("0.1", "0.6")
	text += dec1.String()
	text += "____"
	dec1 = c.add("0.13", "3.59")
	text += dec1.String()
	return c.RenderText(text)
}
Example #20
0
func formatBigRat(r *big.Rat, prec int) string {
	return formatFloatString(r.FloatString(prec), prec, false)
}
Example #21
0
func GetAccountTransactions(user *User, accountid int64, sort string, page uint64, limit uint64) (*AccountTransactionsList, error) {
	var transactions []Transaction
	var atl AccountTransactionsList

	transaction, err := DB.Begin()
	if err != nil {
		return nil, err
	}

	var sqlsort, balanceLimitOffset string
	var balanceLimitOffsetArg uint64
	if sort == "date-asc" {
		sqlsort = " ORDER BY transactions.Date ASC"
		balanceLimitOffset = " LIMIT ?"
		balanceLimitOffsetArg = page * limit
	} else if sort == "date-desc" {
		numSplits, err := transaction.SelectInt("SELECT count(*) FROM splits")
		if err != nil {
			transaction.Rollback()
			return nil, err
		}
		sqlsort = " ORDER BY transactions.Date DESC"
		balanceLimitOffset = fmt.Sprintf(" LIMIT %d OFFSET ?", numSplits)
		balanceLimitOffsetArg = (page + 1) * limit
	}

	var sqloffset string
	if page > 0 {
		sqloffset = fmt.Sprintf(" OFFSET %d", page*limit)
	}

	account, err := GetAccountTx(transaction, accountid, user.UserId)
	if err != nil {
		transaction.Rollback()
		return nil, err
	}
	atl.Account = account

	sql := "SELECT DISTINCT transactions.* FROM transactions INNER JOIN splits ON transactions.TransactionId = splits.TransactionId WHERE transactions.UserId=? AND splits.AccountId=?" + sqlsort + " LIMIT ?" + sqloffset
	_, err = transaction.Select(&transactions, sql, user.UserId, accountid, limit)
	if err != nil {
		transaction.Rollback()
		return nil, err
	}
	atl.Transactions = &transactions

	var pageDifference, tmp big.Rat
	for i := range transactions {
		_, err = transaction.Select(&transactions[i].Splits, "SELECT * FROM splits where TransactionId=?", transactions[i].TransactionId)
		if err != nil {
			transaction.Rollback()
			return nil, err
		}

		// Sum up the amounts from the splits we're returning so we can return
		// an ending balance
		for j := range transactions[i].Splits {
			if transactions[i].Splits[j].AccountId == accountid {
				rat_amount, err := GetBigAmount(transactions[i].Splits[j].Amount)
				if err != nil {
					transaction.Rollback()
					return nil, err
				}
				tmp.Add(&pageDifference, rat_amount)
				pageDifference.Set(&tmp)
			}
		}
	}

	count, err := transaction.SelectInt("SELECT count(DISTINCT transactions.TransactionId) FROM transactions INNER JOIN splits ON transactions.TransactionId = splits.TransactionId WHERE transactions.UserId=? AND splits.AccountId=?", user.UserId, accountid)
	if err != nil {
		transaction.Rollback()
		return nil, err
	}
	atl.TotalTransactions = count

	security, err := GetSecurity(atl.Account.SecurityId, user.UserId)
	if err != nil {
		return nil, err
	}
	if security == nil {
		return nil, errors.New("Security not found")
	}

	// Sum all the splits for all transaction splits for this account that
	// occurred before the page we're returning
	var amounts []string
	sql = "SELECT splits.Amount FROM splits WHERE splits.AccountId=? AND splits.TransactionId IN (SELECT DISTINCT transactions.TransactionId FROM transactions INNER JOIN splits ON transactions.TransactionId = splits.TransactionId WHERE transactions.UserId=? AND splits.AccountId=?" + sqlsort + balanceLimitOffset + ")"
	_, err = transaction.Select(&amounts, sql, accountid, user.UserId, accountid, balanceLimitOffsetArg)
	if err != nil {
		transaction.Rollback()
		return nil, err
	}

	var balance big.Rat
	for _, amount := range amounts {
		rat_amount, err := GetBigAmount(amount)
		if err != nil {
			transaction.Rollback()
			return nil, err
		}
		tmp.Add(&balance, rat_amount)
		balance.Set(&tmp)
	}
	atl.BeginningBalance = balance.FloatString(security.Precision)
	atl.EndingBalance = tmp.Add(&balance, &pageDifference).FloatString(security.Precision)

	err = transaction.Commit()
	if err != nil {
		transaction.Rollback()
		return nil, err
	}

	return &atl, nil
}
Example #22
0
func formatBigRatGrouped(r *big.Rat, prec int) string {
	return formatFloatString(r.FloatString(prec), prec, true)
}
Example #23
0
// BigratToFloat converts a *big.Rat to a float64 (with loss of
// precision).
func BigratToFloat(bigrat *big.Rat) float64 {
	float_string := bigrat.FloatString(10) // arbitrary largish precision
	// no error scenario could be imagined in testing, so discard err
	float, _ := strconv.ParseFloat(float_string, 64)
	return float
}
Example #24
0
// BigratToInt converts a *big.Rat to an int64 (with truncation); it
// returns an error for integer overflows.
func BigratToInt(bigrat *big.Rat) (int64, error) {
	float_string := bigrat.FloatString(0)
	return strconv.ParseInt(float_string, 10, 64)
}
Example #25
0
func formatRat(r *big.Rat, prec int) (string, error) {
	return formatFloatString(r.FloatString(prec), prec)
}
Example #26
0
func ExampleRat_SetString() {
	r := new(big.Rat)
	r.SetString("355/113")
	fmt.Println(r.FloatString(3))
	// Output: 3.142
}
Example #27
0
// FormatNumberBigRat only supports *big.Rat value.
// It is faster than FormatNumber, because it does not do any runtime type evaluation.
func FormatNumberBigRat(x *big.Rat, precision int, thousand string, decimal string) string {
	return formatNumberString(x.FloatString(precision), precision, thousand, decimal)
}
Example #28
0
//export OFXTransactionCallback
func OFXTransactionCallback(transaction_data C.struct_OfxTransactionData, data unsafe.Pointer) C.int {
	iobj := (*ImportObject)(data)
	itl := iobj.TransactionList
	transaction := new(Transaction)

	if transaction_data.name_valid != 0 {
		transaction.Description = C.GoString(&transaction_data.name[0])
	}
	//	if transaction_data.reference_number_valid != 0 {
	//		fmt.Println("reference_number: ", C.GoString(&transaction_data.reference_number[0]))
	//	}
	if transaction_data.date_posted_valid != 0 {
		transaction.Date = time.Unix(int64(transaction_data.date_posted), 0)
	} else if transaction_data.date_initiated_valid != 0 {
		transaction.Date = time.Unix(int64(transaction_data.date_initiated), 0)
	}
	if transaction_data.fi_id_valid != 0 {
		transaction.RemoteId = C.GoString(&transaction_data.fi_id[0])
	}

	if transaction_data.amount_valid != 0 {
		split := new(Split)
		r := new(big.Rat)
		r.SetFloat64(float64(transaction_data.amount))
		security, err := GetSecurity(itl.Account.SecurityId, itl.Account.UserId)
		if err != nil {
			if iobj.Error == nil {
				iobj.Error = err
			}
			return 1
		}
		split.Amount = r.FloatString(security.Precision)
		if transaction_data.memo_valid != 0 {
			split.Memo = C.GoString(&transaction_data.memo[0])
		}
		if transaction_data.check_number_valid != 0 {
			split.Number = C.GoString(&transaction_data.check_number[0])
		}
		split.SecurityId = -1
		split.AccountId = itl.Account.AccountId
		transaction.Splits = append(transaction.Splits, split)
	} else {
		if iobj.Error == nil {
			iobj.Error = errors.New("OFX transaction amount invalid")
		}
		return 1
	}

	var security *Security
	var err error
	split := new(Split)
	units := new(big.Rat)

	if transaction_data.units_valid != 0 {
		units.SetFloat64(float64(transaction_data.units))
		if transaction_data.security_data_valid != 0 {
			security_data := transaction_data.security_data_ptr
			if security_data.ticker_valid != 0 {
				s, err := GetSecurityByName(C.GoString(&security_data.ticker[0]))
				if err != nil {
					if iobj.Error == nil {
						iobj.Error = errors.New("Failed to find OFX transaction security: " + C.GoString(&security_data.ticker[0]))
					}
					return 1
				}
				security = s
			} else {
				if iobj.Error == nil {
					iobj.Error = errors.New("OFX security ticker invalid")
				}
				return 1
			}
			if security.Type == Stock && security_data.unique_id_valid != 0 && security_data.unique_id_type_valid != 0 && C.GoString(&security_data.unique_id_type[0]) == "CUSIP" {
				// Validate the security CUSIP, if possible
				if security.AlternateId != C.GoString(&security_data.unique_id[0]) {
					if iobj.Error == nil {
						iobj.Error = errors.New("OFX transaction security CUSIP failed to validate")
					}
					return 1
				}
			}
		} else {
			security, err = GetSecurity(itl.Account.SecurityId, itl.Account.UserId)
			if err != nil {
				if iobj.Error == nil {
					iobj.Error = err
				}
				return 1
			}
		}
	} else {
		// Calculate units from other available fields if its not present
		//		units = - (amount + various fees) / unitprice
		units.SetFloat64(float64(transaction_data.amount))
		fees := new(big.Rat)
		if transaction_data.fees_valid != 0 {
			fees.SetFloat64(float64(-transaction_data.fees))
		}
		if transaction_data.commission_valid != 0 {
			commission := new(big.Rat)
			commission.SetFloat64(float64(-transaction_data.commission))
			fees.Add(fees, commission)
		}
		units.Add(units, fees)
		units.Neg(units)
		if transaction_data.unitprice_valid != 0 && transaction_data.unitprice != 0 {
			unitprice := new(big.Rat)
			unitprice.SetFloat64(float64(transaction_data.unitprice))
			units.Quo(units, unitprice)
		}

		// If 'units' wasn't present, assume we're using the account's security
		security, err = GetSecurity(itl.Account.SecurityId, itl.Account.UserId)
		if err != nil {
			if iobj.Error == nil {
				iobj.Error = err
			}
			return 1
		}
	}

	split.Amount = units.FloatString(security.Precision)
	split.SecurityId = security.SecurityId
	split.AccountId = -1
	transaction.Splits = append(transaction.Splits, split)

	if transaction_data.fees_valid != 0 {
		split := new(Split)
		r := new(big.Rat)
		r.SetFloat64(float64(-transaction_data.fees))
		security, err := GetSecurity(itl.Account.SecurityId, itl.Account.UserId)
		if err != nil {
			if iobj.Error == nil {
				iobj.Error = err
			}
			return 1
		}
		split.Amount = r.FloatString(security.Precision)
		split.Memo = "fees"
		split.SecurityId = itl.Account.SecurityId
		split.AccountId = -1
		transaction.Splits = append(transaction.Splits, split)
	}

	if transaction_data.commission_valid != 0 {
		split := new(Split)
		r := new(big.Rat)
		r.SetFloat64(float64(-transaction_data.commission))
		security, err := GetSecurity(itl.Account.SecurityId, itl.Account.UserId)
		if err != nil {
			if iobj.Error == nil {
				iobj.Error = err
			}
			return 1
		}
		split.Amount = r.FloatString(security.Precision)
		split.Memo = "commission"
		split.SecurityId = itl.Account.SecurityId
		split.AccountId = -1
		transaction.Splits = append(transaction.Splits, split)
	}

	//	if transaction_data.payee_id_valid != 0 {
	//		fmt.Println("payee_id: ", C.GoString(&transaction_data.payee_id[0]))
	//	}

	transaction_list := append(*itl.Transactions, *transaction)
	iobj.TransactionList.Transactions = &transaction_list

	return 0
}