Hi, This is my first useful Julia code so far. I should have probably started with wrapping C-code for Decimal floating point. I'm a little conflicted, I see that SymPi.jl doesn't wrap all of the Python code and I thought you could call the rest of the functions that are missing also with my code. Then if I change the implementation that wouldn't work.. Right? Would macros help?
Is there something missing to fully be Julian? Do not care about sin, cos.. etc. https://github.com/quinnj/ODBC.jl/blob/master/src/ODBC_Types.jl typealias SQLDECIMAL Cdouble typealias SQLNUMERIC Cdouble module Dec_m using PyCall import Base.show #import Base.parsefloat # Not sure if it is appropriate to extend this/these one #import Base.parseint @pyimport decimal as d @pyimport operator as o export @D_str, Dec #immediate? type Dec <: Number # Or FloatingPoint? n::PyObject # Can I allow just Decimal not all PyObjects? Dec(s::String) = new(d.Decimal(s)) Dec(s::PyObject) = new(s) # missing check to see if PyObject is Decimal (or a better way?) Dec(s::Integer) = new(string(s)) # Right way to "call" other constructor or use promote? end +(a::Dec, b::Dec) = Dec(o.add(a.n, b.n)) -(a::Dec, b::Dec) = Dec(o.sub(a.n, b.n)) *(a::Dec, b::Dec) = Dec(o.mul(a.n, b.n)) /(a::Dec, b::Dec) = Dec(o.div(a.n, b.n)) # Return Decimal or maybe even better a rational type..? NOT better to return floating point "to conform"? #Int32 or Integer better? Ran into trouble either way.. <<(a::Dec, b::Int64) = a * (1 << b) # I could chop the quotes off but maybe I'm doing this wrong, wrong Python function? function show(io::IO, x::Dec) show(io, x.n[:__str__]()) end # can use D"literal number" as short for Dec("number"). Better to use lower case d? macro D_str(s) Dec(s) end end Can stop reading here.. But interesting info to me below.. # from_float(f) # Classmethod that converts a float to a decimal number, exactly. # normalize([context]) # Normalize the number by stripping the rightmost trailing zeros #Why? Should if be defined for binary floating point? # radix() Return Decimal(10), the radix (base) in which the Decimal class does all its arithmetic. Included for compatibility with the specification. #not sure if ___cmp___ way of Python is used in Julia. Neither if decimal's compare (and maybe related) needs to be implemented. #https://docs.python.org/2/reference/datamodel.html#object.__cmp__ #"There are no implied relationships among the comparison operators. The truth of x==y does not imply that x!=y is false." # __nonzero__ and __unicode__ ?! #Not sure I can just override (and if mine is imported first?): https://github.com/quinnj/ODBC.jl/blob/master/src/ODBC_Types.jl typealias SQLDECIMAL Dec typealias SQLNUMERIC Dec # https://github.com/JuliaLang/julia/blob/master/base/rational.jl function convert{T<:Integer}(::Type{Rational{T}}, x::FloatingPoint) r = rationalize(T, x, tol=0) x == convert(typeof(x), r) || throw(InexactError()) r end end convert(::Type{Rational}, x::Float64) = convert(Rational{Int64}, x) convert(::Type{Rational}, x::Float32) = convert(Rational{Int}, x) promote_rule{T<:Integer,S<:Integer}(::Type{Rational{T}}, ::Type{S}) = Rational{promote_type(T,S)} promote_rule{T<:Integer,S<:Integer}(::Type{Rational{T}}, ::Type{Rational{S}}) = Rational{promote_type(T,S)} promote_rule{T<:Integer,S<:FloatingPoint}(::Type{Rational{T}}, ::Type{S}) = promote_type(T,S) widen{T}(::Type{Rational{T}}) = Rational{widen(T)} sign(x::Rational) = sign(x.num) signbit(x::Rational) = signbit(x.num) copysign(x::Rational, y::Real) = copysign(x.num,y) // x.den copysign(x::Rational, y::Rational) = copysign(x.num,y.num) // x.den typemin{T<:Integer}(::Type{Rational{T}}) = -one(T)//zero(T) typemax{T<:Integer}(::Type{Rational{T}}) = one(T)//zero(T) isinteger(x::Rational) = x.den == 1 #Python has a lot of functions including some unexpected: #https://docs.python.org/2/library/decimal.html #logical_or(other[, context]) #logical_xor(other[, context]) #normalize([context])¶ # Normalize the number by stripping the rightmost trailing zeros and converting any result equal to Decimal('0') to Decimal('0e0'). Used for # producing canonical values for attributes of an equivalence class. For example, Decimal('32.100') and Decimal('0.321000e+2') both normalize to the # equivalent value Decimal('32.1'). # radix() # Return Decimal(10), the radix (base) in which the Decimal class does all its arithmetic. Included for compatibility with the specification. # quantize(exp[, rounding[, context[, watchexp]]]) # Return a value equal to the first operand after rounding and having the exponent of the second operand. # to_eng_string([context]) # Convert to an engineering-type string. # Engineering notation has an exponent which is a multiple of 3, so there are up to 3 digits left of the decimal place. For example, converts Decimal('123E+1') to Decimal('1.23E+3') # compare(other[, context]) # Compare the values of two Decimal instances. This operation behaves in the same way as the usual comparison method __cmp__(), except that compare() returns a Decimal instance rather than an integer, and if either operand is a NaN then the result is a NaN: Just not sure about quite vs. signaling NaN.. # compare_signal(other[, context]) #compare_total(other) #compare_total_mag(other # conjugate() # Just returns self, this method is only to comply with the Decimal Specification. # is_canonical() # Return True if the argument is canonical and False otherwise. Currently, a Decimal instance is always canonical, so this operation always returns True. # ???! # rotate(other[, context]) decimal.getcontext() Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999, capitals=1, flags=[], traps=[Overflow, InvalidOperation, DivisionByZero]) class decimal.Context(prec=None, rounding=None, traps=None, flags=None, Emin=None, Emax=None, capitals=1) Creates a new context. If a field is not specified or is None, the default values are copied from the DefaultContext. If the flags field is not specified or is None, all flags are cleared. The prec field is a positive integer that sets the precision for arithmetic operations in the context. The rounding option is one of: ROUND_CEILING (towards Infinity), ROUND_DOWN (towards zero), ROUND_FLOOR (towards -Infinity), ROUND_HALF_DOWN (to nearest with ties going towards zero), ROUND_HALF_EVEN (to nearest with ties going to nearest even integer), ROUND_HALF_UP (to nearest with ties going away from zero), or ROUND_UP (away from zero). ROUND_05UP (away from zero if last digit after rounding towards zero would have been 0 or 5; otherwise towards zero) If value is a unicode string then other Unicode decimal digits are also permitted where digit appears above. These include decimal digits from various other alphabets (for example, Arabic-Indic and Devanāgarī digits) along with the fullwidth digits u'\uff10' through u'\uff19'. If value is a float, the binary floating point value is losslessly converted to its exact decimal equivalent. This conversion can often require 53 or more digits of precision. For example, Decimal(float('1.1')) converts to Decimal('1.100000000000000088817841970012523233890533447265625'). Once constructed, Decimal objects are immutable. Decimal floating point objects share many properties with the other built-in numeric types such as float and int. All of the usual math operations and special methods apply. Likewise, decimal objects can be copied, pickled, printed, used as dictionary keys, used as set elements, compared, sorted, and coerced to another type (such as float or long). Decimal objects cannot generally be combined with floats in arithmetic operations: an attempt to add a Decimal to a float, for example, will raise a TypeError. There’s one exception to this rule: it’s possible to use Python’s comparison operators to compare a float instance x with a Decimal instance y. Without this exception, comparisons between Decimal and float instances would follow the general rules for comparing objects of different types described in the Expressions section of the reference manual, leading to confusing results. >>> D = decimal.Decimal >>> D('1.23') + D('3.45') Decimal('4.68') julia> u, v, w = Dec("11111113"), Dec("-11111111"), Dec("7.51111111") (Error showing value of type (Dec,Dec,Dec): ERROR: stack overflow in show at none:2 (repeats 513 times)