abachrome 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.envrc +3 -0
- data/README.md +10 -0
- data/Rakefile +15 -0
- data/devenv.lock +88 -17
- data/devenv.nix +2 -1
- data/devenv.yaml +5 -12
- data/lib/abachrome/abc_decimal.rb +201 -7
- data/lib/abachrome/color.rb +88 -1
- data/lib/abachrome/color_mixins/blend.rb +53 -2
- data/lib/abachrome/color_mixins/lighten.rb +49 -2
- data/lib/abachrome/color_mixins/to_colorspace.rb +67 -2
- data/lib/abachrome/color_mixins/to_lrgb.rb +70 -2
- data/lib/abachrome/color_mixins/to_oklab.rb +67 -2
- data/lib/abachrome/color_mixins/to_oklch.rb +60 -2
- data/lib/abachrome/color_mixins/to_srgb.rb +77 -2
- data/lib/abachrome/color_models/hsv.rb +25 -2
- data/lib/abachrome/color_models/lms.rb +34 -0
- data/lib/abachrome/color_models/oklab.rb +19 -2
- data/lib/abachrome/color_models/oklch.rb +42 -2
- data/lib/abachrome/color_models/rgb.rb +28 -2
- data/lib/abachrome/color_models/xyz.rb +28 -0
- data/lib/abachrome/color_space.rb +88 -2
- data/lib/abachrome/converter.rb +56 -2
- data/lib/abachrome/converters/base.rb +69 -2
- data/lib/abachrome/converters/lms_to_lrgb.rb +36 -0
- data/lib/abachrome/converters/lms_to_srgb.rb +23 -0
- data/lib/abachrome/converters/lms_to_xyz.rb +30 -0
- data/lib/abachrome/converters/lrgb_to_lms.rb +0 -0
- data/lib/abachrome/converters/lrgb_to_oklab.rb +28 -2
- data/lib/abachrome/converters/lrgb_to_srgb.rb +27 -2
- data/lib/abachrome/converters/lrgb_to_xyz.rb +29 -0
- data/lib/abachrome/converters/oklab_to_lms.rb +41 -0
- data/lib/abachrome/converters/oklab_to_lrgb.rb +56 -29
- data/lib/abachrome/converters/oklab_to_oklch.rb +31 -2
- data/lib/abachrome/converters/oklab_to_srgb.rb +27 -2
- data/lib/abachrome/converters/oklch_to_lrgb.rb +66 -6
- data/lib/abachrome/converters/oklch_to_oklab.rb +29 -4
- data/lib/abachrome/converters/oklch_to_srgb.rb +26 -2
- data/lib/abachrome/converters/oklch_to_xyz.rb +66 -0
- data/lib/abachrome/converters/srgb_to_lrgb.rb +26 -2
- data/lib/abachrome/converters/srgb_to_oklab.rb +28 -2
- data/lib/abachrome/converters/srgb_to_oklch.rb +27 -2
- data/lib/abachrome/converters/xyz_to_lms.rb +30 -0
- data/lib/abachrome/converters/xyz_to_oklab.rb +38 -0
- data/lib/abachrome/gamut/base.rb +2 -2
- data/lib/abachrome/gamut/p3.rb +2 -2
- data/lib/abachrome/gamut/rec2020.rb +2 -2
- data/lib/abachrome/gamut/srgb.rb +20 -2
- data/lib/abachrome/illuminants/base.rb +2 -2
- data/lib/abachrome/illuminants/d50.rb +2 -2
- data/lib/abachrome/illuminants/d55.rb +2 -2
- data/lib/abachrome/illuminants/d65.rb +2 -2
- data/lib/abachrome/illuminants/d75.rb +2 -2
- data/lib/abachrome/named/css.rb +149 -158
- data/lib/abachrome/outputs/css.rb +2 -2
- data/lib/abachrome/palette.rb +112 -2
- data/lib/abachrome/palette_mixins/interpolate.rb +20 -2
- data/lib/abachrome/palette_mixins/resample.rb +2 -2
- data/lib/abachrome/palette_mixins/stretch_luminance.rb +2 -2
- data/lib/abachrome/parsers/hex.rb +2 -2
- data/lib/abachrome/to_abcd.rb +10 -2
- data/lib/abachrome/version.rb +2 -2
- data/lib/abachrome.rb +78 -2
- data/logo.png +0 -0
- data/logo.webp +0 -0
- metadata +26 -67
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a33e1980f4b275bc95646259d6c71b01715d2a77f019828b2c05ea98b24826d8
|
4
|
+
data.tar.gz: 896c1479708b87a3862bc28bdbb1959aefc0bcb3619604980096f34ed7dd07e9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e6923ce91856cf5261cc52613c1e6eacd70e0fb9c3f7a1a2fe4f248b04ea326530ca8e6b56e84f07d4cc7f663ed61fb469c35ab1247ca40f6efeeb22b28952c3
|
7
|
+
data.tar.gz: db5e02222ce2f664086a1deb5b2a4cf878c3e285c9053b652935b45688cac1d64286987b5bca0a02a0a8a884110996a2f071d283ac5df3b94f8d8722a620aef7
|
data/.envrc
ADDED
data/README.md
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
Abachrome is a Ruby gem for parsing, manipulating, and managing colors. It provides a robust set of tools for working with various color formats including hex, RGB, HSL, and named colors.
|
4
4
|
|
5
|
+

