Skip to content

Commit

Permalink
Add rational type.
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelmacinnis committed Apr 14, 2015
1 parent 6fe337a commit 4ebf85d
Show file tree
Hide file tree
Showing 8 changed files with 55 additions and 70 deletions.
4 changes: 2 additions & 2 deletions MANUAL.md
Expand Up @@ -232,7 +232,7 @@ appropriate. For example,

produces the output,

14.44
361/25

#### Booleans

Expand Down Expand Up @@ -610,7 +610,7 @@ with Mice").
define line = ""
while count {
define p: car: read
set line = line ^ ("%7d"::sprintf p)
set line = line ^ ("%7.7s"::sprintf p)
set count: sub count 1
if (not: mod count 10) {
echo line
Expand Down
92 changes: 35 additions & 57 deletions cell.go
Expand Up @@ -92,8 +92,8 @@ var (
False *Boolean
True *Boolean

max *big.Int
min *big.Int
max *big.Rat
min *big.Rat
num [512]*Integer
one *big.Rat
rat [512]*Rational
Expand All @@ -104,8 +104,8 @@ var (
)

func init() {
max = big.NewInt(255)
min = big.NewInt(-256)
max = big.NewRat(255, 1)
min = big.NewRat(-256, 1)

one = big.NewRat(1, 1)
zero = big.NewRat(0, 1)
Expand Down Expand Up @@ -278,7 +278,7 @@ func IsNumber(c Cell) bool {
case Number:
return true
case *Symbol:
return t.isFloat() || t.isInt()
return t.isNumeric()
}
return false
}
Expand Down Expand Up @@ -1002,26 +1002,28 @@ func IsRational(c Cell) bool {
return false
}

func NewRational(v *big.Rat) *Rational {
if !v.IsInt() {
return &Rational{v}
}
func NewRational(r *big.Rat) *Rational {
return &Rational{r}

iv := v.Num()
if iv.Cmp(min) >= 0 && iv.Cmp(max) <= 0 {
n := iv.Int64() + 256
p := rat[n]
/*
TODO: Fix caching
if p.v == nil {
p := &Rational{v}
if !r.IsInt() || r.Cmp(min) < 0 || r.Cmp(max) > 0 {
return &Rational{r}
}
rat[n] = p
}
n := r.Num().Int64() + 256
p := rat[n]
return p
if p == nil {
println("Allocating:", r.Num().Int64())
p := &Rational{r}
rat[n] = p
}
return &Rational{v}
return p
*/
}

func (r *Rational) Bool() bool {
Expand Down Expand Up @@ -1379,62 +1381,38 @@ func (s *Symbol) Less(c Cell) bool {
}

func (s *Symbol) Add(c Cell) Number {
if s.isInt() {
return NewInteger(s.Int() + c.(Atom).Int())
} else if s.isFloat() {
return NewFloat(s.Float() + c.(Atom).Float())
}

panic("type 'symbol' does not implement 'add'")
return NewRational(new(big.Rat).Add(s.Rat(), c.(Atom).Rat()))
}

func (s *Symbol) Divide(c Cell) Number {
if s.isInt() {
return NewInteger(s.Int() / c.(Atom).Int())
} else if s.isFloat() {
return NewFloat(s.Float() / c.(Atom).Float())
}

panic("type 'symbol' does not implement 'div'")
return NewRational(new(big.Rat).Quo(s.Rat(), c.(Atom).Rat()))
}

func (s *Symbol) Modulo(c Cell) Number {
if s.isInt() {
return NewInteger(s.Int() % c.(Atom).Int())
x := s.Rat()
y := c.(Atom).Rat()

if x.IsInt() && y.IsInt() {
z := new(big.Rat).SetInt(new(big.Int).Mod(x.Num(), y.Num()))
return NewRational(z)
}

panic("type 'symbol' does not implement 'mod'")
panic("operation not permitted")
}

func (s *Symbol) Multiply(c Cell) Number {
if s.isInt() {
return NewInteger(s.Int() * c.(Atom).Int())
} else if s.isFloat() {
return NewFloat(s.Float() * c.(Atom).Float())
}

panic("type 'symbol' does not implement 'multiply'")
return NewRational(new(big.Rat).Mul(s.Rat(), c.(Atom).Rat()))
}

func (s *Symbol) Subtract(c Cell) Number {
if s.isInt() {
return NewInteger(s.Int() - c.(Atom).Int())
} else if s.isFloat() {
return NewFloat(s.Float() - c.(Atom).Float())
}

panic("type 'symbol' does not implement 'subtract'")
return NewRational(new(big.Rat).Sub(s.Rat(), c.(Atom).Rat()))
}

/* Symbol-specific functions. */

func (s *Symbol) isFloat() bool {
_, err := strconv.ParseFloat(string(*s), 64)
return err == nil
}

func (s *Symbol) isInt() bool {
_, err := strconv.ParseInt(string(*s), 0, 64)
func (s *Symbol) isNumeric() bool {
r := new(big.Rat)
_, err := fmt.Sscan(string(*s), r)
return err == nil
}

Expand Down
16 changes: 8 additions & 8 deletions doctest/232-types-integers-manual.oh
Expand Up @@ -100,20 +100,20 @@ for operators: method (name) as {
#- add 4 3 => 7
#- add 4 4 => 8
#- div 1 1 => 1
#- div 1 2 => 0
#- div 1 3 => 0
#- div 1 4 => 0
#- div 1 2 => 1/2
#- div 1 3 => 1/3
#- div 1 4 => 1/4
#- div 2 1 => 2
#- div 2 2 => 1
#- div 2 3 => 0
#- div 2 4 => 0
#- div 2 3 => 2/3
#- div 2 4 => 1/2
#- div 3 1 => 3
#- div 3 2 => 1
#- div 3 2 => 3/2
#- div 3 3 => 1
#- div 3 4 => 0
#- div 3 4 => 3/4
#- div 4 1 => 4
#- div 4 2 => 2
#- div 4 3 => 1
#- div 4 3 => 4/3
#- div 4 4 => 1
#- eq 1 1 => true
#- eq 1 2 => false
Expand Down
2 changes: 1 addition & 1 deletion doctest/233-types-floats-manual.oh
Expand Up @@ -30,7 +30,7 @@ write: add 3.14 2.72 1.41 2.50 4.67
##
## produces the output,
##
#+ 14.44
#+ 361/25
##

define x: float -1
Expand Down
2 changes: 1 addition & 1 deletion doctest/288-channels-manual.oh
Expand Up @@ -47,7 +47,7 @@ printf "The first %d prime numbers" count
define line = ""
while count {
define p: car: read
set line = line ^ ("%7d"::sprintf p)
set line = line ^ ("%7.7s"::sprintf p)
set count: sub count 1
if (not: mod count 10) {
echo line
Expand Down
3 changes: 2 additions & 1 deletion generate/go.oh
Expand Up @@ -4,7 +4,8 @@ define t: quote: (is-atom IsAtom) (is-boolean IsBoolean) \
(is-builtin IsBuiltin) (is-channel IsChannel) \
(is-cons IsCons) (is-float IsFloat) (is-integer IsInteger) \
(is-method IsMethod) (is-null IsNull) (is-number IsNumber) \
(is-object IsContext) (is-pipe IsPipe) (is-status IsStatus) \
(is-object IsContext) (is-pipe IsPipe) \
(is-rational IsRational) (is-status IsStatus) \
(is-string IsString) (is-symbol IsSymbol) (is-syntax IsSyntax)

define introduction: method (name) as {
Expand Down
3 changes: 3 additions & 0 deletions predicates.go
Expand Up @@ -41,6 +41,9 @@ func bind_predicates(s *Scope) {
s.DefineMethod("is-pipe", func(t *Task, args Cell) bool {
return t.Return(NewBoolean(IsPipe(Car(args))))
})
s.DefineMethod("is-rational", func(t *Task, args Cell) bool {
return t.Return(NewBoolean(IsRational(Car(args))))
})
s.DefineMethod("is-status", func(t *Task, args Cell) bool {
return t.Return(NewBoolean(IsStatus(Car(args))))
})
Expand Down
3 changes: 3 additions & 0 deletions task.go
Expand Up @@ -890,6 +890,9 @@ func RootScope() *Scope {
scope0.DefineMethod("pipe", func(t *Task, args Cell) bool {
return t.Return(NewPipe(t.Lexical, nil, nil))
})
scope0.DefineMethod("rational", func(t *Task, args Cell) bool {
return t.Return(NewRational(Car(args).(Atom).Rat()))
})
scope0.DefineMethod("status", func(t *Task, args Cell) bool {
return t.Return(NewStatus(Car(args).(Atom).Status()))
})
Expand Down

0 comments on commit 4ebf85d

Please sign in to comment.