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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +3 -0
  3. data/README.md +10 -0
  4. data/Rakefile +15 -0
  5. data/devenv.lock +88 -17
  6. data/devenv.nix +2 -1
  7. data/devenv.yaml +5 -12
  8. data/lib/abachrome/abc_decimal.rb +201 -7
  9. data/lib/abachrome/color.rb +88 -1
  10. data/lib/abachrome/color_mixins/blend.rb +53 -2
  11. data/lib/abachrome/color_mixins/lighten.rb +49 -2
  12. data/lib/abachrome/color_mixins/to_colorspace.rb +67 -2
  13. data/lib/abachrome/color_mixins/to_lrgb.rb +70 -2
  14. data/lib/abachrome/color_mixins/to_oklab.rb +67 -2
  15. data/lib/abachrome/color_mixins/to_oklch.rb +60 -2
  16. data/lib/abachrome/color_mixins/to_srgb.rb +77 -2
  17. data/lib/abachrome/color_models/hsv.rb +25 -2
  18. data/lib/abachrome/color_models/lms.rb +34 -0
  19. data/lib/abachrome/color_models/oklab.rb +19 -2
  20. data/lib/abachrome/color_models/oklch.rb +42 -2
  21. data/lib/abachrome/color_models/rgb.rb +28 -2
  22. data/lib/abachrome/color_models/xyz.rb +28 -0
  23. data/lib/abachrome/color_space.rb +88 -2
  24. data/lib/abachrome/converter.rb +56 -2
  25. data/lib/abachrome/converters/base.rb +69 -2
  26. data/lib/abachrome/converters/lms_to_lrgb.rb +36 -0
  27. data/lib/abachrome/converters/lms_to_srgb.rb +23 -0
  28. data/lib/abachrome/converters/lms_to_xyz.rb +30 -0
  29. data/lib/abachrome/converters/lrgb_to_lms.rb +0 -0
  30. data/lib/abachrome/converters/lrgb_to_oklab.rb +28 -2
  31. data/lib/abachrome/converters/lrgb_to_srgb.rb +27 -2
  32. data/lib/abachrome/converters/lrgb_to_xyz.rb +29 -0
  33. data/lib/abachrome/converters/oklab_to_lms.rb +41 -0
  34. data/lib/abachrome/converters/oklab_to_lrgb.rb +56 -29
  35. data/lib/abachrome/converters/oklab_to_oklch.rb +31 -2
  36. data/lib/abachrome/converters/oklab_to_srgb.rb +27 -2
  37. data/lib/abachrome/converters/oklch_to_lrgb.rb +66 -6
  38. data/lib/abachrome/converters/oklch_to_oklab.rb +29 -4
  39. data/lib/abachrome/converters/oklch_to_srgb.rb +26 -2
  40. data/lib/abachrome/converters/oklch_to_xyz.rb +66 -0
  41. data/lib/abachrome/converters/srgb_to_lrgb.rb +26 -2
  42. data/lib/abachrome/converters/srgb_to_oklab.rb +28 -2
  43. data/lib/abachrome/converters/srgb_to_oklch.rb +27 -2
  44. data/lib/abachrome/converters/xyz_to_lms.rb +30 -0
  45. data/lib/abachrome/converters/xyz_to_oklab.rb +38 -0
  46. data/lib/abachrome/gamut/base.rb +2 -2
  47. data/lib/abachrome/gamut/p3.rb +2 -2
  48. data/lib/abachrome/gamut/rec2020.rb +2 -2
  49. data/lib/abachrome/gamut/srgb.rb +20 -2
  50. data/lib/abachrome/illuminants/base.rb +2 -2
  51. data/lib/abachrome/illuminants/d50.rb +2 -2
  52. data/lib/abachrome/illuminants/d55.rb +2 -2
  53. data/lib/abachrome/illuminants/d65.rb +2 -2
  54. data/lib/abachrome/illuminants/d75.rb +2 -2
  55. data/lib/abachrome/named/css.rb +149 -158
  56. data/lib/abachrome/outputs/css.rb +2 -2
  57. data/lib/abachrome/palette.rb +112 -2
  58. data/lib/abachrome/palette_mixins/interpolate.rb +20 -2
  59. data/lib/abachrome/palette_mixins/resample.rb +2 -2
  60. data/lib/abachrome/palette_mixins/stretch_luminance.rb +2 -2
  61. data/lib/abachrome/parsers/hex.rb +2 -2
  62. data/lib/abachrome/to_abcd.rb +10 -2
  63. data/lib/abachrome/version.rb +2 -2
  64. data/lib/abachrome.rb +78 -2
  65. data/logo.png +0 -0
  66. data/logo.webp +0 -0
  67. metadata +26 -67
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 88fab17313d84aca8190acb8c108af84d1129ce9e240353e2afec2225fc5aa37
4
- data.tar.gz: f98569f28bf4a1fa967f43bc8538de967e7dfa34f40f22749099b51b8b7512ac
3
+ metadata.gz: a33e1980f4b275bc95646259d6c71b01715d2a77f019828b2c05ea98b24826d8
4
+ data.tar.gz: 896c1479708b87a3862bc28bdbb1959aefc0bcb3619604980096f34ed7dd07e9
5
5
  SHA512:
6
- metadata.gz: 1df4f29f6700b0488656b3a7c7dc22a1aa72cfab8d6a11cfc89363acd57488a39e9ded2d79f397c2727e7cbb5a2b203f41975cdbc891de3028435b3d40be1915
7
- data.tar.gz: d31cb69b1412ab7e5c06349ce2e44b9b1ecf1324d2b862d26e19adbf496bfeeec0c1195382bf5f4092d0fe12407e4d9d9024c7fe1065e52b3b353f94e55a79a4
6
+ metadata.gz: e6923ce91856cf5261cc52613c1e6eacd70e0fb9c3f7a1a2fe4f248b04ea326530ca8e6b56e84f07d4cc7f663ed61fb469c35ab1247ca40f6efeeb22b28952c3
7
+ data.tar.gz: db5e02222ce2f664086a1deb5b2a4cf878c3e285c9053b652935b45688cac1d64286987b5bca0a02a0a8a884110996a2f071d283ac5df3b94f8d8722a620aef7
data/.envrc ADDED
@@ -0,0 +1,3 @@
1
+ source_url "https://raw.githubusercontent.com/cachix/devenv/95f329d49a8a5289d31e0982652f7058a189bfca/direnvrc" "sha256-d+8cBpDfDBj41inrADaJt+bDWhOktwslgoP5YiGJ1v0="
2
+
3
+ use devenv
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
+ ![Abachrome Logo](logo.png)
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": 1739172804,
6
+ "lastModified": 1749202057,
7
7
  "owner": "cachix",
8
8
  "repo": "devenv",
9
- "rev": "f8be0ed0141abab89cefb20d3d375740671fbee1",
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": 1733328505,
22
+ "lastModified": 1747046372,
23
23
  "owner": "edolstra",
24
24
  "repo": "flake-compat",
25
- "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec",
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
- "pre-commit-hooks",
90
+ "git-hooks",
38
91
  "nixpkgs"
39
92
  ]
40
93
  },
@@ -53,10 +106,10 @@
53
106
  },
54
107
  "nixpkgs": {
55
108
  "locked": {
56
- "lastModified": 1733477122,
109
+ "lastModified": 1746807397,
57
110
  "owner": "cachix",
58
111
  "repo": "devenv-nixpkgs",
59
- "rev": "7bd9e84d0452f6d2e63b6e6da29fe73fac951857",
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
- "pre-commit-hooks": {
122
+ "nixpkgs-ruby": {
70
123
  "inputs": {
71
- "flake-compat": "flake-compat",
72
- "gitignore": "gitignore",
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": 1737465171,
79
- "owner": "cachix",
80
- "repo": "pre-commit-hooks.nix",
81
- "rev": "9364dc02281ce2d37a1f55b6e51f7c0f65a75f17",
131
+ "lastModified": 1747288354,
132
+ "owner": "bobvanderlinden",
133
+ "repo": "nixpkgs-ruby",
134
+ "rev": "5d7598f3059fff0cbd0dc4756f9d87f8cb7f3f7c",
82
135
  "type": "github"
83
136
  },
84
137
  "original": {
85
- "owner": "cachix",
86
- "repo": "pre-commit-hooks.nix",
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
- "pre-commit-hooks": "pre-commit-hooks"
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 pkgs.ncurses pkgs.asciinema pkgs.asciinema-agg];
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
- # If you're using non-OSS software, you can set allowUnfree to true.
7
- # allowUnfree: true
8
-
9
- # If you're willing to use a package that's vulnerable
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
- # frozen_string_literal: true
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, :to_f, :zero?, :nonzero?
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
- def clamp(*args)
128
- AbcDecimal(@value.clamp(*args))
129
- end
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