|
6
|
+
|
5
7
|
## Installation
|
6
8
|
|
7
9
|
Add this line to your application's Gemfile:
|
@@ -97,3 +99,11 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/durabl
|
|
97
99
|
|
98
100
|
We'd like to thank the excellent Color.js and culori color libraries, which helped inspire this project and
|
99
101
|
inform its design.
|
102
|
+
|
103
|
+
# Commercial Support
|
104
|
+
|
105
|
+
Commercial support for this tool is available from Durable Programming, LLC. You can find out more at [durableprogramming.com](https://durableprogramming.com/) or via email at [commercial@durableprogramming.com](mailto:commercial@durableprogramming.com).
|
106
|
+
|
107
|
+
# Copyright
|
108
|
+
|
109
|
+
Copyright 2025, Durable Programming LLC. All rights reserved.
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bundler/gem_tasks"
|
4
|
+
require "minitest/test_task"
|
5
|
+
|
6
|
+
Minitest::TestTask.create do |t|
|
7
|
+
|
8
|
+
t.test_prelude = %(require "simplecov"; SimpleCov.start { add_filter %p }) % ['/test/']
|
9
|
+
t.test_globs = FileList["test/**/*_test.rb", 'test/**/test_*.rb']
|
10
|
+
t.framework = %(require "test/test_helper.rb")
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
task default: :test
|
15
|
+
|
data/devenv.lock
CHANGED
@@ -3,10 +3,10 @@
|
|
3
3
|
"devenv": {
|
4
4
|
"locked": {
|
5
5
|
"dir": "src/modules",
|
6
|
-
"lastModified":
|
6
|
+
"lastModified": 1749202057,
|
7
7
|
"owner": "cachix",
|
8
8
|
"repo": "devenv",
|
9
|
-
"rev": "
|
9
|
+
"rev": "1c28c31f09f8a5ab134e1943b29b9d2f302cfbcd",
|
10
10
|
"type": "github"
|
11
11
|
},
|
12
12
|
"original": {
|
@@ -19,10 +19,10 @@
|
|
19
19
|
"flake-compat": {
|
20
20
|
"flake": false,
|
21
21
|
"locked": {
|
22
|
-
"lastModified":
|
22
|
+
"lastModified": 1747046372,
|
23
23
|
"owner": "edolstra",
|
24
24
|
"repo": "flake-compat",
|
25
|
-
"rev": "
|
25
|
+
"rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885",
|
26
26
|
"type": "github"
|
27
27
|
},
|
28
28
|
"original": {
|
@@ -31,10 +31,63 @@
|
|
31
31
|
"type": "github"
|
32
32
|
}
|
33
33
|
},
|
34
|
+
"flake-compat_2": {
|
35
|
+
"flake": false,
|
36
|
+
"locked": {
|
37
|
+
"lastModified": 1747046372,
|
38
|
+
"owner": "edolstra",
|
39
|
+
"repo": "flake-compat",
|
40
|
+
"rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885",
|
41
|
+
"type": "github"
|
42
|
+
},
|
43
|
+
"original": {
|
44
|
+
"owner": "edolstra",
|
45
|
+
"repo": "flake-compat",
|
46
|
+
"type": "github"
|
47
|
+
}
|
48
|
+
},
|
49
|
+
"flake-utils": {
|
50
|
+
"inputs": {
|
51
|
+
"systems": "systems"
|
52
|
+
},
|
53
|
+
"locked": {
|
54
|
+
"lastModified": 1731533236,
|
55
|
+
"owner": "numtide",
|
56
|
+
"repo": "flake-utils",
|
57
|
+
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
58
|
+
"type": "github"
|
59
|
+
},
|
60
|
+
"original": {
|
61
|
+
"owner": "numtide",
|
62
|
+
"repo": "flake-utils",
|
63
|
+
"type": "github"
|
64
|
+
}
|
65
|
+
},
|
66
|
+
"git-hooks": {
|
67
|
+
"inputs": {
|
68
|
+
"flake-compat": "flake-compat",
|
69
|
+
"gitignore": "gitignore",
|
70
|
+
"nixpkgs": [
|
71
|
+
"nixpkgs"
|
72
|
+
]
|
73
|
+
},
|
74
|
+
"locked": {
|
75
|
+
"lastModified": 1747372754,
|
76
|
+
"owner": "cachix",
|
77
|
+
"repo": "git-hooks.nix",
|
78
|
+
"rev": "80479b6ec16fefd9c1db3ea13aeb038c60530f46",
|
79
|
+
"type": "github"
|
80
|
+
},
|
81
|
+
"original": {
|
82
|
+
"owner": "cachix",
|
83
|
+
"repo": "git-hooks.nix",
|
84
|
+
"type": "github"
|
85
|
+
}
|
86
|
+
},
|
34
87
|
"gitignore": {
|
35
88
|
"inputs": {
|
36
89
|
"nixpkgs": [
|
37
|
-
"
|
90
|
+
"git-hooks",
|
38
91
|
"nixpkgs"
|
39
92
|
]
|
40
93
|
},
|
@@ -53,10 +106,10 @@
|
|
53
106
|
},
|
54
107
|
"nixpkgs": {
|
55
108
|
"locked": {
|
56
|
-
"lastModified":
|
109
|
+
"lastModified": 1746807397,
|
57
110
|
"owner": "cachix",
|
58
111
|
"repo": "devenv-nixpkgs",
|
59
|
-
"rev": "
|
112
|
+
"rev": "c5208b594838ea8e6cca5997fbf784b7cca1ca90",
|
60
113
|
"type": "github"
|
61
114
|
},
|
62
115
|
"original": {
|
@@ -66,32 +119,50 @@
|
|
66
119
|
"type": "github"
|
67
120
|
}
|
68
121
|
},
|
69
|
-
"
|
122
|
+
"nixpkgs-ruby": {
|
70
123
|
"inputs": {
|
71
|
-
"flake-compat": "flake-
|
72
|
-
"
|
124
|
+
"flake-compat": "flake-compat_2",
|
125
|
+
"flake-utils": "flake-utils",
|
73
126
|
"nixpkgs": [
|
74
127
|
"nixpkgs"
|
75
128
|
]
|
76
129
|
},
|
77
130
|
"locked": {
|
78
|
-
"lastModified":
|
79
|
-
"owner": "
|
80
|
-
"repo": "
|
81
|
-
"rev": "
|
131
|
+
"lastModified": 1747288354,
|
132
|
+
"owner": "bobvanderlinden",
|
133
|
+
"repo": "nixpkgs-ruby",
|
134
|
+
"rev": "5d7598f3059fff0cbd0dc4756f9d87f8cb7f3f7c",
|
82
135
|
"type": "github"
|
83
136
|
},
|
84
137
|
"original": {
|
85
|
-
"owner": "
|
86
|
-
"repo": "
|
138
|
+
"owner": "bobvanderlinden",
|
139
|
+
"repo": "nixpkgs-ruby",
|
87
140
|
"type": "github"
|
88
141
|
}
|
89
142
|
},
|
90
143
|
"root": {
|
91
144
|
"inputs": {
|
92
145
|
"devenv": "devenv",
|
146
|
+
"git-hooks": "git-hooks",
|
93
147
|
"nixpkgs": "nixpkgs",
|
94
|
-
"
|
148
|
+
"nixpkgs-ruby": "nixpkgs-ruby",
|
149
|
+
"pre-commit-hooks": [
|
150
|
+
"git-hooks"
|
151
|
+
]
|
152
|
+
}
|
153
|
+
},
|
154
|
+
"systems": {
|
155
|
+
"locked": {
|
156
|
+
"lastModified": 1681028828,
|
157
|
+
"owner": "nix-systems",
|
158
|
+
"repo": "default",
|
159
|
+
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
160
|
+
"type": "github"
|
161
|
+
},
|
162
|
+
"original": {
|
163
|
+
"owner": "nix-systems",
|
164
|
+
"repo": "default",
|
165
|
+
"type": "github"
|
95
166
|
}
|
96
167
|
}
|
97
168
|
},
|
data/devenv.nix
CHANGED
@@ -5,9 +5,10 @@
|
|
5
5
|
env.GREET = "devenv";
|
6
6
|
|
7
7
|
# https://devenv.sh/packages/
|
8
|
-
packages = [ pkgs.git
|
8
|
+
packages = [ pkgs.git];
|
9
9
|
|
10
10
|
languages.ruby.enable = true;
|
11
|
+
languages.ruby.version = "3.3.2";
|
11
12
|
|
12
13
|
languages.javascript.enable = true;
|
13
14
|
languages.javascript.npm.enable = true;
|
data/devenv.yaml
CHANGED
@@ -1,15 +1,8 @@
|
|
1
|
-
# yaml-language-server: $schema=https://devenv.sh/devenv.schema.json
|
2
1
|
inputs:
|
3
2
|
nixpkgs:
|
4
3
|
url: github:cachix/devenv-nixpkgs/rolling
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
# permittedInsecurePackages:
|
11
|
-
# - "openssl-1.1.1w"
|
12
|
-
|
13
|
-
# If you have more than one devenv you can merge them
|
14
|
-
#imports:
|
15
|
-
# - ./backend
|
4
|
+
nixpkgs-ruby:
|
5
|
+
url: github:bobvanderlinden/nixpkgs-ruby
|
6
|
+
inputs:
|
7
|
+
nixpkgs:
|
8
|
+
follows: nixpkgs
|
@@ -1,4 +1,17 @@
|
|
1
|
-
#
|
1
|
+
# Abachrome::AbcDecimal - High-precision decimal arithmetic for color calculations
|
2
|
+
#
|
3
|
+
# This class provides a wrapper around Ruby's BigDecimal to ensure consistent precision
|
4
|
+
# across color space conversions and calculations. It handles the precision requirements
|
5
|
+
# needed for accurate color manipulation while providing a convenient interface that
|
6
|
+
# supports standard arithmetic operations and type coercion.
|
7
|
+
#
|
8
|
+
# The class is designed to work seamlessly with Ruby's numeric types while maintaining
|
9
|
+
# the high precision necessary for color science calculations. It includes methods for
|
10
|
+
# conversion between different numeric representations and implements the full set of
|
11
|
+
# comparison and arithmetic operators.
|
12
|
+
#
|
13
|
+
# Default precision can be configured via the ABC_DECIMAL_PRECISION environment variable,
|
14
|
+
# falling back to 24 significant digits if not specified.
|
2
15
|
|
3
16
|
require "bigdecimal"
|
4
17
|
require "forwardable"
|
@@ -10,8 +23,17 @@ module Abachrome
|
|
10
23
|
|
11
24
|
attr_accessor :value, :precision
|
12
25
|
|
13
|
-
def_delegators :@value, :to_i, :
|
14
|
-
|
26
|
+
def_delegators :@value, :to_i, :zero?, :nonzero?, :finite?
|
27
|
+
|
28
|
+
# Initializes a new AbcDecimal object with the specified value and precision.
|
29
|
+
#
|
30
|
+
# @param value [AbcDecimal, BigDecimal, Rational, #to_s] The numeric value to represent.
|
31
|
+
# If an AbcDecimal is provided, its internal value is used.
|
32
|
+
# If a BigDecimal or Rational is provided, it's used directly.
|
33
|
+
# Otherwise, the value is converted to a string and parsed as a BigDecimal.
|
34
|
+
# @param precision [Integer] The decimal precision to use (number of significant digits).
|
35
|
+
# Defaults to DEFAULT_PRECISION.
|
36
|
+
# @return [AbcDecimal] A new AbcDecimal instance.
|
15
37
|
def initialize(value, precision = DEFAULT_PRECISION)
|
16
38
|
@precision = precision
|
17
39
|
@value = case value
|
@@ -26,6 +48,13 @@ module Abachrome
|
|
26
48
|
end
|
27
49
|
end
|
28
50
|
|
51
|
+
# Returns a string representation of the decimal value.
|
52
|
+
#
|
53
|
+
# This method converts the internal value to a String, using a fixed-point
|
54
|
+
# notation format. If the internal value is a Rational, it's first converted
|
55
|
+
# to a BigDecimal with the configured precision before string conversion.
|
56
|
+
#
|
57
|
+
# @return [String] The decimal value as a string in fixed-point notation
|
29
58
|
def to_s
|
30
59
|
if @value.is_a?(Rational)
|
31
60
|
BigDecimal(@value, precision).to_s("F")
|
@@ -34,55 +63,127 @@ module Abachrome
|
|
34
63
|
end
|
35
64
|
end
|
36
65
|
|
66
|
+
# Converts the decimal value to a floating-point number.
|
67
|
+
#
|
68
|
+
# @return [Float] the floating-point representation of the AbcDecimal value
|
37
69
|
def to_f
|
38
70
|
@value.to_f
|
39
71
|
end
|
40
72
|
|
73
|
+
# Creates a new AbcDecimal from a string representation of a number.
|
74
|
+
#
|
75
|
+
# @param str [String] The string representation of a number to convert to an AbcDecimal
|
76
|
+
# @param precision [Integer] The precision to use for the decimal value (number of significant digits after the decimal point). Defaults to DEFAULT_PRECISION
|
77
|
+
# @return [AbcDecimal] A new AbcDecimal instance initialized with the given string value and precision
|
41
78
|
def self.from_string(str, precision = DEFAULT_PRECISION)
|
42
79
|
new(str, precision)
|
43
80
|
end
|
44
81
|
|
82
|
+
# Creates a new AbcDecimal from a Rational number.
|
83
|
+
#
|
84
|
+
# @param rational [Rational] The rational number to convert to an AbcDecimal
|
85
|
+
# @param precision [Integer] The precision to use for the decimal representation, defaults to DEFAULT_PRECISION
|
86
|
+
# @return [AbcDecimal] A new AbcDecimal instance with the value of the given rational number
|
45
87
|
def self.from_rational(rational, precision = DEFAULT_PRECISION)
|
46
88
|
new(rational, precision)
|
47
89
|
end
|
48
90
|
|
91
|
+
# Creates a new AbcDecimal instance from a float value.
|
92
|
+
#
|
93
|
+
# @param float [Float] The floating point number to convert to an AbcDecimal
|
94
|
+
# @param precision [Integer] The precision to use for the decimal representation (default: DEFAULT_PRECISION)
|
95
|
+
# @return [AbcDecimal] A new AbcDecimal instance representing the given float value
|
49
96
|
def self.from_float(float, precision = DEFAULT_PRECISION)
|
50
97
|
new(float, precision)
|
51
98
|
end
|
52
99
|
|
100
|
+
# Creates a new AbcDecimal from an integer value.
|
101
|
+
#
|
102
|
+
# @param integer [Integer] The integer value to convert to an AbcDecimal
|
103
|
+
# @param precision [Integer] The precision to use for the decimal, defaults to DEFAULT_PRECISION
|
104
|
+
# @return [AbcDecimal] A new AbcDecimal instance with the specified integer value and precision
|
53
105
|
def self.from_integer(integer, precision = DEFAULT_PRECISION)
|
54
106
|
new(integer, precision)
|
55
107
|
end
|
56
108
|
|
109
|
+
# # Addition operation
|
110
|
+
# #
|
111
|
+
# # Adds another value to this decimal.
|
112
|
+
# #
|
113
|
+
# # @param other [AbcDecimal, Numeric] The value to add. If not an AbcDecimal,
|
114
|
+
# # it will be converted to one.
|
115
|
+
# # @return [AbcDecimal] A new AbcDecimal instance with the sum of the two values
|
57
116
|
def +(other)
|
58
117
|
other_value = other.is_a?(AbcDecimal) ? other.value : AbcDecimal(other).value
|
59
118
|
self.class.new(@value + other_value)
|
60
119
|
end
|
61
120
|
|
121
|
+
# Subtracts another numeric value from this AbcDecimal.
|
122
|
+
#
|
123
|
+
# @param other [AbcDecimal, Numeric] The value to subtract from this AbcDecimal.
|
124
|
+
# @return [AbcDecimal] A new AbcDecimal representing the result of the subtraction.
|
62
125
|
def -(other)
|
63
126
|
other_value = other.is_a?(AbcDecimal) ? other.value : AbcDecimal(other).value
|
64
127
|
self.class.new(@value - other_value)
|
65
128
|
end
|
66
129
|
|
130
|
+
# Multiplies this AbcDecimal by another value.
|
131
|
+
#
|
132
|
+
# @param other [Object] The value to multiply by. If not an AbcDecimal, it will be converted to one.
|
133
|
+
# @return [AbcDecimal] A new AbcDecimal instance representing the product of this decimal and the other value.
|
134
|
+
# @example
|
135
|
+
# dec1 = AbcDecimal.new(5)
|
136
|
+
# dec2 = AbcDecimal.new(2)
|
137
|
+
# result = dec1 * dec2 # => AbcDecimal representing 10
|
138
|
+
#
|
139
|
+
# # With a non-AbcDecimal value
|
140
|
+
# result = dec1 * 3 # => AbcDecimal representing 15
|
67
141
|
def *(other)
|
68
142
|
other_value = other.is_a?(AbcDecimal) ? other.value : AbcDecimal(other).value
|
69
143
|
self.class.new(@value * other_value)
|
70
144
|
end
|
71
145
|
|
146
|
+
# Divides this decimal by another value.
|
147
|
+
#
|
148
|
+
# @param other [Numeric, AbcDecimal] The divisor, which can be an AbcDecimal instance or any numeric value
|
149
|
+
# @return [AbcDecimal] A new AbcDecimal representing the result of the division
|
150
|
+
# @example
|
151
|
+
# decimal = AbcDecimal.new(10)
|
152
|
+
# result = decimal / 2
|
153
|
+
# # => AbcDecimal.new(5)
|
72
154
|
def /(other)
|
73
155
|
other_value = other.is_a?(AbcDecimal) ? other.value : AbcDecimal(other).value
|
74
156
|
self.class.new(@value / other_value)
|
75
157
|
end
|
76
158
|
|
159
|
+
# Performs modulo operation with another value.
|
160
|
+
#
|
161
|
+
# @param other [Numeric, AbcDecimal] The divisor for the modulo operation
|
162
|
+
# @return [AbcDecimal] A new AbcDecimal containing the remainder after division
|
77
163
|
def %(other)
|
78
164
|
other_value = other.is_a?(AbcDecimal) ? other.value : AbcDecimal(other).value
|
79
165
|
self.class.new(@value % other_value)
|
80
166
|
end
|
81
167
|
|
168
|
+
# Constrains the value to be between the specified minimum and maximum values.
|
169
|
+
#
|
170
|
+
# @param min [Numeric, AbcDecimal] The minimum value to clamp to
|
171
|
+
# @param max [Numeric, AbcDecimal] The maximum value to clamp to
|
172
|
+
# @return [AbcDecimal] A new AbcDecimal within the specified range
|
173
|
+
# @example
|
174
|
+
# AbcDecimal(5).clamp(0, 10) # => 5
|
175
|
+
# AbcDecimal(15).clamp(0, 10) # => 10
|
176
|
+
# AbcDecimal(-5).clamp(0, 10) # => 0
|
82
177
|
def clamp(min,max)
|
83
178
|
@value.clamp(AbcDecimal(min),AbcDecimal(max))
|
84
179
|
end
|
85
180
|
|
181
|
+
# Raises self to the power of another value.
|
182
|
+
# This method handles different input types, including Rational values and
|
183
|
+
# other AbcDecimal instances.
|
184
|
+
#
|
185
|
+
# @param other [Numeric, Rational, AbcDecimal] The exponent to raise this value to
|
186
|
+
# @return [AbcDecimal] A new AbcDecimal representing self raised to the power of other
|
86
187
|
def **(other)
|
87
188
|
if other.is_a?(Rational)
|
88
189
|
self.class.new(@value**other)
|
@@ -92,58 +193,137 @@ module Abachrome
|
|
92
193
|
end
|
93
194
|
end
|
94
195
|
|
196
|
+
# Allows for mixed arithmetic operations between AbcDecimal and other numeric types.
|
197
|
+
#
|
198
|
+
# @param other [Numeric] The other number to be coerced into an AbcDecimal object
|
199
|
+
# @return [Array<AbcDecimal>] A two-element array containing the coerced value and self,
|
200
|
+
# allowing Ruby to perform arithmetic operations with mixed types
|
95
201
|
def coerce(other)
|
96
202
|
[self.class.new(other), self]
|
97
203
|
end
|
98
204
|
|
205
|
+
# Returns a string representation of the decimal value for inspection purposes.
|
206
|
+
# This method returns a formatted string that includes the class name and
|
207
|
+
# the string representation of the decimal value itself.
|
208
|
+
#
|
209
|
+
# @return [String] A string in the format "ClassName('value')"
|
99
210
|
def inspect
|
100
211
|
"#{self.class}('#{self}')"
|
101
212
|
end
|
102
213
|
|
214
|
+
# Compares this decimal value with another value for equality.
|
215
|
+
# Attempts to convert the other value to an AbcDecimal if it isn't one already.
|
216
|
+
#
|
217
|
+
# @param other [Object] The value to compare against this AbcDecimal
|
218
|
+
# @return [Boolean] True if the values are equal, false otherwise
|
103
219
|
def ==(other)
|
104
220
|
@value == (other.is_a?(AbcDecimal) ? other.value : AbcDecimal(other).value)
|
105
221
|
end
|
106
222
|
|
223
|
+
# Compares this AbcDecimal instance with another AbcDecimal or a value that can be
|
224
|
+
# converted to an AbcDecimal.
|
225
|
+
#
|
226
|
+
# @param other [Object] The value to compare with this AbcDecimal.
|
227
|
+
# If not an AbcDecimal, it will be converted using AbcDecimal().
|
228
|
+
# @return [Integer, nil] Returns -1 if self is less than other,
|
229
|
+
# 0 if they are equal,
|
230
|
+
# 1 if self is greater than other,
|
231
|
+
# or nil if the comparison is not possible.
|
107
232
|
def <=>(other)
|
108
233
|
@value <=> (other.is_a?(AbcDecimal) ? other.value : AbcDecimal(other).value)
|
109
234
|
end
|
110
235
|
|
236
|
+
# Compares this decimal with another value.
|
237
|
+
#
|
238
|
+
# @param other [Object] The value to compare with. Can be an AbcDecimal or any value
|
239
|
+
# convertible to AbcDecimal
|
240
|
+
# @return [Boolean] true if this decimal is greater than the other value, false otherwise
|
111
241
|
def >(other)
|
112
242
|
@value > (other.is_a?(AbcDecimal) ? other.value : AbcDecimal(other).value)
|
113
243
|
end
|
114
244
|
|
245
|
+
# Compares this decimal value with another value.
|
246
|
+
#
|
247
|
+
# @param other [Object] The value to compare against. If not an AbcDecimal,
|
248
|
+
# it will be converted to one.
|
249
|
+
# @return [Boolean] true if this decimal is greater than or equal to the other value,
|
250
|
+
# false otherwise.
|
115
251
|
def >=(other)
|
116
252
|
@value >= (other.is_a?(AbcDecimal) ? other.value : AbcDecimal(other).value)
|
117
253
|
end
|
118
254
|
|
255
|
+
# Compares this decimal with another value.
|
256
|
+
#
|
257
|
+
# @param other [Object] The value to compare with. Will be coerced to AbcDecimal if not already an instance.
|
258
|
+
# @return [Boolean] true if this decimal is less than the other value, false otherwise.
|
259
|
+
# @example
|
260
|
+
# dec1 = AbcDecimal.new(1.5)
|
261
|
+
# dec2 = AbcDecimal.new(2.0)
|
262
|
+
# dec1 < dec2 #=> true
|
263
|
+
# dec1 < 2.0 #=> true
|
119
264
|
def <(other)
|
120
265
|
@value < (other.is_a?(AbcDecimal) ? other.value : AbcDecimal(other).value)
|
121
266
|
end
|
122
267
|
|
268
|
+
# Compares this AbcDecimal with another value.
|
269
|
+
#
|
270
|
+
# @param other [AbcDecimal, Numeric] The value to compare with. If not an AbcDecimal,
|
271
|
+
# it will be converted to one.
|
272
|
+
# @return [Boolean] true if this AbcDecimal is less than or equal to the other value,
|
273
|
+
# false otherwise.
|
123
274
|
def <=(other)
|
124
275
|
@value <= (other.is_a?(AbcDecimal) ? other.value : AbcDecimal(other).value)
|
125
276
|
end
|
126
277
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
278
|
+
# @overload round(*args)
|
279
|
+
# Rounds this decimal to a specified precision.
|
280
|
+
#
|
281
|
+
# @param args [Array] Arguments to be passed to BigDecimal#round. Can include
|
282
|
+
# the number of decimal places to round to and the rounding mode.
|
283
|
+
# @return [AbcDecimal] A new AbcDecimal instance with the rounded value
|
284
|
+
# @example Round to 2 decimal places
|
285
|
+
# decimal = AbcDecimal(3.14159)
|
286
|
+
# decimal.round(2) #=> 3.14
|
287
|
+
# @example Round with specific rounding mode
|
288
|
+
# decimal = AbcDecimal(3.5)
|
289
|
+
# decimal.round(0, half: :up) #=> 4
|
131
290
|
def round(*args)
|
132
291
|
AbcDecimal(@value.round(*args))
|
133
292
|
end
|
134
293
|
|
294
|
+
# Returns the absolute value (magnitude) of the decimal number.
|
295
|
+
#
|
296
|
+
# Wraps BigDecimal#abs to ensure return values are properly converted to AbcDecimal.
|
297
|
+
#
|
298
|
+
# @param args [Array] Optional arguments to pass to BigDecimal#abs
|
299
|
+
# @return [AbcDecimal] The absolute value of the decimal number
|
135
300
|
def abs(*args)
|
136
301
|
AbcDecimal(@value.abs(*args))
|
137
302
|
end
|
138
303
|
|
304
|
+
# Returns the square root of the AbcDecimal value.
|
305
|
+
# Calculates the square root by using Ruby's built-in Math.sqrt function
|
306
|
+
# and converting the result back to an AbcDecimal.
|
307
|
+
#
|
308
|
+
# @return [AbcDecimal] A new AbcDecimal representing the square root of the value
|
139
309
|
def sqrt
|
140
310
|
AbcDecimal(Math.sqrt(@value))
|
141
311
|
end
|
142
312
|
|
313
|
+
# Returns true if the internal value is negative, false otherwise.
|
314
|
+
#
|
315
|
+
# @return [Boolean] true if the value is negative, false otherwise
|
143
316
|
def negative?
|
144
317
|
@value.negative?
|
145
318
|
end
|
146
319
|
|
320
|
+
# Calculates the arctangent of y/x using the signs of the arguments to determine the quadrant.
|
321
|
+
# Unlike the standard Math.atan2, this method accepts AbcDecimal objects or any values
|
322
|
+
# that can be converted to AbcDecimal.
|
323
|
+
#
|
324
|
+
# @param y [AbcDecimal, Numeric] The y coordinate
|
325
|
+
# @param x [AbcDecimal, Numeric] The x coordinate
|
326
|
+
# @return [AbcDecimal] The angle in radians between the positive x-axis and the ray to the point (x,y)
|
147
327
|
def self.atan2(y, x)
|
148
328
|
y_value = y.is_a?(AbcDecimal) ? y.value : AbcDecimal(y).value
|
149
329
|
x_value = x.is_a?(AbcDecimal) ? x.value : AbcDecimal(x).value
|
@@ -152,10 +332,24 @@ module Abachrome
|
|
152
332
|
end
|
153
333
|
end
|
154
334
|
|
335
|
+
# Creates a new AbcDecimal instance.
|
336
|
+
#
|
337
|
+
# This is a convenience method that allows creating AbcDecimal objects
|
338
|
+
# without explicitly referencing the Abachrome namespace.
|
339
|
+
#
|
340
|
+
# @param args [Array] Arguments to pass to the AbcDecimal constructor
|
341
|
+
# @return [Abachrome::AbcDecimal] A new AbcDecimal instance
|
155
342
|
def AbcDecimal(*args)
|
156
343
|
Abachrome::AbcDecimal.new(*args)
|
157
344
|
end
|
158
345
|
|
346
|
+
# Creates a new AbcDecimal instance.
|
347
|
+
#
|
348
|
+
# @param args [Array] Arguments to pass to AbcDecimal.new
|
349
|
+
# @return [Abachrome::AbcDecimal] A new AbcDecimal instance
|
350
|
+
# @example
|
351
|
+
# AD(3.14) # => #<Abachrome::AbcDecimal:0x... @value=3.14>
|
352
|
+
# AD("2.718") # => #<Abachrome::AbcDecimal:0x... @value=2.718>
|
159
353
|
def AD(*args)
|
160
354
|
Abachrome::AbcDecimal.new(*args)
|
161
355
|
end
|